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