blob: 142e3a45f2b0dbed0b6f06001ed44d260d381381 [file] [log] [blame]
Aaron Durbin4058d7b2014-08-22 10:24:27 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2014 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Aaron Durbin4058d7b2014-08-22 10:24:27 -050014 */
15
Aaron Durbin4058d7b2014-08-22 10:24:27 -050016#include <arch/io.h>
Julius Werner96195ee2014-10-20 13:25:21 -070017#include <console/console.h>
Aaron Durbin4058d7b2014-08-22 10:24:27 -050018#include <soc/addressmap.h>
Julius Werner96195ee2014-10-20 13:25:21 -070019#include <soc/clk_rst.h>
Aaron Durbin4058d7b2014-08-22 10:24:27 -050020#include <soc/cpu.h>
Julius Werner96195ee2014-10-20 13:25:21 -070021#include <soc/pmc.h>
Aaron Durbin4058d7b2014-08-22 10:24:27 -050022
23#define EVP_CPU_RESET_VECTOR (void *)(uintptr_t)(TEGRA_EVP_BASE + 0x100)
Aaron Durbin4058d7b2014-08-22 10:24:27 -050024#define PMC_REGS (void *)(uintptr_t)(TEGRA_PMC_BASE)
25
26static void enable_core_clocks(int cpu)
27{
Aaron Durbin4058d7b2014-08-22 10:24:27 -050028 const uint32_t cpu0_clocks = CRC_RST_CPUG_CLR_CPU0 |
29 CRC_RST_CPUG_CLR_DBG0 |
30 CRC_RST_CPUG_CLR_CORE0 |
31 CRC_RST_CPUG_CLR_CX0;
32 const uint32_t cpu1_clocks = CRC_RST_CPUG_CLR_CPU1 |
33 CRC_RST_CPUG_CLR_DBG1 |
34 CRC_RST_CPUG_CLR_CORE1 |
35 CRC_RST_CPUG_CLR_CX1;
36
37 /* Clear reset of CPU components. */
38 if (cpu == 0)
Julius Werner2f37bd62015-02-19 14:51:15 -080039 write32(CLK_RST_REG(rst_cpug_cmplx_clr), cpu0_clocks);
Aaron Durbin4058d7b2014-08-22 10:24:27 -050040 else
Julius Werner2f37bd62015-02-19 14:51:15 -080041 write32(CLK_RST_REG(rst_cpug_cmplx_clr), cpu1_clocks);
Aaron Durbin4058d7b2014-08-22 10:24:27 -050042}
43
44static void set_armv8_32bit_reset_vector(uintptr_t entry)
45{
46 void * const evp_cpu_reset_vector = EVP_CPU_RESET_VECTOR;
Julius Werner2f37bd62015-02-19 14:51:15 -080047 write32(evp_cpu_reset_vector, entry);
Aaron Durbin4058d7b2014-08-22 10:24:27 -050048}
49
50static void set_armv8_64bit_reset_vector(uintptr_t entry)
51{
52 struct tegra_pmc_regs * const pmc = PMC_REGS;
53
54 /* Currently assume 32-bit addresses only. */
Julius Werner2f37bd62015-02-19 14:51:15 -080055 write32(&pmc->secure_scratch34, entry);
56 write32(&pmc->secure_scratch35, 0);
Aaron Durbin4058d7b2014-08-22 10:24:27 -050057}
58
Aaron Durbind8060902014-11-25 16:47:56 -060059void cpu_prepare_startup(void *entry_64)
Aaron Durbin4058d7b2014-08-22 10:24:27 -050060{
Aaron Durbin4058d7b2014-08-22 10:24:27 -050061 /* Warm reset vector is pulled from the PMC scratch registers. */
62 set_armv8_64bit_reset_vector((uintptr_t)entry_64);
63
64 /*
65 * The Denver cores start in 32-bit mode. Therefore a trampoline
66 * is needed to get into 64-bit mode. Point the cold reset vector
67 * to the traompoline location.
68 */
69 set_armv8_32bit_reset_vector((uintptr_t)reset_entry_32bit);
Aaron Durbind8060902014-11-25 16:47:56 -060070}
Aaron Durbin4058d7b2014-08-22 10:24:27 -050071
Aaron Durbind8060902014-11-25 16:47:56 -060072void start_cpu_silent(int cpu, void *entry_64)
73{
74 cpu_prepare_startup(entry_64);
Aaron Durbin4058d7b2014-08-22 10:24:27 -050075 enable_core_clocks(cpu);
76}
Aaron Durbind8060902014-11-25 16:47:56 -060077
78void start_cpu(int cpu, void *entry_64)
79{
80 printk(BIOS_DEBUG, "Starting CPU%d @ %p trampolining to %p.\n",
81 cpu, reset_entry_32bit, entry_64);
82
83 start_cpu_silent(cpu, entry_64);
84}