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