blob: cc1e284b668cbf1195ad8171bebbe0c1c7375ccc [file] [log] [blame]
Patrick Georgi40a3e322015-06-22 19:41:29 +02001/*
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.
Patrick Georgi40a3e322015-06-22 19:41:29 +020014 */
15
Kyösti Mälkki13f66502019-03-03 08:01:05 +020016#include <device/mmio.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +020017#include <console/console.h>
18#include <soc/addressmap.h>
19#include <soc/clock.h>
20#include <soc/clk_rst.h>
21#include <soc/ccplex.h>
22#include <soc/cpu.h>
23#include <soc/flow.h>
24#include <soc/mc.h>
25#include <soc/pmc.h>
26#include <soc/power.h>
27#include <soc/romstage.h>
28#include <string.h>
29#include <timer.h>
30
31#define PMC_REGS (void *)(uintptr_t)(TEGRA_PMC_BASE)
32
33static void enable_cpu_clocks(void)
34{
35 clock_enable(CLK_ENB_CPU, 0, 0, SET_CLK_ENB_CPUG_ENABLE |
36 SET_CLK_ENB_CPULP_ENABLE, 0, 0, 0);
37}
38
39static void enable_cpu_power_partitions(void)
40{
41 /* Bring up fast cluster, non-CPU, CPU0, CPU1, CPU2 and CPU3 parts. */
42 power_ungate_partition(POWER_PARTID_CRAIL);
43 power_ungate_partition(POWER_PARTID_C0NC);
44 power_ungate_partition(POWER_PARTID_CE0);
Patrick Georgi40a3e322015-06-22 19:41:29 +020045
46 if (IS_ENABLED(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE)) {
47 /*
48 * Deassert reset signal of all the secondary CPUs.
49 * PMC and flow controller will take over the power sequence
50 * controller in the ATF.
51 */
52 uint32_t reg = CRC_RST_CPUG_CLR_CPU1 | CRC_RST_CPUG_CLR_DBG1 |
53 CRC_RST_CPUG_CLR_CORE1 | CRC_RST_CPUG_CLR_CX1 |
54 CRC_RST_CPUG_CLR_CPU2 | CRC_RST_CPUG_CLR_DBG2 |
55 CRC_RST_CPUG_CLR_CORE2 | CRC_RST_CPUG_CLR_CX2 |
56 CRC_RST_CPUG_CLR_CPU3 | CRC_RST_CPUG_CLR_DBG3 |
57 CRC_RST_CPUG_CLR_CORE3 | CRC_RST_CPUG_CLR_CX3;
58 write32(CLK_RST_REG(rst_cpug_cmplx_clr), reg);
59 }
60}
61
62static void request_ram_repair(void)
63{
64 struct flow_ctlr * const flow = (void *)(uintptr_t)TEGRA_FLOW_BASE;
65 const uint32_t req = 1 << 0;
66 const uint32_t sts = 1 << 1;
67 uint32_t reg;
68 struct stopwatch sw;
69
70 printk(BIOS_DEBUG, "Requesting RAM repair.\n");
71
72 stopwatch_init(&sw);
73
Elyes HAOUAS038e7242016-07-29 18:31:16 +020074 /* Perform RAM repair */
Patrick Georgi40a3e322015-06-22 19:41:29 +020075 reg = read32(&flow->ram_repair);
76 reg |= req;
77 write32(&flow->ram_repair, reg);
78 while ((read32(&flow->ram_repair) & sts) != sts)
79 ;
80
81 printk(BIOS_DEBUG, "RAM repair complete in %ld usecs.\n",
82 stopwatch_duration_usecs(&sw));
83}
84
Yen Lincad9e7a2015-05-06 13:56:50 -070085static void set_cpu_ack_width(uint32_t val)
86{
87 uint32_t reg;
88
89 reg = read32(CLK_RST_REG(cpu_softrst_ctrl2));
90 reg &= ~CAR2PMC_CPU_ACK_WIDTH_MASK;
91 reg |= val;
92 write32(CLK_RST_REG(cpu_softrst_ctrl2), reg);
93}
94
Patrick Georgi40a3e322015-06-22 19:41:29 +020095void ccplex_cpu_prepare(void)
96{
97 enable_cpu_clocks();
Yen Lincad9e7a2015-05-06 13:56:50 -070098
99 /*
100 * The POR value of CAR2PMC_CPU_ACK_WIDTH is 0x200.
101 * The recommended value is 0.
102 */
103 set_cpu_ack_width(0);
104
Patrick Georgi40a3e322015-06-22 19:41:29 +0200105 enable_cpu_power_partitions();
106
107 mainboard_configure_pmc();
108 mainboard_enable_vdd_cpu();
109
110 request_ram_repair();
111}
112
113static void start_common_clocks(void)
114{
115 /* Clear fast CPU partition reset. */
116 write32(CLK_RST_REG(rst_cpug_cmplx_clr), CRC_RST_CPUG_CLR_NONCPU);
117
118 /* Clear reset of L2 and CoreSight components. */
119 write32(CLK_RST_REG(rst_cpug_cmplx_clr),
120 CRC_RST_CPUG_CLR_L2 | CRC_RST_CPUG_CLR_PDBG);
121}
122
123void ccplex_cpu_start(void *entry_addr)
124{
125 /* Enable common clocks for the shared resources between the cores. */
126 start_common_clocks();
127
128 start_cpu(0, entry_addr);
129}