xref: /rk3399_ARM-atf/drivers/renesas/rcar_gen4/pwrc/pwrc.c (revision 6fb6bee1dfd7fd896c44cc21b02b4ef3aad3bbd0)
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 */
45 static uintptr_t apsreg_ap_cluster_aux0(uint32_t n)
46 {
47 	return APSREG_BASE + 0x10UL + ((n & 0x3) * 0x1000UL);
48 }
49 
50 /* APMU */
51 static uintptr_t rcar_apmu_cluster_base(uint32_t n)
52 {
53 	return RCAR_APMU_BASE + 0x400UL + ((n & 0x3) * 0x40UL);
54 }
55 
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 
62 static uintptr_t rcar_apmu_pwrctrlcl(uint32_t n)
63 {
64 	return rcar_apmu_cluster_base(n);
65 }
66 
67 static uintptr_t rcar_apmu_pwrctrlc(uint32_t n)
68 {
69 	return rcar_apmu_cpu_base(n);
70 }
71 
72 static uintptr_t rcar_apmu_safectrlc(uint32_t n)
73 {
74 	return rcar_apmu_cpu_base(n) + 0x20UL;
75 }
76 
77 static uintptr_t rcar_apmu_rvbarplc(uint32_t n)
78 {
79 	return rcar_apmu_cpu_base(n) + 0x38UL;
80 }
81 
82 static uintptr_t rcar_apmu_rvbarphc(uint32_t n)
83 {
84 	return rcar_apmu_cpu_base(n) + 0x3cUL;
85 }
86 
87 static uintptr_t rcar_apmu_fsmstsrc(uint32_t n)
88 {
89 	return rcar_apmu_cpu_base(n) + 0x18UL;
90 }
91 
92 /* Product register */
93 static uint32_t prr_caxx_xx_en_cpu(uint32_t n)
94 {
95 	return BIT(n & 0x1);
96 }
97 
98 static void write_cpupwrctlr(u_register_t v)
99 {
100 	__asm__ volatile ("msr S3_0_C15_C2_7, %0" : : "r" (v));
101 }
102 
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 
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 
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 
159 bool rcar_pwrc_mpidr_is_boot_cpu(u_register_t mpidr)
160 {
161 	return (mpidr & RCAR_MPIDR_AFFMASK) == rcar_boot_mpidr;
162 }
163 
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 
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 
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 
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 
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 
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 
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 
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 __section(".system_ram") rcar_pwrc_set_self_refresh(void)
316 {
317 	uint64_t base_count, freq, get_count, wait_time;
318 	uint32_t reg;
319 
320 	/* Enable DBSC4 register access */
321 	mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE);
322 
323 	/* DFI_PHYMSTR_ACK setting */
324 	mmio_clrbits_32(DBSC4_REG_DBDFIPMSTRCNF, DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN);
325 
326 	/* Set the Self-Refresh mode */
327 
328 	/* Disable access to the SDRAM */
329 	mmio_write_32(DBSC4_REG_DBACEN, 0);
330 
331 	/* Flush the access request in DBSC */
332 	mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1);
333 
334 	/* Wait succeed to flush */
335 	freq = read_cntfrq_el0();
336 	base_count = read_cntpct_el0();
337 
338 	while ((mmio_read_32(DBSC4_REG_DBCAM0STAT0) & DBSC4_BIT_DBCAM0STAT0)
339 			!= DBSC4_BIT_DBCAM0STAT0) {
340 
341 		get_count = read_cntpct_el0();
342 		wait_time = ((get_count - base_count) * RCAR_CONV_MICROSEC) / freq;
343 
344 		/* Get base counter */
345 		if (wait_time >= RCAR_WAIT_DBCS4_FLUSH) {
346 
347 			/* Stop flushing and enable access to SDRAM */
348 			mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0);
349 			mmio_write_32(DBSC4_REG_DBACEN, 1);
350 
351 			/* Dummy write to SDRAM */
352 			dummy_sdram = ~dummy_sdram;
353 
354 			/* Re-Disable access and flush */
355 			mmio_write_32(DBSC4_REG_DBACEN, 0);
356 			mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1);
357 
358 			/* refresh base counter */
359 			base_count = read_cntpct_el0();
360 		}
361 	}
362 
363 	/* Clear the SDRAM calibration configuration register */
364 	mmio_write_32(DBSC4_REG_DBCALCNF, 0);
365 
366 	/* Issue Precharge All (PREA) command */
367 	reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL |
368 	      DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL;
369 	mmio_write_32(DBSC4_REG_DBCMD, reg);
370 
371 	/* Wait to complete PREA operation */
372 	while (mmio_read_32(DBSC4_REG_DBWAIT) != 0)
373 		;
374 
375 	/* Issue Self-Refresh Entry (SRE) command   */
376 	reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL |
377 	      DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER;
378 	mmio_write_32(DBSC4_REG_DBCMD, reg);
379 
380 	/* Wait to complete SRE operation */
381 	while (mmio_read_32(DBSC4_REG_DBWAIT) != 0)
382 		;
383 
384 	/* Issue Mode Register 11 (MR11) write command. (ODT disabled)  */
385 	reg = DBSC4_SET_DBCMD_OPC_MRW | DBSC4_SET_DBCMD_CH_ALL |
386 	      DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_MRW_ODTC;
387 	mmio_write_32(DBSC4_REG_DBCMD, reg);
388 
389 	/* Wait to complete MR11 operation */
390 	while (mmio_read_32(DBSC4_REG_DBWAIT) != 0)
391 		;
392 
393 	/* Issue Power Down (PD) command */
394 	reg = DBSC4_SET_DBCMD_OPC_PD | DBSC4_SET_DBCMD_CH_ALL |
395 	      DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER;
396 	mmio_write_32(DBSC4_REG_DBCMD, reg);
397 
398 	/* Wait to complete PD operation */
399 	while (mmio_read_32(DBSC4_REG_DBWAIT) != 0)
400 		;
401 
402 	/* Issue set the Auto-Refresh Enable register */
403 	/* to stop the auto-refresh function */
404 	mmio_write_32(DBSC4_REG_DBRFEN, 0);
405 
406 	/* Dummy read DBWAIT register to wait tCKELPD time */
407 	(void)mmio_read_32(DBSC4_REG_DBWAIT);
408 
409 	/* Disable DBSC4 register access */
410 	mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE);
411 }
412 
413 static void __section(".system_ram") __attribute__ ((noinline))
414 		rcar_pwrc_go_suspend_to_ram(void)
415 {
416 	rcar_pwrc_set_self_refresh();
417 
418 	wfi();
419 
420 	/* Do not return */
421 	while (true)
422 		;
423 }
424 
425 void rcar_pwrc_suspend_to_ram(void)
426 {
427 	uintptr_t jump = (uintptr_t) rcar_pwrc_go_suspend_to_ram;
428 	uintptr_t stack = (uintptr_t) (DEVICE_SRAM_STACK_BASE +
429 				       DEVICE_SRAM_STACK_SIZE);
430 
431 	rcar_pwrc_save_timer_state();
432 
433 	/* Clear code copy state to execute copy on next boot time */
434 	rcar_pwrc_code_copy_state = RCAR_CODE_COPY_NONE;
435 
436 	/* disable MMU */
437 	disable_mmu_el3();
438 
439 	/* cache flush */
440 	dcsw_op_all(DCCISW);
441 
442 	(void)rcar_pwrc_switch_stack(jump, stack, NULL);
443 }
444 
445 void rcar_pwrc_code_copy_to_system_ram(void)
446 {
447 	int __maybe_unused ret;
448 	uint32_t attr;
449 	struct {
450 		uintptr_t	base;
451 		size_t		len;
452 	} sram = {
453 		.base	= (uintptr_t) DEVICE_SRAM_BASE,
454 		.len	= DEVICE_SRAM_SIZE
455 	}, code = {
456 		.base	= (uintptr_t) SRAM_COPY_START,
457 		.len	= (size_t)(SYSTEM_RAM_END - SYSTEM_RAM_START)
458 	};
459 
460 	/*
461 	 * The copy of the code should only be executed for ColdBoot,
462 	 * and for WarmBoot from SuspendToRAM.
463 	 */
464 	if (rcar_pwrc_code_copy_state == RCAR_CODE_COPY_DONE) {
465 		/* No need to run because it has already been copied */
466 		return;
467 	}
468 
469 	rcar_pwrc_code_copy_state = RCAR_CODE_COPY_DONE;
470 	flush_dcache_range((uintptr_t)(&rcar_pwrc_code_copy_state),
471 			   sizeof(rcar_pwrc_code_copy_state));
472 
473 	attr = MT_MEMORY | MT_RW | MT_SECURE | MT_EXECUTE_NEVER;
474 	ret = xlat_change_mem_attributes(sram.base, sram.len, attr);
475 	assert(ret == 0);
476 
477 	(void)memcpy((void *)sram.base, (void *)code.base, code.len);
478 	flush_dcache_range(sram.base, code.len);
479 
480 	/* Invalidate instruction cache */
481 	plat_invalidate_icache();
482 	dsb();
483 	isb();
484 
485 	attr = MT_MEMORY | MT_RO | MT_SECURE | MT_EXECUTE;
486 	ret = xlat_change_mem_attributes(sram.base, sram.len, attr);
487 	assert(ret == 0);
488 
489 	/* clean up data and stack area in system ram */
490 	(void)memset((void *)DEVICE_SRAM_DATA_BASE, 0x0,
491 		     DEVICE_SRAM_DATA_SIZE + DEVICE_SRAM_STACK_SIZE);
492 	flush_dcache_range((uintptr_t)DEVICE_SRAM_DATA_BASE,
493 			   DEVICE_SRAM_DATA_SIZE + DEVICE_SRAM_STACK_SIZE);
494 }
495