blob: 13e9489161e5bec38b72e83b0166814b0ab170b4 [file] [log] [blame]
Angel Pons1ddb8942020-04-04 18:51:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Hung-Te Lin0682cfe2013-08-06 20:37:55 +08002
Julius Werner80af4422014-10-20 13:18:56 -07003#include <arch/cpu.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02004#include <device/mmio.h>
Julius Werner80af4422014-10-20 13:18:56 -07005#include <soc/cpu.h>
6#include <soc/power.h>
Julius Wernerfa938c72013-08-29 14:17:36 -07007#include <string.h>
Hung-Te Lin0682cfe2013-08-06 20:37:55 +08008#include <types.h>
Hung-Te Lin0682cfe2013-08-06 20:37:55 +08009
10/* ACTLR, L2CTLR L2ACTLR constants used in SMP core power up. */
11
12#define ACTLR_SMP (1 << 6)
13
14#define L2CTLR_ECC_PARITY (1 << 21)
15#define L2CTLR_DATA_RAM_LATENCY_MASK (7 << 0)
16#define L2CTLR_TAG_RAM_LATENCY_MASK (7 << 6)
17#define L2CTLR_DATA_RAM_LATENCY_CYCLES_3 (2 << 0)
18#define L2CTLR_TAG_RAM_LATENCY_CYCLES_3 (2 << 6)
19
20#define L2ACTLR_DISABLE_CLEAN_EVICT_PUSH_EXTERNAL (1 << 3)
21#define L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT (1 << 7)
22#define L2ACTLR_FORCE_L2_LOGIC_CLOCK_ENABLE_ACTIVE (1 << 27)
23
24/* Part number in CPU ID (MPIDR). */
25#define PART_NUMBER_CORTEX_A15 (0xc0f)
26
27/* State of CPU cores in Exynos 5420. */
28#define CORE_STATE_RESET (1 << 0)
29#define CORE_STATE_SECONDARY_RESET (1 << 1)
30#define CORE_STATE_SWITCH_CLUSTER (1 << 4)
31
32/* The default address to re-power on a code. */
Elyes HAOUAS39303d52018-07-08 12:40:45 +020033#define CORE_RESET_INIT_ADDRESS ((void *)0x00000000)
Hung-Te Lin0682cfe2013-08-06 20:37:55 +080034
35/* Vectors in BL1 (0x02020000 = base of iRAM). */
Elyes HAOUAS39303d52018-07-08 12:40:45 +020036#define VECTOR_CORE_SEV_HANDLER ((void *)(intptr_t)0x02020004)
37#define VECTOR_LOW_POWER_FLAG ((void *)(intptr_t)0x02020028)
38#define VECTOR_LOW_POWER_ADDRESS ((void *)(intptr_t)0x0202002C)
Hung-Te Lin0682cfe2013-08-06 20:37:55 +080039
40/* The data structure for the "CPU state" memory page (shared with kernel)
41 * controlling cores in active cluster. Kernel will put starting address for one
42 * core in "hotplug_address" before power on. Note the address is hard-coded in
43 * kernel (EXYNOS5420_PA_SYSRAM_NS = 0x02073000). */
44volatile struct exynos5420_cpu_states
45{
46 uint32_t _reserved[2]; /* RESV, +0x00 */
47 uint32_t resume_address; /* REG0, +0x08 */
48 uint32_t resume_flag; /* REG1, +0x0C */
49 uint32_t _reg2; /* REG2, +0x10 */
50 uint32_t _reg3; /* REG3, +0x14 */
51 uint32_t switch_address; /* REG4, +0x18, cluster switching */
52 uint32_t hotplug_address; /* REG5, +0x1C, core hotplug */
53 uint32_t _reg6; /* REG6, +0x20 */
54 uint32_t c2_address; /* REG7, +0x24, C2 state change */
55
56 /* Managed per core status for active cluster, offset: +0x28~0x38 */
57 uint32_t cpu_states[4];
58
59 /* Managed per core GIC status for active cluster, offset: 0x38~0x48 */
60 uint32_t cpu_gic_states[4];
61} *exynos_cpu_states = (volatile struct exynos5420_cpu_states*)0x02073000;
62
63/* When leaving core handlers and jump to hot-plug address (or cluster
64 * switching), we are not sure if the destination is Thumb or ARM mode.
65 * So a BX command is required.
66 */
67inline static void jump_bx(void *address)
68{
69 asm volatile ("bx %0" : : "r"(address));
70 /* never returns. */
71}
72
73/* Extracts arbitrary bits from a 32-bit unsigned int. */
74inline static uint32_t get_bits(uint32_t value, uint32_t start, uint32_t len)
75{
76 return ((value << (sizeof(value) * 8 - len - start)) >>
77 (sizeof(value) * 8 - len));
78}
79
80/* Waits the referenced address to be ready (non-zero) and then jump into it. */
Elyes HAOUAS39303d52018-07-08 12:40:45 +020081static void wait_and_jump(volatile uint32_t *reference)
Hung-Te Lin0682cfe2013-08-06 20:37:55 +080082{
83 while (!*reference) {
84 wfe();
85 }
Elyes HAOUAS39303d52018-07-08 12:40:45 +020086 jump_bx((void *)*reference);
Hung-Te Lin0682cfe2013-08-06 20:37:55 +080087}
88
89/* Configures L2 Control Register to use 3 cycles for DATA/TAG RAM latency. */
90static void configure_l2ctlr(void)
91{
92 uint32_t val;
93
94 val = read_l2ctlr();
95 val &= ~(L2CTLR_DATA_RAM_LATENCY_MASK | L2CTLR_TAG_RAM_LATENCY_MASK);
96 val |= (L2CTLR_DATA_RAM_LATENCY_CYCLES_3 | L2CTLR_TAG_RAM_LATENCY_CYCLES_3 |
97 L2CTLR_ECC_PARITY);
98 write_l2ctlr(val);
99}
100
101/* Configures L2 Auxiliary Control Register for Cortex A15. */
102static void configure_l2actlr(void)
103{
104 uint32_t val;
105
106 val = read_l2actlr();
107 val |= (L2ACTLR_DISABLE_CLEAN_EVICT_PUSH_EXTERNAL |
108 L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT |
109 L2ACTLR_FORCE_L2_LOGIC_CLOCK_ENABLE_ACTIVE);
110 write_l2actlr(val);
111}
112
113/* Initializes the CPU states to reset state. */
114static void init_exynos_cpu_states(void) {
Elyes HAOUAS39303d52018-07-08 12:40:45 +0200115 memset((void *)exynos_cpu_states, 0, sizeof(*exynos_cpu_states));
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800116 exynos_cpu_states->cpu_states[0] = CORE_STATE_RESET;
117 exynos_cpu_states->cpu_states[1] = CORE_STATE_SECONDARY_RESET;
118 exynos_cpu_states->cpu_states[2] = CORE_STATE_SECONDARY_RESET;
119 exynos_cpu_states->cpu_states[3] = CORE_STATE_SECONDARY_RESET;
120}
121
122/*
123 * Ensures that the L2 logic has been used within the previous 256 cycles
124 * before modifying the ACTLR.SMP bit. This is required during boot before
125 * MMU has been enabled, or during a specified reset or power down sequence.
126 */
127static void enable_smp(void)
128{
129 uint32_t actlr, val;
130
131 /* Enable SMP mode */
132 actlr = read_actlr();
133 actlr |= ACTLR_SMP;
134
135 /* Dummy read to assure L2 access */
Julius Werner2f37bd62015-02-19 14:51:15 -0800136 val = read32(&exynos_power->inform0);
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800137 val &= 0;
138 actlr |= val;
139
140 write_actlr(actlr);
141 dsb();
142 isb();
143}
144
145/* Starts the core and jumps to correct location by its state. */
146static void core_start_execution(void)
147{
148 u32 cpu_id, cpu_state;
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800149
150 enable_smp();
Julius Werner985ff362013-09-18 14:39:50 -0700151 set_system_mode();
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800152
153 cpu_id = read_mpidr() & 0x3; /* up to 4 processors for one cluster. */
154 cpu_state = exynos_cpu_states->cpu_states[cpu_id];
155
156 if (cpu_state & CORE_STATE_SWITCH_CLUSTER) {
157 wait_and_jump(&exynos_cpu_states->switch_address);
158 /* never returns. */
159 }
160
161 /* Standard Exynos suspend/resume. */
Julius Wernerfa938c72013-08-29 14:17:36 -0700162 if (exynos_power->inform1) {
163 exynos_power->inform1 = 0;
Elyes HAOUAS39303d52018-07-08 12:40:45 +0200164 jump_bx((void *)exynos_power->inform0);
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800165 /* never returns. */
166 }
167
168 if (cpu_state & CORE_STATE_RESET) {
169 /* For Reset, U-Boot jumps to its starting address;
Martin Rothe18e6422017-06-03 20:03:18 -0600170 * on coreboot, seems ok to ignore for now. */
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800171 }
172 wait_and_jump(&exynos_cpu_states->hotplug_address);
173 /* never returns. */
174}
175
176/* The entry point for hotplug-in and cluster switching. */
177static void low_power_start(void)
178{
179 uint32_t sctlr, reg_val;
180
181 /* On warm reset, because iRAM is not cleared, all cores will enter
182 * low_power_start, not the initial address. So we need to check reset
183 * status again, and jump to 0x0 in that case. */
Julius Werner2f37bd62015-02-19 14:51:15 -0800184 reg_val = read32(&exynos_power->spare0);
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800185 if (reg_val != RST_FLAG_VAL) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800186 write32(VECTOR_LOW_POWER_FLAG, 0x0);
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800187 jump_bx(CORE_RESET_INIT_ADDRESS);
Elyes HAOUAS038e7242016-07-29 18:31:16 +0200188 /* restart CPU execution and never returns. */
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800189 }
190
191 /* Workaround for iROM EVT1. A7 core execution may flow into incorrect
192 * path, bypassing first jump address and makes final jump address 0x0,
193 * so we try to make any core set again low_power_start address, if that
194 * becomes zero. */
Julius Werner2f37bd62015-02-19 14:51:15 -0800195 reg_val = read32(VECTOR_CORE_SEV_HANDLER);
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800196 if (reg_val != (intptr_t)low_power_start) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800197 write32(VECTOR_CORE_SEV_HANDLER, (intptr_t)low_power_start);
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800198 dsb();
199 /* ask all cores to power on again. */
200 sev();
201 }
202
Julius Werner985ff362013-09-18 14:39:50 -0700203 set_system_mode();
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800204
205 /* Whenever a Cortex A-15 core powers on, iROM resets its L2 cache
206 * so we need to configure again. */
207 if (get_bits(read_midr(), 4, 12) == PART_NUMBER_CORTEX_A15) {
208 configure_l2ctlr();
209 configure_l2actlr();
210 }
211
212 /* Invalidate L1 & TLB */
213 tlbiall();
214 iciallu();
215
216 /* Disable MMU stuff and caches */
217 sctlr = read_sctlr();
218 sctlr &= ~(SCTLR_V | SCTLR_M | SCTLR_C);
219 sctlr |= (SCTLR_I | SCTLR_Z | SCTLR_A);
220 write_sctlr(sctlr);
221
222 core_start_execution();
223 /* The core should not return. But in order to prevent unexpected
224 * errors, a WFI command will help to put CPU back to idle state. */
225 wfi();
226}
227
228/* Callback to shutdown a core, safe to be set as hot-plug address. */
229static void power_down_core(void)
230{
231 uint32_t mpidr, core_id;
232
233 /* MPIDR: 0~2=ID, 8~11=cluster. On Exynos 5420, cluster will be only 0
234 * or 1. */
235 mpidr = read_mpidr();
236 core_id = get_bits(mpidr, 0, 2) | (get_bits(mpidr, 8, 4) << 2);
237
238 /* Set the status of the core to low.
239 * S5E5420A User Manual, 8.8.1.202, ARM_CORE0_CONFIGURATION, two bits to
240 * control power state in each power down level.
241 */
Julius Werner2f37bd62015-02-19 14:51:15 -0800242 write32(&exynos_power->arm_core[core_id].config, 0x0);
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800243
244 /* S5E5420A User Manual, 8.4.2.5, after ARM_CORE*_CONFIGURATION has been
245 * set to zero, PMU will detect and wait for WFI then run power-down
246 * sequence. */
247 wfi();
248}
249
Martin Roth1fc2ba52014-12-07 14:59:11 -0700250/* Configures the CPU states shared memory page and then shutdown all cores. */
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800251static void configure_secondary_cores(void)
252{
David Hendricksb7743132013-08-09 18:19:29 -0700253 if (get_bits(read_midr(), 4, 12) == PART_NUMBER_CORTEX_A15) {
254 configure_l2ctlr();
255 configure_l2actlr();
256 }
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800257
258 /* Currently we use power_down_core as callback for each core to
259 * shutdown itself, but it is also ok to directly set ARM_CORE*_CONFIG
260 * to zero by CPU0 because every secondary cores should be already in
261 * WFI state (in bootblock). The power_down_core will be more helpful
262 * when we want to use SMP inside firmware. */
263
Elyes HAOUAS038e7242016-07-29 18:31:16 +0200264 /* Clear boot reg (hotplug address) in CPU states */
Julius Werner2f37bd62015-02-19 14:51:15 -0800265 write32((void *)&exynos_cpu_states->hotplug_address, 0);
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800266
267 /* set low_power flag and address */
Julius Werner2f37bd62015-02-19 14:51:15 -0800268 write32(VECTOR_LOW_POWER_ADDRESS, (intptr_t)low_power_start);
269 write32(VECTOR_LOW_POWER_FLAG, RST_FLAG_VAL);
270 write32(&exynos_power->spare0, RST_FLAG_VAL);
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800271
272 /* On next SEV, shutdown all cores. */
Julius Werner2f37bd62015-02-19 14:51:15 -0800273 write32(VECTOR_CORE_SEV_HANDLER, (intptr_t)power_down_core);
Hung-Te Lin0682cfe2013-08-06 20:37:55 +0800274
275 /* Ask all cores in WFE mode to shutdown. */
276 dsb();
277 sev();
278}
279
280/* Configures the SMP cores on Exynos 5420 SOC (and shutdown all secondary
281 * cores) */
282void exynos5420_config_smp(void)
283{
284 init_exynos_cpu_states();
285 configure_secondary_cores();
286}