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