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 #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 #if RCAR_SYSTEM_SUSPEND
133 if (SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
134 rcar_pwrc_suspend_to_ram();
135 #endif
136 }
137
rcar_pwr_domain_suspend_finish(const psci_power_state_t * target_state)138 static void rcar_pwr_domain_suspend_finish(const psci_power_state_t
139 *target_state)
140 {
141 uint32_t cluster_type = rcar_pwrc_get_cluster();
142
143 if (SYSTEM_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
144 goto finish;
145
146 plat_rcar_gic_driver_init();
147 plat_rcar_gic_init();
148
149 if (cluster_type == RCAR_CLUSTER_A53A57)
150 plat_cci_init();
151
152 rcar_pwrc_restore_timer_state();
153 rcar_pwrc_setup();
154 rcar_pwrc_code_copy_to_system_ram();
155
156 #if RCAR_SYSTEM_SUSPEND
157 rcar_pwrc_init_suspend_to_ram();
158 #endif
159 finish:
160 rcar_pwr_domain_on_finish(target_state);
161 }
162
rcar_system_off(void)163 static void __dead2 rcar_system_off(void)
164 {
165 #if PMIC_ROHM_BD9571
166 #if PMIC_LEVEL_MODE
167 if (rcar_iic_dvfs_send(PMIC, DVFS_SET_VID, DVFS_SET_VID_0V))
168 ERROR("BL3-1:Failed the SYSTEM-OFF.\n");
169 #else
170 if (rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, P_ALL_OFF))
171 ERROR("BL3-1:Failed the SYSTEM-RESET.\n");
172 #endif
173 #else
174 uint64_t cpu = read_mpidr_el1() & 0x0000ffff;
175 int32_t rtn_on;
176
177 rtn_on = rcar_pwrc_cpu_on_check(cpu);
178
179 if (cpu == rcar_boot_mpidr)
180 panic();
181
182 if (rtn_on)
183 panic();
184
185 rcar_pwrc_cpuoff(cpu);
186 rcar_pwrc_clusteroff(cpu);
187
188 #endif /* PMIC_ROHM_BD9571 */
189 wfi();
190 ERROR("RCAR System Off: operation not handled.\n");
191 panic();
192 }
193
rcar_system_reset(void)194 static void __dead2 rcar_system_reset(void)
195 {
196 #if PMIC_ROHM_BD9571
197 #if PMIC_LEVEL_MODE
198 #if RCAR_SYSTEM_RESET_KEEPON_DDR
199 uint8_t mode;
200 int32_t error;
201
202 error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, KEEP10_MAGIC);
203 if (error) {
204 ERROR("Failed send KEEP10 magic ret=%d\n", error);
205 goto done;
206 }
207
208 error = rcar_iic_dvfs_receive(PMIC, BKUP_MODE_CNT, &mode);
209 if (error) {
210 ERROR("Failed receive BKUP_Mode_Cnt ret=%d\n", error);
211 goto done;
212 }
213
214 mode |= KEEPON_DDR1C | KEEPON_DDR0C | KEEPON_DDR1 | KEEPON_DDR0;
215 error = rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, mode);
216 if (error) {
217 ERROR("Failed send KEEPON_DDRx ret=%d\n", error);
218 goto done;
219 }
220
221 rcar_pwrc_set_suspend_to_ram();
222 done:
223 #else
224 if (rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, P_ALL_OFF))
225 ERROR("BL3-1:Failed the SYSTEM-RESET.\n");
226 #endif
227 #else
228 #if (RCAR_GEN3_ULCB == 1)
229 rcar_cpld_reset_cpu();
230 #endif
231 #endif
232 #else
233 rcar_pwrc_system_reset();
234 #endif
235 wfi();
236
237 ERROR("RCAR System Reset: operation not handled.\n");
238 panic();
239 }
240
rcar_validate_power_state(unsigned int power_state,psci_power_state_t * req_state)241 static int rcar_validate_power_state(unsigned int power_state,
242 psci_power_state_t *req_state)
243 {
244 unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
245 unsigned int pstate = psci_get_pstate_type(power_state);
246 uint32_t i;
247
248 if (pstate == PSTATE_TYPE_STANDBY) {
249 if (pwr_lvl != MPIDR_AFFLVL0)
250 return PSCI_E_INVALID_PARAMS;
251
252 req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
253 } else {
254 for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
255 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
256 }
257
258 if (psci_get_pstate_id(power_state))
259 return PSCI_E_INVALID_PARAMS;
260
261 return PSCI_E_SUCCESS;
262 }
263
264 #if RCAR_SYSTEM_SUSPEND
rcar_get_sys_suspend_power_state(psci_power_state_t * req_state)265 static void rcar_get_sys_suspend_power_state(psci_power_state_t *req_state)
266 {
267 unsigned long mpidr = read_mpidr_el1() & 0x0000ffffU;
268 int i;
269
270 if (mpidr != rcar_boot_mpidr)
271 goto deny;
272
273 for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
274 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
275
276 return;
277 deny:
278 /* deny system suspend entry */
279 req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PSCI_LOCAL_STATE_RUN;
280 for (i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
281 req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE;
282 }
283 #endif
284
285 static const plat_psci_ops_t rcar_plat_psci_ops = {
286 .cpu_standby = rcar_cpu_standby,
287 .pwr_domain_on = rcar_pwr_domain_on,
288 .pwr_domain_off = rcar_pwr_domain_off,
289 .pwr_domain_suspend = rcar_pwr_domain_suspend,
290 .pwr_domain_on_finish = rcar_pwr_domain_on_finish,
291 .pwr_domain_suspend_finish = rcar_pwr_domain_suspend_finish,
292 .system_off = rcar_system_off,
293 .system_reset = rcar_system_reset,
294 .validate_power_state = rcar_validate_power_state,
295 #if RCAR_SYSTEM_SUSPEND
296 .get_sys_suspend_power_state = rcar_get_sys_suspend_power_state,
297 #endif
298 };
299
plat_setup_psci_ops(uintptr_t sec_entrypoint,const plat_psci_ops_t ** psci_ops)300 int plat_setup_psci_ops(uintptr_t sec_entrypoint, const plat_psci_ops_t **psci_ops)
301 {
302 *psci_ops = &rcar_plat_psci_ops;
303 rcar_sec_entrypoint = sec_entrypoint;
304
305 #if RCAR_SYSTEM_SUSPEND
306 rcar_pwrc_init_suspend_to_ram();
307 #endif
308 return 0;
309 }
310
311