1 /*
2 * Copyright (c) 2015-2025, Renesas Electronics Corporation. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8 #include <string.h>
9
10 #include <arch.h>
11 #include <arch_helpers.h>
12 #include <common/debug.h>
13 #include <lib/bakery_lock.h>
14 #include <lib/mmio.h>
15 #include <lib/xlat_tables/xlat_tables_v2.h>
16 #include <plat/common/platform.h>
17
18 #include "pwrc.h"
19 #include "timer.h"
20
21 #include "rcar_def.h"
22 #include "rcar_private.h"
23
24 #ifndef __ASSEMBLER__
25 IMPORT_SYM(uintptr_t, __system_ram_start__, SYSTEM_RAM_START);
26 IMPORT_SYM(uintptr_t, __system_ram_end__, SYSTEM_RAM_END);
27 IMPORT_SYM(uintptr_t, __SRAM_COPY_START__, SRAM_COPY_START);
28 #endif /*__ASSEMBLER__*/
29
30 #define RCAR_CODE_COPY_NONE 0
31 #define RCAR_CODE_COPY_DONE 1
32
33 static uint32_t dummy_sdram = 0xAAAAAAAA;
34 static uint32_t rcar_pwrc_code_copy_state;
35
36 /*
37 * Someday there will be a generic power controller API. At the moment each
38 * platform has its own PWRC so just exporting functions should be acceptable.
39 */
40 static RCAR_INSTANTIATE_LOCK;
41
42 static u_register_t rcar_boot_mpidr;
43
44 /* APSREG boot configuration */
apsreg_ap_cluster_aux0(uint32_t n)45 static uintptr_t apsreg_ap_cluster_aux0(uint32_t n)
46 {
47 return APSREG_BASE + 0x10UL + ((n & 0x3) * 0x1000UL);
48 }
49
50 /* APMU */
rcar_apmu_cluster_base(uint32_t n)51 static uintptr_t rcar_apmu_cluster_base(uint32_t n)
52 {
53 return RCAR_APMU_BASE + 0x400UL + ((n & 0x3) * 0x40UL);
54 }
55
rcar_apmu_cpu_base(uint32_t n)56 static uintptr_t rcar_apmu_cpu_base(uint32_t n)
57 {
58 return RCAR_APMU_BASE + 0x800UL + ((n & 0x6) * 0x100UL) +
59 ((n & 0x1) * 0x40UL);
60 }
61
rcar_apmu_pwrctrlcl(uint32_t n)62 static uintptr_t rcar_apmu_pwrctrlcl(uint32_t n)
63 {
64 return rcar_apmu_cluster_base(n);
65 }
66
rcar_apmu_pwrctrlc(uint32_t n)67 static uintptr_t rcar_apmu_pwrctrlc(uint32_t n)
68 {
69 return rcar_apmu_cpu_base(n);
70 }
71
rcar_apmu_safectrlc(uint32_t n)72 static uintptr_t rcar_apmu_safectrlc(uint32_t n)
73 {
74 return rcar_apmu_cpu_base(n) + 0x20UL;
75 }
76
rcar_apmu_rvbarplc(uint32_t n)77 static uintptr_t rcar_apmu_rvbarplc(uint32_t n)
78 {
79 return rcar_apmu_cpu_base(n) + 0x38UL;
80 }
81
rcar_apmu_rvbarphc(uint32_t n)82 static uintptr_t rcar_apmu_rvbarphc(uint32_t n)
83 {
84 return rcar_apmu_cpu_base(n) + 0x3cUL;
85 }
86
rcar_apmu_fsmstsrc(uint32_t n)87 static uintptr_t rcar_apmu_fsmstsrc(uint32_t n)
88 {
89 return rcar_apmu_cpu_base(n) + 0x18UL;
90 }
91
92 /* Product register */
prr_caxx_xx_en_cpu(uint32_t n)93 static uint32_t prr_caxx_xx_en_cpu(uint32_t n)
94 {
95 return BIT(n & 0x1);
96 }
97
write_cpupwrctlr(u_register_t v)98 static void write_cpupwrctlr(u_register_t v)
99 {
100 __asm__ volatile ("msr S3_0_C15_C2_7, %0" : : "r" (v));
101 }
102
rcar_pwrc_core_pos(u_register_t mpidr)103 static uint32_t rcar_pwrc_core_pos(u_register_t mpidr)
104 {
105 int cpu;
106
107 cpu = plat_core_pos_by_mpidr(mpidr);
108 if (cpu < 0) {
109 ERROR("BL3-1 : The value of passed MPIDR is invalid.");
110 panic();
111 }
112
113 return (uint32_t)cpu;
114 }
115
rcar_pwrc_cpuon(u_register_t mpidr)116 void rcar_pwrc_cpuon(u_register_t mpidr)
117 {
118 uint32_t cluster, cpu;
119
120 rcar_lock_get();
121
122 cpu = rcar_pwrc_core_pos(mpidr);
123
124 cluster = rcar_pwrc_get_mpidr_cluster(mpidr);
125
126 /* clear Cluster OFF bit */
127 mmio_clrbits_32(rcar_apmu_pwrctrlcl(cluster),
128 RCAR_APMU_PWRCTRLCL_PCHPDNEN);
129
130 /* clear Core OFF bit */
131 mmio_clrbits_32(rcar_apmu_pwrctrlc(cpu), RCAR_APMU_PWRCTRLC_PCHPDNEN);
132 while (mmio_read_32(rcar_apmu_pwrctrlc(cpu)) & RCAR_APMU_PWRCTRLC_PCHPDNEN)
133 ;
134
135 mmio_setbits_32(rcar_apmu_pwrctrlc(cpu), RCAR_APMU_PWRCTRLC_WUP_REQ);
136
137 /* Wait until CAXX wake up sequence finishes */
138 while ((mmio_read_32(rcar_apmu_pwrctrlc(cpu)) & RCAR_APMU_PWRCTRLC_WUP_REQ) ==
139 RCAR_APMU_PWRCTRLC_WUP_REQ)
140 ;
141
142 rcar_lock_release();
143
144 /*
145 * mask should match the kernel's MPIDR_HWID_BITMASK so the core can be
146 * identified during cpuhotplug (check the kernel's psci migrate set of
147 * functions
148 */
149 rcar_boot_mpidr = read_mpidr_el1() & RCAR_MPIDR_AFFMASK;
150 }
151
rcar_pwrc_cpu_migrate_info(u_register_t * resident_cpu)152 int32_t rcar_pwrc_cpu_migrate_info(u_register_t *resident_cpu)
153 {
154 *resident_cpu = rcar_boot_mpidr;
155
156 return PSCI_TOS_NOT_UP_MIG_CAP;
157 }
158
rcar_pwrc_mpidr_is_boot_cpu(u_register_t mpidr)159 bool rcar_pwrc_mpidr_is_boot_cpu(u_register_t mpidr)
160 {
161 return (mpidr & RCAR_MPIDR_AFFMASK) == rcar_boot_mpidr;
162 }
163
rcar_pwrc_cpuoff_sub(uint32_t cpu)164 static void rcar_pwrc_cpuoff_sub(uint32_t cpu)
165 {
166 /* Clear DBGGEN_PPDN bit for core down to 'OFF' mode */
167 mmio_clrbits_32(rcar_apmu_safectrlc(cpu), RCAR_APMU_SAFECTRLC_DBGGEN);
168 /* for Core OFF */
169 mmio_setbits_32(rcar_apmu_pwrctrlc(cpu), RCAR_APMU_PWRCTRLC_PCHPDNEN);
170
171 write_cpupwrctlr(CPUPWRCTLR_PWDN);
172 }
173
rcar_pwrc_cpuoff(u_register_t mpidr)174 void rcar_pwrc_cpuoff(u_register_t mpidr)
175 {
176 uint32_t cpu;
177
178 rcar_lock_get();
179
180 cpu = rcar_pwrc_core_pos(mpidr);
181
182 rcar_pwrc_cpuoff_sub(cpu);
183
184 rcar_lock_release();
185 }
186
rcar_pwrc_enable_interrupt_wakeup(u_register_t mpidr)187 void rcar_pwrc_enable_interrupt_wakeup(u_register_t mpidr)
188 {
189 uint32_t cpu;
190
191 rcar_lock_get();
192
193 cpu = rcar_pwrc_core_pos(mpidr);
194
195 mmio_setbits_32(rcar_apmu_pwrctrlc(cpu), RCAR_APMU_PWRCTRLC_IWUP_EN);
196
197 rcar_lock_release();
198 }
199
rcar_pwrc_disable_interrupt_wakeup(u_register_t mpidr)200 void rcar_pwrc_disable_interrupt_wakeup(u_register_t mpidr)
201 {
202 uint32_t cpu;
203
204 rcar_lock_get();
205
206 cpu = rcar_pwrc_core_pos(mpidr);
207
208 mmio_clrbits_32(rcar_apmu_pwrctrlc(cpu), RCAR_APMU_PWRCTRLC_IWUP_EN);
209
210 rcar_lock_release();
211 }
212
rcar_pwrc_clusteroff(u_register_t mpidr)213 void rcar_pwrc_clusteroff(u_register_t mpidr)
214 {
215 uint32_t cluster, cpu;
216
217 rcar_lock_get();
218
219 cpu = rcar_pwrc_core_pos(mpidr);
220
221 cluster = rcar_pwrc_get_mpidr_cluster(mpidr);
222
223 /* for Cluster OFF */
224 mmio_setbits_32(rcar_apmu_pwrctrlcl(cluster),
225 RCAR_APMU_PWRCTRLCL_PCHPDNEN);
226
227 rcar_pwrc_cpuoff_sub(cpu);
228
229 rcar_lock_release();
230 }
231
rcar_pwrc_setup(void)232 void rcar_pwrc_setup(void)
233 {
234 uintptr_t rst_barh, rst_barl;
235 uint32_t cpu, i, j, reg;
236 uint64_t reset;
237
238 reset = (uint64_t)(&plat_secondary_reset) & 0xFFFFFFFFU;
239 reset &= RCAR_APMU_RVBARPLC_MASK;
240 reset |= RCAR_APMU_RVBARPL_VLD;
241
242 reg = mmio_read_32(RCAR_PRR) >> 17;
243 for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) {
244 reg >>= 3;
245
246 if ((reg & PRR_CAXX_XX_EN_CLUSTER_MASK) != RCAR_CPU_HAVE_CAXX)
247 continue;
248
249 mmio_setbits_32(apsreg_ap_cluster_aux0(i),
250 APSREG_AP_CLUSTER_AUX0_INIT);
251
252 for (j = 0; j < PLATFORM_MAX_CPUS_PER_CLUSTER; j++) {
253 cpu = (i * PLATFORM_MAX_CPUS_PER_CLUSTER) + j;
254
255 if ((reg & prr_caxx_xx_en_cpu(cpu)) != RCAR_CPU_HAVE_CAXX)
256 continue;
257
258 rst_barh = rcar_apmu_rvbarphc(cpu);
259 rst_barl = rcar_apmu_rvbarplc(cpu);
260 mmio_write_32(rst_barh, 0);
261 mmio_write_32(rst_barl, (uint32_t)reset);
262 }
263 }
264
265 mmio_setbits_32(APSREG_CCI500_AUX, APSREG_CCI500_AUX_INIT);
266 mmio_setbits_32(APSREG_P_CCI500_AUX, APSREG_P_CCI500_AUX_INIT);
267
268 rcar_lock_init();
269 }
270
rcar_pwrc_get_mpidr_cluster(u_register_t mpidr)271 uint32_t rcar_pwrc_get_mpidr_cluster(u_register_t mpidr)
272 {
273 int32_t cluster = rcar_cluster_pos_by_mpidr(mpidr);
274
275 if (cluster < 0) {
276 ERROR("BL3-1 : The value of passed MPIDR is invalid.");
277 panic();
278 }
279
280 return (uint32_t)cluster;
281 }
282
rcar_pwrc_cpu_on_check(u_register_t mpidr)283 uint32_t rcar_pwrc_cpu_on_check(u_register_t mpidr)
284 {
285 uint32_t core_pos, cpu, i, j, prr, state;
286 uint32_t count = 0;
287
288 core_pos = rcar_pwrc_core_pos(mpidr);
289 prr = mmio_read_32(RCAR_PRR) >> 17;
290 for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) {
291 prr >>= 3;
292
293 /* check the cluster has cores */
294 if ((prr & PRR_CAXX_XX_EN_CLUSTER_MASK) != RCAR_CPU_HAVE_CAXX)
295 continue;
296
297 for (j = 0; j < PLATFORM_MAX_CPUS_PER_CLUSTER; j++) {
298 cpu = (i * PLATFORM_MAX_CPUS_PER_CLUSTER) + j;
299
300 /* check the core be implemented */
301 if ((prr & prr_caxx_xx_en_cpu(cpu)) != RCAR_CPU_HAVE_CAXX)
302 continue;
303
304 if (core_pos != cpu) {
305 state = mmio_read_32(rcar_apmu_fsmstsrc(cpu));
306 if (state != RCAR_APMU_FSMSTSRC_STATE_OFF)
307 count++;
308 }
309 }
310 }
311
312 return count;
313 }
314
315 static void __attribute__ ((section(".system_ram"), no_stack_protector))
rcar_pwrc_set_self_refresh(void)316 rcar_pwrc_set_self_refresh(void)
317 {
318 uint64_t base_count, freq, get_count, wait_time;
319 uint32_t reg;
320
321 /* Enable DBSC4 register access */
322 mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE);
323
324 /* DFI_PHYMSTR_ACK setting */
325 mmio_clrbits_32(DBSC4_REG_DBDFIPMSTRCNF, DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN);
326
327 /* Set the Self-Refresh mode */
328
329 /* Disable access to the SDRAM */
330 mmio_write_32(DBSC4_REG_DBACEN, 0);
331
332 /* Flush the access request in DBSC */
333 mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1);
334
335 /* Wait succeed to flush */
336 freq = read_cntfrq_el0();
337 base_count = read_cntpct_el0();
338
339 while ((mmio_read_32(DBSC4_REG_DBCAM0STAT0) & DBSC4_BIT_DBCAM0STAT0)
340 != DBSC4_BIT_DBCAM0STAT0) {
341
342 get_count = read_cntpct_el0();
343 wait_time = ((get_count - base_count) * RCAR_CONV_MICROSEC) / freq;
344
345 /* Get base counter */
346 if (wait_time >= RCAR_WAIT_DBCS4_FLUSH) {
347
348 /* Stop flushing and enable access to SDRAM */
349 mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0);
350 mmio_write_32(DBSC4_REG_DBACEN, 1);
351
352 /* Dummy write to SDRAM */
353 dummy_sdram = ~dummy_sdram;
354
355 /* Re-Disable access and flush */
356 mmio_write_32(DBSC4_REG_DBACEN, 0);
357 mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1);
358
359 /* refresh base counter */
360 base_count = read_cntpct_el0();
361 }
362 }
363
364 /* Clear the SDRAM calibration configuration register */
365 mmio_write_32(DBSC4_REG_DBCALCNF, 0);
366
367 /* Issue Precharge All (PREA) command */
368 reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL |
369 DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL;
370 mmio_write_32(DBSC4_REG_DBCMD, reg);
371
372 /* Wait to complete PREA operation */
373 while (mmio_read_32(DBSC4_REG_DBWAIT) != 0)
374 ;
375
376 /* Issue Self-Refresh Entry (SRE) command */
377 reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL |
378 DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER;
379 mmio_write_32(DBSC4_REG_DBCMD, reg);
380
381 /* Wait to complete SRE operation */
382 while (mmio_read_32(DBSC4_REG_DBWAIT) != 0)
383 ;
384
385 /* Issue Mode Register 11 (MR11) write command. (ODT disabled) */
386 reg = DBSC4_SET_DBCMD_OPC_MRW | DBSC4_SET_DBCMD_CH_ALL |
387 DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_MRW_ODTC;
388 mmio_write_32(DBSC4_REG_DBCMD, reg);
389
390 /* Wait to complete MR11 operation */
391 while (mmio_read_32(DBSC4_REG_DBWAIT) != 0)
392 ;
393
394 /* Issue Power Down (PD) command */
395 reg = DBSC4_SET_DBCMD_OPC_PD | DBSC4_SET_DBCMD_CH_ALL |
396 DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER;
397 mmio_write_32(DBSC4_REG_DBCMD, reg);
398
399 /* Wait to complete PD operation */
400 while (mmio_read_32(DBSC4_REG_DBWAIT) != 0)
401 ;
402
403 /* Issue set the Auto-Refresh Enable register */
404 /* to stop the auto-refresh function */
405 mmio_write_32(DBSC4_REG_DBRFEN, 0);
406
407 /* Dummy read DBWAIT register to wait tCKELPD time */
408 (void)mmio_read_32(DBSC4_REG_DBWAIT);
409
410 /* Disable DBSC4 register access */
411 mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE);
412 }
413
414 static void __attribute__ ((section(".system_ram"), no_stack_protector))
rcar_pwrc_go_suspend_to_ram(void)415 rcar_pwrc_go_suspend_to_ram(void)
416 {
417 rcar_pwrc_set_self_refresh();
418
419 wfi();
420
421 /* Do not return */
422 while (true)
423 ;
424 }
425
rcar_pwrc_suspend_to_ram(void)426 void rcar_pwrc_suspend_to_ram(void)
427 {
428 uintptr_t jump = (uintptr_t) rcar_pwrc_go_suspend_to_ram;
429 uintptr_t stack = (uintptr_t) (DEVICE_SRAM_STACK_BASE +
430 DEVICE_SRAM_STACK_SIZE);
431
432 rcar_pwrc_save_timer_state();
433
434 /* Clear code copy state to execute copy on next boot time */
435 rcar_pwrc_code_copy_state = RCAR_CODE_COPY_NONE;
436
437 /* disable MMU */
438 disable_mmu_el3();
439
440 /* cache flush */
441 dcsw_op_all(DCCISW);
442
443 (void)rcar_pwrc_switch_stack(jump, stack, NULL);
444 }
445
rcar_pwrc_code_copy_to_system_ram(void)446 void rcar_pwrc_code_copy_to_system_ram(void)
447 {
448 int __maybe_unused ret;
449 uint32_t attr;
450 struct {
451 uintptr_t base;
452 size_t len;
453 } sram = {
454 .base = (uintptr_t) DEVICE_SRAM_BASE,
455 .len = DEVICE_SRAM_SIZE
456 }, code = {
457 .base = (uintptr_t) SRAM_COPY_START,
458 .len = (size_t)(SYSTEM_RAM_END - SYSTEM_RAM_START)
459 };
460
461 /*
462 * The copy of the code should only be executed for ColdBoot,
463 * and for WarmBoot from SuspendToRAM.
464 */
465 if (rcar_pwrc_code_copy_state == RCAR_CODE_COPY_DONE) {
466 /* No need to run because it has already been copied */
467 return;
468 }
469
470 rcar_pwrc_code_copy_state = RCAR_CODE_COPY_DONE;
471 flush_dcache_range((uintptr_t)(&rcar_pwrc_code_copy_state),
472 sizeof(rcar_pwrc_code_copy_state));
473
474 attr = MT_MEMORY | MT_RW | MT_SECURE | MT_EXECUTE_NEVER;
475 ret = xlat_change_mem_attributes(sram.base, sram.len, attr);
476 assert(ret == 0);
477
478 (void)memcpy((void *)sram.base, (void *)code.base, code.len);
479 flush_dcache_range(sram.base, code.len);
480
481 /* Invalidate instruction cache */
482 plat_invalidate_icache();
483 dsb();
484 isb();
485
486 attr = MT_MEMORY | MT_RO | MT_SECURE | MT_EXECUTE;
487 ret = xlat_change_mem_attributes(sram.base, sram.len, attr);
488 assert(ret == 0);
489
490 /* clean up data and stack area in system ram */
491 (void)memset((void *)DEVICE_SRAM_DATA_BASE, 0x0,
492 DEVICE_SRAM_DATA_SIZE + DEVICE_SRAM_STACK_SIZE);
493 flush_dcache_range((uintptr_t)DEVICE_SRAM_DATA_BASE,
494 DEVICE_SRAM_DATA_SIZE + DEVICE_SRAM_STACK_SIZE);
495 }
496