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