xref: /rk3399_ARM-atf/plat/renesas/common/plat_pm.c (revision 499c2713f05c602e6f22467c18be30cf9697c42d)
1*499c2713SBiju Das /*
2*499c2713SBiju Das  * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
3*499c2713SBiju Das  *
4*499c2713SBiju Das  * SPDX-License-Identifier: BSD-3-Clause
5*499c2713SBiju Das  */
6*499c2713SBiju Das 
7*499c2713SBiju Das #include <errno.h>
8*499c2713SBiju Das 
9*499c2713SBiju Das #include <arch_helpers.h>
10*499c2713SBiju Das #include <common/bl_common.h>
11*499c2713SBiju Das #include <common/debug.h>
12*499c2713SBiju Das #include <drivers/arm/cci.h>
13*499c2713SBiju Das #include <drivers/arm/gicv2.h>
14*499c2713SBiju Das #include <lib/bakery_lock.h>
15*499c2713SBiju Das #include <lib/mmio.h>
16*499c2713SBiju Das #include <lib/psci/psci.h>
17*499c2713SBiju Das #include <plat/common/platform.h>
18*499c2713SBiju Das 
19*499c2713SBiju Das #include "iic_dvfs.h"
20*499c2713SBiju Das #include "platform_def.h"
21*499c2713SBiju Das #include "pwrc.h"
22*499c2713SBiju Das #include "rcar_def.h"
23*499c2713SBiju Das #include "rcar_private.h"
24*499c2713SBiju Das #include "ulcb_cpld.h"
25*499c2713SBiju Das 
26*499c2713SBiju Das #define DVFS_SET_VID_0V		(0x00)
27*499c2713SBiju Das #define P_ALL_OFF		(0x80)
28*499c2713SBiju Das #define KEEPON_DDR1C		(0x08)
29*499c2713SBiju Das #define KEEPON_DDR0C		(0x04)
30*499c2713SBiju Das #define KEEPON_DDR1		(0x02)
31*499c2713SBiju Das #define KEEPON_DDR0		(0x01)
32*499c2713SBiju Das 
33*499c2713SBiju Das #define SYSTEM_PWR_STATE(s)	((s)->pwr_domain_state[PLAT_MAX_PWR_LVL])
34*499c2713SBiju Das #define CLUSTER_PWR_STATE(s)	((s)->pwr_domain_state[MPIDR_AFFLVL1])
35*499c2713SBiju Das #define CORE_PWR_STATE(s)	((s)->pwr_domain_state[MPIDR_AFFLVL0])
36*499c2713SBiju Das 
37*499c2713SBiju Das extern void rcar_pwrc_restore_generic_timer(uint64_t *stack);
38*499c2713SBiju Das extern void plat_rcar_gic_driver_init(void);
39*499c2713SBiju Das extern void plat_rcar_gic_init(void);
40*499c2713SBiju Das extern u_register_t rcar_boot_mpidr;
41*499c2713SBiju Das 
42*499c2713SBiju Das static uintptr_t rcar_sec_entrypoint;
43*499c2713SBiju Das 
44*499c2713SBiju Das static void rcar_program_mailbox(uint64_t mpidr, uint64_t address)
45*499c2713SBiju Das {
46*499c2713SBiju Das 	mailbox_t *rcar_mboxes = (mailbox_t *) MBOX_BASE;
47*499c2713SBiju Das 	uint64_t linear_id = plat_core_pos_by_mpidr(mpidr);
48*499c2713SBiju Das 	unsigned long range;
49*499c2713SBiju Das 
50*499c2713SBiju Das 	rcar_mboxes[linear_id].value = address;
51*499c2713SBiju Das 	range = (unsigned long)&rcar_mboxes[linear_id];
52*499c2713SBiju Das 
53*499c2713SBiju Das 	flush_dcache_range(range, sizeof(range));
54*499c2713SBiju Das }
55*499c2713SBiju Das 
56*499c2713SBiju Das static void rcar_cpu_standby(plat_local_state_t cpu_state)
57*499c2713SBiju Das {
58*499c2713SBiju Das 	u_register_t scr_el3 = read_scr_el3();
59*499c2713SBiju Das 
60*499c2713SBiju Das 	write_scr_el3(scr_el3 | SCR_IRQ_BIT);
61*499c2713SBiju Das 	dsb();
62*499c2713SBiju Das 	wfi();
63*499c2713SBiju Das 	write_scr_el3(scr_el3);
64*499c2713SBiju Das }
65*499c2713SBiju Das 
66*499c2713SBiju Das static int rcar_pwr_domain_on(u_register_t mpidr)
67*499c2713SBiju Das {
68*499c2713SBiju Das 	rcar_program_mailbox(mpidr, rcar_sec_entrypoint);
69*499c2713SBiju Das 	rcar_pwrc_cpuon(mpidr);
70*499c2713SBiju Das 
71*499c2713SBiju Das 	return PSCI_E_SUCCESS;
72*499c2713SBiju Das }
73*499c2713SBiju Das 
74*499c2713SBiju Das static void rcar_pwr_domain_on_finish(const psci_power_state_t *target_state)
75*499c2713SBiju Das {
76*499c2713SBiju Das 	uint32_t cluster_type = rcar_pwrc_get_cluster();
77*499c2713SBiju Das 	unsigned long mpidr = read_mpidr_el1();
78*499c2713SBiju Das 
79*499c2713SBiju Das 	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
80*499c2713SBiju Das 		if (cluster_type == RCAR_CLUSTER_A53A57)
81*499c2713SBiju Das 			plat_cci_enable();
82*499c2713SBiju Das 
83*499c2713SBiju Das 	rcar_pwrc_disable_interrupt_wakeup(mpidr);
84*499c2713SBiju Das 	rcar_program_mailbox(mpidr, 0);
85*499c2713SBiju Das 
86*499c2713SBiju Das 	gicv2_cpuif_enable();
87*499c2713SBiju Das 	gicv2_pcpu_distif_init();
88*499c2713SBiju Das }
89*499c2713SBiju Das 
90*499c2713SBiju Das static void rcar_pwr_domain_off(const psci_power_state_t *target_state)
91*499c2713SBiju Das {
92*499c2713SBiju Das #if RCAR_LSI != RCAR_D3
93*499c2713SBiju Das 	uint32_t cluster_type = rcar_pwrc_get_cluster();
94*499c2713SBiju Das #endif
95*499c2713SBiju Das 	unsigned long mpidr = read_mpidr_el1();
96*499c2713SBiju Das 
97*499c2713SBiju Das 	gicv2_cpuif_disable();
98*499c2713SBiju Das 	rcar_pwrc_cpuoff(mpidr);
99*499c2713SBiju Das 
100*499c2713SBiju Das #if RCAR_LSI != RCAR_D3
101*499c2713SBiju Das 	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
102*499c2713SBiju Das 		if (cluster_type == RCAR_CLUSTER_A53A57)
103*499c2713SBiju Das 			plat_cci_disable();
104*499c2713SBiju Das 
105*499c2713SBiju Das 		rcar_pwrc_clusteroff(mpidr);
106*499c2713SBiju Das 	}
107*499c2713SBiju Das #endif
108*499c2713SBiju Das }
109*499c2713SBiju Das 
110*499c2713SBiju Das static void rcar_pwr_domain_suspend(const psci_power_state_t *target_state)
111*499c2713SBiju Das {
112*499c2713SBiju Das 	uint32_t cluster_type = rcar_pwrc_get_cluster();
113*499c2713SBiju Das 	unsigned long mpidr = read_mpidr_el1();
114*499c2713SBiju Das 
115*499c2713SBiju Das 	if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
116*499c2713SBiju Das 		return;
117*499c2713SBiju Das 
118*499c2713SBiju Das 	rcar_program_mailbox(mpidr, rcar_sec_entrypoint);
119*499c2713SBiju Das 	rcar_pwrc_enable_interrupt_wakeup(mpidr);
120*499c2713SBiju Das 	gicv2_cpuif_disable();
121*499c2713SBiju Das 	rcar_pwrc_cpuoff(mpidr);
122*499c2713SBiju Das 
123*499c2713SBiju Das 	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
124*499c2713SBiju Das 		if (cluster_type == RCAR_CLUSTER_A53A57)
125*499c2713SBiju Das 			plat_cci_disable();
126*499c2713SBiju Das 
127*499c2713SBiju Das 		rcar_pwrc_clusteroff(mpidr);
128*499c2713SBiju Das 	}
129*499c2713SBiju Das 
130*499c2713SBiju Das #if RCAR_SYSTEM_SUSPEND
131*499c2713SBiju Das 	if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
132*499c2713SBiju Das 		rcar_pwrc_suspend_to_ram();
133*499c2713SBiju Das #endif
134*499c2713SBiju Das }
135*499c2713SBiju Das 
136*499c2713SBiju Das static void rcar_pwr_domain_suspend_finish(const psci_power_state_t
137*499c2713SBiju Das 					   *target_state)
138*499c2713SBiju Das {
139*499c2713SBiju Das 	uint32_t cluster_type = rcar_pwrc_get_cluster();
140*499c2713SBiju Das 
141*499c2713SBiju Das 	if (SYSTEM_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
142*499c2713SBiju Das 		goto finish;
143*499c2713SBiju Das 
144*499c2713SBiju Das 	plat_rcar_gic_driver_init();
145*499c2713SBiju Das 	plat_rcar_gic_init();
146*499c2713SBiju Das 
147*499c2713SBiju Das 	if (cluster_type == RCAR_CLUSTER_A53A57)
148*499c2713SBiju Das 		plat_cci_init();
149*499c2713SBiju Das 
150*499c2713SBiju Das 	rcar_pwrc_restore_timer_state();
151*499c2713SBiju Das 	rcar_pwrc_setup();
152*499c2713SBiju Das 	rcar_pwrc_code_copy_to_system_ram();
153*499c2713SBiju Das 
154*499c2713SBiju Das #if RCAR_SYSTEM_SUSPEND
155*499c2713SBiju Das 	rcar_pwrc_init_suspend_to_ram();
156*499c2713SBiju Das #endif
157*499c2713SBiju Das finish:
158*499c2713SBiju Das 	rcar_pwr_domain_on_finish(target_state);
159*499c2713SBiju Das }
160*499c2713SBiju Das 
161*499c2713SBiju Das static void __dead2 rcar_system_off(void)
162*499c2713SBiju Das {
163*499c2713SBiju Das #if PMIC_ROHM_BD9571
164*499c2713SBiju Das #if PMIC_LEVEL_MODE
165*499c2713SBiju Das 	if (rcar_iic_dvfs_send(PMIC, DVFS_SET_VID, DVFS_SET_VID_0V))
166*499c2713SBiju Das 		ERROR("BL3-1:Failed the SYSTEM-OFF.\n");
167*499c2713SBiju Das #else
168*499c2713SBiju Das 	if (rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, P_ALL_OFF))
169*499c2713SBiju Das 		ERROR("BL3-1:Failed the SYSTEM-RESET.\n");
170*499c2713SBiju Das #endif
171*499c2713SBiju Das #else
172*499c2713SBiju Das 	uint64_t cpu = read_mpidr_el1() & 0x0000ffff;
173*499c2713SBiju Das 	int32_t rtn_on;
174*499c2713SBiju Das 
175*499c2713SBiju Das 	rtn_on = rcar_pwrc_cpu_on_check(cpu);
176*499c2713SBiju Das 
177*499c2713SBiju Das 	if (cpu == rcar_boot_mpidr)
178*499c2713SBiju Das 		panic();
179*499c2713SBiju Das 
180*499c2713SBiju Das 	if (rtn_on)
181*499c2713SBiju Das 		panic();
182*499c2713SBiju Das 
183*499c2713SBiju Das 	rcar_pwrc_cpuoff(cpu);
184*499c2713SBiju Das 	rcar_pwrc_clusteroff(cpu);
185*499c2713SBiju Das 
186*499c2713SBiju Das #endif /* PMIC_ROHM_BD9571 */
187*499c2713SBiju Das 	wfi();
188*499c2713SBiju Das 	ERROR("RCAR System Off: operation not handled.\n");
189*499c2713SBiju Das 	panic();
190*499c2713SBiju Das }
191*499c2713SBiju Das 
192*499c2713SBiju Das static void __dead2 rcar_system_reset(void)
193*499c2713SBiju Das {
194*499c2713SBiju Das #if PMIC_ROHM_BD9571
195*499c2713SBiju Das #if PMIC_LEVEL_MODE
196*499c2713SBiju Das #if RCAR_SYSTEM_RESET_KEEPON_DDR
197*499c2713SBiju Das 	uint8_t mode;
198*499c2713SBiju Das 	int32_t error;
199*499c2713SBiju Das 
200*499c2713SBiju Das 	error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, KEEP10_MAGIC);
201*499c2713SBiju Das 	if (error) {
202*499c2713SBiju Das 		ERROR("Failed send KEEP10 magic ret=%d\n", error);
203*499c2713SBiju Das 		goto done;
204*499c2713SBiju Das 	}
205*499c2713SBiju Das 
206*499c2713SBiju Das 	error = rcar_iic_dvfs_receive(PMIC, BKUP_MODE_CNT, &mode);
207*499c2713SBiju Das 	if (error) {
208*499c2713SBiju Das 		ERROR("Failed receive BKUP_Mode_Cnt ret=%d\n", error);
209*499c2713SBiju Das 		goto done;
210*499c2713SBiju Das 	}
211*499c2713SBiju Das 
212*499c2713SBiju Das 	mode |= KEEPON_DDR1C | KEEPON_DDR0C | KEEPON_DDR1 | KEEPON_DDR0;
213*499c2713SBiju Das 	error = rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, mode);
214*499c2713SBiju Das 	if (error) {
215*499c2713SBiju Das 		ERROR("Failed send KEEPON_DDRx ret=%d\n", error);
216*499c2713SBiju Das 		goto done;
217*499c2713SBiju Das 	}
218*499c2713SBiju Das 
219*499c2713SBiju Das 	rcar_pwrc_set_suspend_to_ram();
220*499c2713SBiju Das done:
221*499c2713SBiju Das #else
222*499c2713SBiju Das 	if (rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, P_ALL_OFF))
223*499c2713SBiju Das 		ERROR("BL3-1:Failed the SYSTEM-RESET.\n");
224*499c2713SBiju Das #endif
225*499c2713SBiju Das #else
226*499c2713SBiju Das #if (RCAR_GEN3_ULCB == 1)
227*499c2713SBiju Das 	rcar_cpld_reset_cpu();
228*499c2713SBiju Das #endif
229*499c2713SBiju Das #endif
230*499c2713SBiju Das #else
231*499c2713SBiju Das 	rcar_pwrc_system_reset();
232*499c2713SBiju Das #endif
233*499c2713SBiju Das 	wfi();
234*499c2713SBiju Das 
235*499c2713SBiju Das 	ERROR("RCAR System Reset: operation not handled.\n");
236*499c2713SBiju Das 	panic();
237*499c2713SBiju Das }
238*499c2713SBiju Das 
239*499c2713SBiju Das static int rcar_validate_power_state(unsigned int power_state,
240*499c2713SBiju Das 				    psci_power_state_t *req_state)
241*499c2713SBiju Das {
242*499c2713SBiju Das 	unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
243*499c2713SBiju Das 	unsigned int pstate = psci_get_pstate_type(power_state);
244*499c2713SBiju Das 	uint32_t i;
245*499c2713SBiju Das 
246*499c2713SBiju Das 	if (pstate == PSTATE_TYPE_STANDBY) {
247*499c2713SBiju Das 		if (pwr_lvl != MPIDR_AFFLVL0)
248*499c2713SBiju Das 			return PSCI_E_INVALID_PARAMS;
249*499c2713SBiju Das 
250*499c2713SBiju Das 		req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
251*499c2713SBiju Das 	} else {
252*499c2713SBiju Das 		for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
253*499c2713SBiju Das 			req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
254*499c2713SBiju Das 	}
255*499c2713SBiju Das 
256*499c2713SBiju Das 	if (psci_get_pstate_id(power_state))
257*499c2713SBiju Das 		return PSCI_E_INVALID_PARAMS;
258*499c2713SBiju Das 
259*499c2713SBiju Das 	return PSCI_E_SUCCESS;
260*499c2713SBiju Das }
261*499c2713SBiju Das 
262*499c2713SBiju Das #if RCAR_SYSTEM_SUSPEND
263*499c2713SBiju Das static void rcar_get_sys_suspend_power_state(psci_power_state_t *req_state)
264*499c2713SBiju Das {
265*499c2713SBiju Das 	unsigned long mpidr = read_mpidr_el1() & 0x0000ffffU;
266*499c2713SBiju Das 	int i;
267*499c2713SBiju Das 
268*499c2713SBiju Das 	if (mpidr != rcar_boot_mpidr)
269*499c2713SBiju Das 		goto deny;
270*499c2713SBiju Das 
271*499c2713SBiju Das 	for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
272*499c2713SBiju Das 		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
273*499c2713SBiju Das 
274*499c2713SBiju Das 	return;
275*499c2713SBiju Das deny:
276*499c2713SBiju Das 	/* deny system suspend entry */
277*499c2713SBiju Das 	req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PSCI_LOCAL_STATE_RUN;
278*499c2713SBiju Das 	for (i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
279*499c2713SBiju Das 		req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE;
280*499c2713SBiju Das }
281*499c2713SBiju Das #endif
282*499c2713SBiju Das 
283*499c2713SBiju Das static const plat_psci_ops_t rcar_plat_psci_ops = {
284*499c2713SBiju Das 	.cpu_standby			= rcar_cpu_standby,
285*499c2713SBiju Das 	.pwr_domain_on			= rcar_pwr_domain_on,
286*499c2713SBiju Das 	.pwr_domain_off			= rcar_pwr_domain_off,
287*499c2713SBiju Das 	.pwr_domain_suspend		= rcar_pwr_domain_suspend,
288*499c2713SBiju Das 	.pwr_domain_on_finish		= rcar_pwr_domain_on_finish,
289*499c2713SBiju Das 	.pwr_domain_suspend_finish	= rcar_pwr_domain_suspend_finish,
290*499c2713SBiju Das 	.system_off			= rcar_system_off,
291*499c2713SBiju Das 	.system_reset			= rcar_system_reset,
292*499c2713SBiju Das 	.validate_power_state		= rcar_validate_power_state,
293*499c2713SBiju Das #if RCAR_SYSTEM_SUSPEND
294*499c2713SBiju Das 	.get_sys_suspend_power_state	= rcar_get_sys_suspend_power_state,
295*499c2713SBiju Das #endif
296*499c2713SBiju Das };
297*499c2713SBiju Das 
298*499c2713SBiju Das int plat_setup_psci_ops(uintptr_t sec_entrypoint, const plat_psci_ops_t **psci_ops)
299*499c2713SBiju Das {
300*499c2713SBiju Das 	*psci_ops = &rcar_plat_psci_ops;
301*499c2713SBiju Das 	rcar_sec_entrypoint = sec_entrypoint;
302*499c2713SBiju Das 
303*499c2713SBiju Das #if RCAR_SYSTEM_SUSPEND
304*499c2713SBiju Das 	rcar_pwrc_init_suspend_to_ram();
305*499c2713SBiju Das #endif
306*499c2713SBiju Das 	return 0;
307*499c2713SBiju Das }
308*499c2713SBiju Das 
309