Angel Pons | a2ee761 | 2020-04-04 18:51:15 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Patrick Georgi | 40a3e32 | 2015-06-22 19:41:29 +0200 | [diff] [blame] | 2 | |
Kyösti Mälkki | 13f6650 | 2019-03-03 08:01:05 +0200 | [diff] [blame] | 3 | #include <device/mmio.h> |
Patrick Georgi | 40a3e32 | 2015-06-22 19:41:29 +0200 | [diff] [blame] | 4 | #include <assert.h> |
| 5 | #include <console/console.h> |
| 6 | #include <soc/addressmap.h> |
| 7 | #include <soc/clk_rst.h> |
| 8 | #include <soc/cpu.h> |
| 9 | #include <soc/secure_boot.h> |
| 10 | |
| 11 | static void enable_core_clocks(int cpu) |
| 12 | { |
Julius Werner | 7dcf9d5 | 2015-10-16 13:10:02 -0700 | [diff] [blame] | 13 | const uint32_t cpu_clocks[] = { |
Patrick Georgi | 40a3e32 | 2015-06-22 19:41:29 +0200 | [diff] [blame] | 14 | [0] = CRC_RST_CPUG_CLR_CPU0 | CRC_RST_CPUG_CLR_DBG0 | |
| 15 | CRC_RST_CPUG_CLR_CORE0 | CRC_RST_CPUG_CLR_CX0, |
| 16 | [1] = CRC_RST_CPUG_CLR_CPU1 | CRC_RST_CPUG_CLR_DBG1 | |
| 17 | CRC_RST_CPUG_CLR_CORE1 | CRC_RST_CPUG_CLR_CX1, |
| 18 | [2] = CRC_RST_CPUG_CLR_CPU2 | CRC_RST_CPUG_CLR_DBG2 | |
| 19 | CRC_RST_CPUG_CLR_CORE2 | CRC_RST_CPUG_CLR_CX2, |
| 20 | [3] = CRC_RST_CPUG_CLR_CPU3 | CRC_RST_CPUG_CLR_DBG3 | |
| 21 | CRC_RST_CPUG_CLR_CORE3 | CRC_RST_CPUG_CLR_CX3, |
| 22 | }; |
| 23 | |
Elyes Haouas | 98a9b34 | 2023-09-10 10:39:11 +0200 | [diff] [blame] | 24 | assert(cpu < CONFIG_MAX_CPUS); |
Patrick Georgi | 40a3e32 | 2015-06-22 19:41:29 +0200 | [diff] [blame] | 25 | |
| 26 | /* Clear reset of CPU components. */ |
| 27 | write32(CLK_RST_REG(rst_cpug_cmplx_clr), cpu_clocks[cpu]); |
| 28 | } |
| 29 | |
| 30 | void cpu_prepare_startup(void *entry_64) |
| 31 | { |
| 32 | struct tegra_secure_boot *sb = |
| 33 | (struct tegra_secure_boot *)TEGRA_SB_BASE; |
| 34 | |
| 35 | /* |
| 36 | * T210 TRM, section 12.4.4.2: "SB_AA64_RESET_LOW_0[0:0] is used to |
| 37 | * decide between CPU boot up in AARCH32 (=0) or AARCH64 (=1) mode. |
| 38 | * This bit .. is sampled only during 'cold reset of CPU'. Before the |
| 39 | * CPU is powered up, the CPU reset vector is loaded in |
| 40 | * EVP_CPU_REST_VECTOR_0 for 32-bit boot mode .... However, the CPU |
| 41 | * decides to boot in 32-/64-bit mode based on |
| 42 | * SB_AA64_RESET_LOW_0[0:0]. If this bit is set (=1), the CPU boots in |
| 43 | * 64-bit mode using SB_AA64_RESET_* as the reset address. If this bit |
| 44 | * is clear (=0), CPU boots in 32-bit mode using EVP_CPU_RESET_VECTOR." |
| 45 | */ |
| 46 | |
| 47 | write32(&sb->sb_aa64_reset_low, (uintptr_t)entry_64); |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 48 | setbits32(&sb->sb_aa64_reset_low, 1); |
Patrick Georgi | 40a3e32 | 2015-06-22 19:41:29 +0200 | [diff] [blame] | 49 | write32(&sb->sb_aa64_reset_high, 0); |
| 50 | } |
| 51 | |
| 52 | void start_cpu_silent(int cpu, void *entry_64) |
| 53 | { |
| 54 | cpu_prepare_startup(entry_64); |
| 55 | enable_core_clocks(cpu); |
| 56 | } |
| 57 | |
| 58 | void start_cpu(int cpu, void *entry_64) |
| 59 | { |
| 60 | printk(BIOS_DEBUG, "Starting CPU%d @ %p.\n", cpu, entry_64); |
| 61 | start_cpu_silent(cpu, entry_64); |
| 62 | } |