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