diff options
Diffstat (limited to 'src/soc/nvidia/tegra210/cpu.c')
-rw-r--r-- | src/soc/nvidia/tegra210/cpu.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/soc/nvidia/tegra210/cpu.c b/src/soc/nvidia/tegra210/cpu.c new file mode 100644 index 0000000000..6e51a8cdae --- /dev/null +++ b/src/soc/nvidia/tegra210/cpu.c @@ -0,0 +1,79 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc. + */ + +#include <arch/io.h> +#include <assert.h> +#include <console/console.h> +#include <soc/addressmap.h> +#include <soc/clk_rst.h> +#include <soc/cpu.h> +#include <soc/secure_boot.h> + +static void enable_core_clocks(int cpu) +{ + const uint32_t cpu_clocks[CONFIG_MAX_CPUS] = { + [0] = CRC_RST_CPUG_CLR_CPU0 | CRC_RST_CPUG_CLR_DBG0 | + CRC_RST_CPUG_CLR_CORE0 | CRC_RST_CPUG_CLR_CX0, + [1] = CRC_RST_CPUG_CLR_CPU1 | CRC_RST_CPUG_CLR_DBG1 | + CRC_RST_CPUG_CLR_CORE1 | CRC_RST_CPUG_CLR_CX1, + [2] = CRC_RST_CPUG_CLR_CPU2 | CRC_RST_CPUG_CLR_DBG2 | + CRC_RST_CPUG_CLR_CORE2 | CRC_RST_CPUG_CLR_CX2, + [3] = CRC_RST_CPUG_CLR_CPU3 | CRC_RST_CPUG_CLR_DBG3 | + CRC_RST_CPUG_CLR_CORE3 | CRC_RST_CPUG_CLR_CX3, + }; + + assert (cpu < CONFIG_MAX_CPUS); + + /* Clear reset of CPU components. */ + write32(CLK_RST_REG(rst_cpug_cmplx_clr), cpu_clocks[cpu]); +} + +void cpu_prepare_startup(void *entry_64) +{ + struct tegra_secure_boot *sb = + (struct tegra_secure_boot *)TEGRA_SB_BASE; + + /* + * T210 TRM, section 12.4.4.2: "SB_AA64_RESET_LOW_0[0:0] is used to + * decide between CPU boot up in AARCH32 (=0) or AARCH64 (=1) mode. + * This bit .. is sampled only during 'cold reset of CPU'. Before the + * CPU is powered up, the CPU reset vector is loaded in + * EVP_CPU_REST_VECTOR_0 for 32-bit boot mode .... However, the CPU + * decides to boot in 32-/64-bit mode based on + * SB_AA64_RESET_LOW_0[0:0]. If this bit is set (=1), the CPU boots in + * 64-bit mode using SB_AA64_RESET_* as the reset address. If this bit + * is clear (=0), CPU boots in 32-bit mode using EVP_CPU_RESET_VECTOR." + */ + + write32(&sb->sb_aa64_reset_low, (uintptr_t)entry_64); + setbits_le32(&sb->sb_aa64_reset_low, 1); + write32(&sb->sb_aa64_reset_high, 0); +} + +void start_cpu_silent(int cpu, void *entry_64) +{ + cpu_prepare_startup(entry_64); + enable_core_clocks(cpu); +} + +void start_cpu(int cpu, void *entry_64) +{ + printk(BIOS_DEBUG, "Starting CPU%d @ %p.\n", cpu, entry_64); + start_cpu_silent(cpu, entry_64); +} |