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 43 static uintptr_t rcar_sec_entrypoint; 44 45 static void rcar_program_mailbox(u_register_t mpidr, uintptr_t address) 46 { 47 mailbox_t *rcar_mboxes = (mailbox_t *) MBOX_BASE; 48 uint64_t linear_id = plat_core_pos_by_mpidr(mpidr); 49 unsigned long range; 50 51 rcar_mboxes[linear_id].value = address; 52 range = (unsigned long)&rcar_mboxes[linear_id]; 53 54 flush_dcache_range(range, sizeof(range)); 55 } 56 57 static void rcar_cpu_standby(plat_local_state_t cpu_state) 58 { 59 u_register_t scr_el3 = read_scr_el3(); 60 61 write_scr_el3(scr_el3 | SCR_IRQ_BIT); 62 dsb(); 63 wfi(); 64 write_scr_el3(scr_el3); 65 } 66 67 static int rcar_pwr_domain_on(u_register_t mpidr) 68 { 69 rcar_program_mailbox(mpidr, rcar_sec_entrypoint); 70 rcar_pwrc_cpuon(mpidr); 71 72 return PSCI_E_SUCCESS; 73 } 74 75 static void rcar_pwr_domain_on_finish(const psci_power_state_t *target_state) 76 { 77 uint32_t cluster_type = rcar_pwrc_get_cluster(); 78 u_register_t mpidr = read_mpidr_el1(); 79 80 if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) 81 if (cluster_type == RCAR_CLUSTER_A53A57) 82 plat_cci_enable(); 83 84 rcar_program_mailbox(mpidr, 0); 85 rcar_pwrc_enable_interrupt_wakeup(mpidr); 86 87 gicv2_cpuif_enable(); 88 gicv2_pcpu_distif_init(); 89 } 90 91 static void rcar_pwr_domain_off(const psci_power_state_t *target_state) 92 { 93 #if RCAR_LSI != RCAR_D3 94 uint32_t cluster_type = rcar_pwrc_get_cluster(); 95 #endif 96 u_register_t mpidr = read_mpidr_el1(); 97 98 rcar_pwrc_disable_interrupt_wakeup(mpidr); 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 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 u_register_t 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 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 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 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 u_register_t mpidr = read_mpidr_el1(); 182 u_register_t cpu = mpidr & 0x0000ffffU; 183 int32_t rtn_on; 184 185 rtn_on = rcar_pwrc_cpu_on_check(mpidr); 186 187 if (cpu != rcar_boot_mpidr) { 188 panic(); 189 } 190 191 if (rtn_on != 0) { 192 panic(); 193 } 194 195 rcar_pwrc_cpuoff(mpidr); 196 rcar_pwrc_clusteroff(mpidr); 197 198 #endif /* PMIC_ROHM_BD9571 */ 199 wfi(); 200 ERROR("RCAR System Off: operation not handled.\n"); 201 panic(); 202 } 203 204 static void __dead2 rcar_system_reset(void) 205 { 206 #if PMIC_ROHM_BD9571 207 #if PMIC_LEVEL_MODE 208 #if RCAR_SYSTEM_RESET_KEEPON_DDR 209 uint8_t mode; 210 int32_t error; 211 212 error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, KEEP10_MAGIC); 213 if (error) { 214 ERROR("Failed send KEEP10 magic ret=%d\n", error); 215 goto done; 216 } 217 218 error = rcar_iic_dvfs_receive(PMIC, BKUP_MODE_CNT, &mode); 219 if (error) { 220 ERROR("Failed receive BKUP_Mode_Cnt ret=%d\n", error); 221 goto done; 222 } 223 224 mode |= KEEPON_DDR1C | KEEPON_DDR0C | KEEPON_DDR1 | KEEPON_DDR0; 225 error = rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, mode); 226 if (error) { 227 ERROR("Failed send KEEPON_DDRx ret=%d\n", error); 228 goto done; 229 } 230 231 rcar_pwrc_set_suspend_to_ram(); 232 done: 233 #else 234 if (rcar_iic_dvfs_send(PMIC, BKUP_MODE_CNT, P_ALL_OFF)) 235 ERROR("BL3-1:Failed the SYSTEM-RESET.\n"); 236 #endif 237 #else 238 #if (RCAR_GEN3_ULCB == 1) 239 rcar_cpld_reset_cpu(); 240 #endif 241 #endif 242 #else 243 rcar_pwrc_system_reset(); 244 #endif 245 wfi(); 246 247 ERROR("RCAR System Reset: operation not handled.\n"); 248 panic(); 249 } 250 251 static int rcar_validate_power_state(unsigned int power_state, 252 psci_power_state_t *req_state) 253 { 254 unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 255 unsigned int pstate = psci_get_pstate_type(power_state); 256 uint32_t i; 257 258 if (pstate == PSTATE_TYPE_STANDBY) { 259 if (pwr_lvl != MPIDR_AFFLVL0) 260 return PSCI_E_INVALID_PARAMS; 261 262 req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; 263 } else { 264 for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) 265 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 266 } 267 268 if (psci_get_pstate_id(power_state)) 269 return PSCI_E_INVALID_PARAMS; 270 271 return PSCI_E_SUCCESS; 272 } 273 274 #if RCAR_SYSTEM_SUSPEND 275 static void rcar_get_sys_suspend_power_state(psci_power_state_t *req_state) 276 { 277 u_register_t mpidr = read_mpidr_el1() & 0x0000ffffU; 278 int i; 279 280 if (mpidr != rcar_boot_mpidr) 281 goto deny; 282 283 for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) 284 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 285 286 return; 287 deny: 288 /* deny system suspend entry */ 289 req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PSCI_LOCAL_STATE_RUN; 290 for (i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++) 291 req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE; 292 } 293 #endif 294 295 static const plat_psci_ops_t rcar_plat_psci_ops = { 296 .cpu_standby = rcar_cpu_standby, 297 .pwr_domain_on = rcar_pwr_domain_on, 298 .pwr_domain_off = rcar_pwr_domain_off, 299 .pwr_domain_suspend = rcar_pwr_domain_suspend, 300 .pwr_domain_on_finish = rcar_pwr_domain_on_finish, 301 .pwr_domain_suspend_finish = rcar_pwr_domain_suspend_finish, 302 .system_off = rcar_system_off, 303 .system_reset = rcar_system_reset, 304 .validate_power_state = rcar_validate_power_state, 305 .pwr_domain_pwr_down_wfi = rcar_pwr_domain_pwr_down_wfi, 306 #if RCAR_SYSTEM_SUSPEND 307 .get_sys_suspend_power_state = rcar_get_sys_suspend_power_state, 308 #endif 309 }; 310 311 int plat_setup_psci_ops(uintptr_t sec_entrypoint, const plat_psci_ops_t **psci_ops) 312 { 313 *psci_ops = &rcar_plat_psci_ops; 314 rcar_sec_entrypoint = sec_entrypoint; 315 316 #if RCAR_SYSTEM_SUSPEND 317 rcar_pwrc_init_suspend_to_ram(); 318 #endif 319 return 0; 320 } 321 322