1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017 - 2020, Broadcom 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <inttypes.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <arch_helpers.h> 12*91f16700Schasinglulu #include <common/debug.h> 13*91f16700Schasinglulu #include <drivers/arm/ccn.h> 14*91f16700Schasinglulu #include <lib/bakery_lock.h> 15*91f16700Schasinglulu #include <lib/mmio.h> 16*91f16700Schasinglulu #include <lib/psci/psci.h> 17*91f16700Schasinglulu #include <lib/spinlock.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu #include <brcm_scpi.h> 20*91f16700Schasinglulu #include <chimp.h> 21*91f16700Schasinglulu #include <cmn_plat_util.h> 22*91f16700Schasinglulu #include <plat_brcm.h> 23*91f16700Schasinglulu #include <platform_def.h> 24*91f16700Schasinglulu #include <sr_utils.h> 25*91f16700Schasinglulu 26*91f16700Schasinglulu #include "m0_cfg.h" 27*91f16700Schasinglulu 28*91f16700Schasinglulu 29*91f16700Schasinglulu #define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0]) 30*91f16700Schasinglulu #define CLUSTER_PWR_STATE(state) \ 31*91f16700Schasinglulu ((state)->pwr_domain_state[MPIDR_AFFLVL1]) 32*91f16700Schasinglulu #define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL2]) 33*91f16700Schasinglulu 34*91f16700Schasinglulu #define VENDOR_RST_TYPE_SHIFT 4 35*91f16700Schasinglulu 36*91f16700Schasinglulu #if HW_ASSISTED_COHERENCY 37*91f16700Schasinglulu /* 38*91f16700Schasinglulu * On systems where participant CPUs are cache-coherent, we can use spinlocks 39*91f16700Schasinglulu * instead of bakery locks. 40*91f16700Schasinglulu */ 41*91f16700Schasinglulu spinlock_t event_lock; 42*91f16700Schasinglulu #define event_lock_get(_lock) spin_lock(&_lock) 43*91f16700Schasinglulu #define event_lock_release(_lock) spin_unlock(&_lock) 44*91f16700Schasinglulu 45*91f16700Schasinglulu #else 46*91f16700Schasinglulu /* 47*91f16700Schasinglulu * Use bakery locks for state coordination as not all participants are 48*91f16700Schasinglulu * cache coherent now. 49*91f16700Schasinglulu */ 50*91f16700Schasinglulu DEFINE_BAKERY_LOCK(event_lock); 51*91f16700Schasinglulu #define event_lock_get(_lock) bakery_lock_get(&_lock) 52*91f16700Schasinglulu #define event_lock_release(_lock) bakery_lock_release(&_lock) 53*91f16700Schasinglulu #endif 54*91f16700Schasinglulu 55*91f16700Schasinglulu static int brcm_pwr_domain_on(u_register_t mpidr) 56*91f16700Schasinglulu { 57*91f16700Schasinglulu /* 58*91f16700Schasinglulu * SCP takes care of powering up parent power domains so we 59*91f16700Schasinglulu * only need to care about level 0 60*91f16700Schasinglulu */ 61*91f16700Schasinglulu scpi_set_brcm_power_state(mpidr, scpi_power_on, scpi_power_on, 62*91f16700Schasinglulu scpi_power_on); 63*91f16700Schasinglulu 64*91f16700Schasinglulu return PSCI_E_SUCCESS; 65*91f16700Schasinglulu } 66*91f16700Schasinglulu 67*91f16700Schasinglulu /******************************************************************************* 68*91f16700Schasinglulu * Handler called when a power level has just been powered on after 69*91f16700Schasinglulu * being turned off earlier. The target_state encodes the low power state that 70*91f16700Schasinglulu * each level has woken up from. This handler would never be invoked with 71*91f16700Schasinglulu * the system power domain uninitialized as either the primary would have taken 72*91f16700Schasinglulu * care of it as part of cold boot or the first core awakened from system 73*91f16700Schasinglulu * suspend would have already initialized it. 74*91f16700Schasinglulu ******************************************************************************/ 75*91f16700Schasinglulu static void brcm_pwr_domain_on_finish(const psci_power_state_t *target_state) 76*91f16700Schasinglulu { 77*91f16700Schasinglulu unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr()); 78*91f16700Schasinglulu 79*91f16700Schasinglulu /* Assert that the system power domain need not be initialized */ 80*91f16700Schasinglulu assert(SYSTEM_PWR_STATE(target_state) == PLAT_LOCAL_STATE_RUN); 81*91f16700Schasinglulu 82*91f16700Schasinglulu assert(CORE_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF); 83*91f16700Schasinglulu 84*91f16700Schasinglulu /* 85*91f16700Schasinglulu * Perform the common cluster specific operations i.e enable coherency 86*91f16700Schasinglulu * if this cluster was off. 87*91f16700Schasinglulu */ 88*91f16700Schasinglulu if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF) { 89*91f16700Schasinglulu INFO("Cluster #%lu entering to snoop/dvm domain\n", cluster_id); 90*91f16700Schasinglulu ccn_enter_snoop_dvm_domain(1 << cluster_id); 91*91f16700Schasinglulu } 92*91f16700Schasinglulu 93*91f16700Schasinglulu /* Program the gic per-cpu distributor or re-distributor interface */ 94*91f16700Schasinglulu plat_brcm_gic_pcpu_init(); 95*91f16700Schasinglulu 96*91f16700Schasinglulu /* Enable the gic cpu interface */ 97*91f16700Schasinglulu plat_brcm_gic_cpuif_enable(); 98*91f16700Schasinglulu } 99*91f16700Schasinglulu 100*91f16700Schasinglulu static void brcm_power_down_common(void) 101*91f16700Schasinglulu { 102*91f16700Schasinglulu unsigned int standbywfil2, standbywfi; 103*91f16700Schasinglulu uint64_t mpidr = read_mpidr_el1(); 104*91f16700Schasinglulu 105*91f16700Schasinglulu switch (MPIDR_AFFLVL1_VAL(mpidr)) { 106*91f16700Schasinglulu case 0x0: 107*91f16700Schasinglulu standbywfi = CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFI; 108*91f16700Schasinglulu standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH0_CDRU_STANDBYWFIL2; 109*91f16700Schasinglulu break; 110*91f16700Schasinglulu case 0x1: 111*91f16700Schasinglulu standbywfi = CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFI; 112*91f16700Schasinglulu standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH1_CDRU_STANDBYWFIL2; 113*91f16700Schasinglulu break; 114*91f16700Schasinglulu case 0x2: 115*91f16700Schasinglulu standbywfi = CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFI; 116*91f16700Schasinglulu standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH2_CDRU_STANDBYWFIL2; 117*91f16700Schasinglulu break; 118*91f16700Schasinglulu case 0x3: 119*91f16700Schasinglulu standbywfi = CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFI; 120*91f16700Schasinglulu standbywfil2 = CDRU_PROC_EVENT_CLEAR__IH3_CDRU_STANDBYWFIL2; 121*91f16700Schasinglulu break; 122*91f16700Schasinglulu default: 123*91f16700Schasinglulu ERROR("Invalid cluster #%" PRIx64 "\n", MPIDR_AFFLVL1_VAL(mpidr)); 124*91f16700Schasinglulu return; 125*91f16700Schasinglulu } 126*91f16700Schasinglulu /* Clear the WFI status bit */ 127*91f16700Schasinglulu event_lock_get(event_lock); 128*91f16700Schasinglulu mmio_setbits_32(CDRU_PROC_EVENT_CLEAR, 129*91f16700Schasinglulu (1 << (standbywfi + MPIDR_AFFLVL0_VAL(mpidr))) | 130*91f16700Schasinglulu (1 << standbywfil2)); 131*91f16700Schasinglulu event_lock_release(event_lock); 132*91f16700Schasinglulu } 133*91f16700Schasinglulu 134*91f16700Schasinglulu /* 135*91f16700Schasinglulu * Helper function to inform power down state to SCP. 136*91f16700Schasinglulu */ 137*91f16700Schasinglulu static void brcm_scp_suspend(const psci_power_state_t *target_state) 138*91f16700Schasinglulu { 139*91f16700Schasinglulu uint32_t cluster_state = scpi_power_on; 140*91f16700Schasinglulu uint32_t system_state = scpi_power_on; 141*91f16700Schasinglulu 142*91f16700Schasinglulu /* Check if power down at system power domain level is requested */ 143*91f16700Schasinglulu if (SYSTEM_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF) 144*91f16700Schasinglulu system_state = scpi_power_retention; 145*91f16700Schasinglulu 146*91f16700Schasinglulu /* Check if Cluster is to be turned off */ 147*91f16700Schasinglulu if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF) 148*91f16700Schasinglulu cluster_state = scpi_power_off; 149*91f16700Schasinglulu 150*91f16700Schasinglulu /* 151*91f16700Schasinglulu * Ask the SCP to power down the appropriate components depending upon 152*91f16700Schasinglulu * their state. 153*91f16700Schasinglulu */ 154*91f16700Schasinglulu scpi_set_brcm_power_state(read_mpidr_el1(), 155*91f16700Schasinglulu scpi_power_off, 156*91f16700Schasinglulu cluster_state, 157*91f16700Schasinglulu system_state); 158*91f16700Schasinglulu } 159*91f16700Schasinglulu 160*91f16700Schasinglulu /* 161*91f16700Schasinglulu * Helper function to turn off a CPU power domain and its parent power domains 162*91f16700Schasinglulu * if applicable. Since SCPI doesn't differentiate between OFF and suspend, we 163*91f16700Schasinglulu * call the suspend helper here. 164*91f16700Schasinglulu */ 165*91f16700Schasinglulu static void brcm_scp_off(const psci_power_state_t *target_state) 166*91f16700Schasinglulu { 167*91f16700Schasinglulu brcm_scp_suspend(target_state); 168*91f16700Schasinglulu } 169*91f16700Schasinglulu 170*91f16700Schasinglulu static void brcm_pwr_domain_off(const psci_power_state_t *target_state) 171*91f16700Schasinglulu { 172*91f16700Schasinglulu unsigned long cluster_id = MPIDR_AFFLVL1_VAL(read_mpidr_el1()); 173*91f16700Schasinglulu 174*91f16700Schasinglulu assert(CORE_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF); 175*91f16700Schasinglulu /* Prevent interrupts from spuriously waking up this cpu */ 176*91f16700Schasinglulu plat_brcm_gic_cpuif_disable(); 177*91f16700Schasinglulu 178*91f16700Schasinglulu /* Turn redistributor off */ 179*91f16700Schasinglulu plat_brcm_gic_redistif_off(); 180*91f16700Schasinglulu 181*91f16700Schasinglulu /* If Cluster is to be turned off, disable coherency */ 182*91f16700Schasinglulu if (CLUSTER_PWR_STATE(target_state) == PLAT_LOCAL_STATE_OFF) 183*91f16700Schasinglulu ccn_exit_snoop_dvm_domain(1 << cluster_id); 184*91f16700Schasinglulu 185*91f16700Schasinglulu brcm_power_down_common(); 186*91f16700Schasinglulu 187*91f16700Schasinglulu brcm_scp_off(target_state); 188*91f16700Schasinglulu } 189*91f16700Schasinglulu 190*91f16700Schasinglulu /******************************************************************************* 191*91f16700Schasinglulu * Handler called when the CPU power domain is about to enter standby. 192*91f16700Schasinglulu ******************************************************************************/ 193*91f16700Schasinglulu static void brcm_cpu_standby(plat_local_state_t cpu_state) 194*91f16700Schasinglulu { 195*91f16700Schasinglulu unsigned int scr; 196*91f16700Schasinglulu 197*91f16700Schasinglulu assert(cpu_state == PLAT_LOCAL_STATE_RET); 198*91f16700Schasinglulu 199*91f16700Schasinglulu scr = read_scr_el3(); 200*91f16700Schasinglulu /* 201*91f16700Schasinglulu * Enable the Non secure interrupt to wake the CPU. 202*91f16700Schasinglulu * In GICv3 affinity routing mode, the non secure group1 interrupts use 203*91f16700Schasinglulu * the PhysicalFIQ at EL3 whereas in GICv2, it uses the PhysicalIRQ. 204*91f16700Schasinglulu * Enabling both the bits works for both GICv2 mode and GICv3 affinity 205*91f16700Schasinglulu * routing mode. 206*91f16700Schasinglulu */ 207*91f16700Schasinglulu write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); 208*91f16700Schasinglulu isb(); 209*91f16700Schasinglulu dsb(); 210*91f16700Schasinglulu wfi(); 211*91f16700Schasinglulu 212*91f16700Schasinglulu /* 213*91f16700Schasinglulu * Restore SCR to the original value, synchronisation of scr_el3 is 214*91f16700Schasinglulu * done by eret while el3_exit to save some execution cycles. 215*91f16700Schasinglulu */ 216*91f16700Schasinglulu write_scr_el3(scr); 217*91f16700Schasinglulu } 218*91f16700Schasinglulu 219*91f16700Schasinglulu /* 220*91f16700Schasinglulu * Helper function to shutdown the system via SCPI. 221*91f16700Schasinglulu */ 222*91f16700Schasinglulu static void __dead2 brcm_scp_sys_shutdown(void) 223*91f16700Schasinglulu { 224*91f16700Schasinglulu /* 225*91f16700Schasinglulu * Disable GIC CPU interface to prevent pending interrupt 226*91f16700Schasinglulu * from waking up the AP from WFI. 227*91f16700Schasinglulu */ 228*91f16700Schasinglulu plat_brcm_gic_cpuif_disable(); 229*91f16700Schasinglulu 230*91f16700Schasinglulu /* Flush and invalidate data cache */ 231*91f16700Schasinglulu dcsw_op_all(DCCISW); 232*91f16700Schasinglulu 233*91f16700Schasinglulu /* Bring Cluster out of coherency domain as its going to die */ 234*91f16700Schasinglulu plat_brcm_interconnect_exit_coherency(); 235*91f16700Schasinglulu 236*91f16700Schasinglulu brcm_power_down_common(); 237*91f16700Schasinglulu 238*91f16700Schasinglulu /* Send the power down request to the SCP */ 239*91f16700Schasinglulu scpi_sys_power_state(scpi_system_shutdown); 240*91f16700Schasinglulu 241*91f16700Schasinglulu wfi(); 242*91f16700Schasinglulu ERROR("BRCM System Off: operation not handled.\n"); 243*91f16700Schasinglulu panic(); 244*91f16700Schasinglulu } 245*91f16700Schasinglulu 246*91f16700Schasinglulu /* 247*91f16700Schasinglulu * Helper function to reset the system 248*91f16700Schasinglulu */ 249*91f16700Schasinglulu static void __dead2 brcm_scp_sys_reset(unsigned int reset_type) 250*91f16700Schasinglulu { 251*91f16700Schasinglulu /* 252*91f16700Schasinglulu * Disable GIC CPU interface to prevent pending interrupt 253*91f16700Schasinglulu * from waking up the AP from WFI. 254*91f16700Schasinglulu */ 255*91f16700Schasinglulu plat_brcm_gic_cpuif_disable(); 256*91f16700Schasinglulu 257*91f16700Schasinglulu /* Flush and invalidate data cache */ 258*91f16700Schasinglulu dcsw_op_all(DCCISW); 259*91f16700Schasinglulu 260*91f16700Schasinglulu /* Bring Cluster out of coherency domain as its going to die */ 261*91f16700Schasinglulu plat_brcm_interconnect_exit_coherency(); 262*91f16700Schasinglulu 263*91f16700Schasinglulu brcm_power_down_common(); 264*91f16700Schasinglulu 265*91f16700Schasinglulu /* Send the system reset request to the SCP 266*91f16700Schasinglulu * 267*91f16700Schasinglulu * As per PSCI spec system power state could be 268*91f16700Schasinglulu * 0-> Shutdown 269*91f16700Schasinglulu * 1-> Reboot- Board level Reset 270*91f16700Schasinglulu * 2-> Reset - SoC level Reset 271*91f16700Schasinglulu * 272*91f16700Schasinglulu * Spec allocates 8 bits, 2 nibble, for this. One nibble is sufficient 273*91f16700Schasinglulu * for sending the state hence We are utilizing 2nd nibble for vendor 274*91f16700Schasinglulu * define reset type. 275*91f16700Schasinglulu */ 276*91f16700Schasinglulu scpi_sys_power_state((reset_type << VENDOR_RST_TYPE_SHIFT) | 277*91f16700Schasinglulu scpi_system_reboot); 278*91f16700Schasinglulu 279*91f16700Schasinglulu wfi(); 280*91f16700Schasinglulu ERROR("BRCM System Reset: operation not handled.\n"); 281*91f16700Schasinglulu panic(); 282*91f16700Schasinglulu } 283*91f16700Schasinglulu 284*91f16700Schasinglulu static void __dead2 brcm_system_reset(void) 285*91f16700Schasinglulu { 286*91f16700Schasinglulu unsigned int reset_type; 287*91f16700Schasinglulu 288*91f16700Schasinglulu if (bcm_chimp_is_nic_mode()) 289*91f16700Schasinglulu reset_type = SOFT_RESET_L3; 290*91f16700Schasinglulu else 291*91f16700Schasinglulu reset_type = SOFT_SYS_RESET_L1; 292*91f16700Schasinglulu 293*91f16700Schasinglulu brcm_scp_sys_reset(reset_type); 294*91f16700Schasinglulu } 295*91f16700Schasinglulu 296*91f16700Schasinglulu static int brcm_system_reset2(int is_vendor, int reset_type, 297*91f16700Schasinglulu u_register_t cookie) 298*91f16700Schasinglulu { 299*91f16700Schasinglulu if (!is_vendor) { 300*91f16700Schasinglulu /* Architectural warm boot: only warm reset is supported */ 301*91f16700Schasinglulu reset_type = SOFT_RESET_L3; 302*91f16700Schasinglulu } else { 303*91f16700Schasinglulu uint32_t boot_source = (uint32_t)cookie; 304*91f16700Schasinglulu 305*91f16700Schasinglulu boot_source &= BOOT_SOURCE_MASK; 306*91f16700Schasinglulu brcm_stingray_set_straps(boot_source); 307*91f16700Schasinglulu } 308*91f16700Schasinglulu brcm_scp_sys_reset(reset_type); 309*91f16700Schasinglulu 310*91f16700Schasinglulu /* 311*91f16700Schasinglulu * brcm_scp_sys_reset cannot return (it is a __dead function), 312*91f16700Schasinglulu * but brcm_system_reset2 has to return some value, even in 313*91f16700Schasinglulu * this case. 314*91f16700Schasinglulu */ 315*91f16700Schasinglulu return 0; 316*91f16700Schasinglulu } 317*91f16700Schasinglulu 318*91f16700Schasinglulu static int brcm_validate_ns_entrypoint(uintptr_t entrypoint) 319*91f16700Schasinglulu { 320*91f16700Schasinglulu /* 321*91f16700Schasinglulu * Check if the non secure entrypoint lies within the non 322*91f16700Schasinglulu * secure DRAM. 323*91f16700Schasinglulu */ 324*91f16700Schasinglulu if ((entrypoint >= BRCM_NS_DRAM1_BASE) && 325*91f16700Schasinglulu (entrypoint < (BRCM_NS_DRAM1_BASE + BRCM_NS_DRAM1_SIZE))) 326*91f16700Schasinglulu return PSCI_E_SUCCESS; 327*91f16700Schasinglulu #ifdef __aarch64__ 328*91f16700Schasinglulu if ((entrypoint >= BRCM_DRAM2_BASE) && 329*91f16700Schasinglulu (entrypoint < (BRCM_DRAM2_BASE + BRCM_DRAM2_SIZE))) 330*91f16700Schasinglulu return PSCI_E_SUCCESS; 331*91f16700Schasinglulu 332*91f16700Schasinglulu if ((entrypoint >= BRCM_DRAM3_BASE) && 333*91f16700Schasinglulu (entrypoint < (BRCM_DRAM3_BASE + BRCM_DRAM3_SIZE))) 334*91f16700Schasinglulu return PSCI_E_SUCCESS; 335*91f16700Schasinglulu #endif 336*91f16700Schasinglulu 337*91f16700Schasinglulu return PSCI_E_INVALID_ADDRESS; 338*91f16700Schasinglulu } 339*91f16700Schasinglulu 340*91f16700Schasinglulu /******************************************************************************* 341*91f16700Schasinglulu * ARM standard platform handler called to check the validity of the power state 342*91f16700Schasinglulu * parameter. 343*91f16700Schasinglulu ******************************************************************************/ 344*91f16700Schasinglulu static int brcm_validate_power_state(unsigned int power_state, 345*91f16700Schasinglulu psci_power_state_t *req_state) 346*91f16700Schasinglulu { 347*91f16700Schasinglulu int pstate = psci_get_pstate_type(power_state); 348*91f16700Schasinglulu int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 349*91f16700Schasinglulu int i; 350*91f16700Schasinglulu 351*91f16700Schasinglulu assert(req_state); 352*91f16700Schasinglulu 353*91f16700Schasinglulu if (pwr_lvl > PLAT_MAX_PWR_LVL) 354*91f16700Schasinglulu return PSCI_E_INVALID_PARAMS; 355*91f16700Schasinglulu 356*91f16700Schasinglulu /* Sanity check the requested state */ 357*91f16700Schasinglulu if (pstate == PSTATE_TYPE_STANDBY) { 358*91f16700Schasinglulu /* 359*91f16700Schasinglulu * It's possible to enter standby only on power level 0 360*91f16700Schasinglulu * Ignore any other power level. 361*91f16700Schasinglulu */ 362*91f16700Schasinglulu if (pwr_lvl != MPIDR_AFFLVL0) 363*91f16700Schasinglulu return PSCI_E_INVALID_PARAMS; 364*91f16700Schasinglulu 365*91f16700Schasinglulu req_state->pwr_domain_state[MPIDR_AFFLVL0] = 366*91f16700Schasinglulu PLAT_LOCAL_STATE_RET; 367*91f16700Schasinglulu } else { 368*91f16700Schasinglulu for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) 369*91f16700Schasinglulu req_state->pwr_domain_state[i] = 370*91f16700Schasinglulu PLAT_LOCAL_STATE_OFF; 371*91f16700Schasinglulu } 372*91f16700Schasinglulu 373*91f16700Schasinglulu /* 374*91f16700Schasinglulu * We expect the 'state id' to be zero. 375*91f16700Schasinglulu */ 376*91f16700Schasinglulu if (psci_get_pstate_id(power_state)) 377*91f16700Schasinglulu return PSCI_E_INVALID_PARAMS; 378*91f16700Schasinglulu 379*91f16700Schasinglulu return PSCI_E_SUCCESS; 380*91f16700Schasinglulu } 381*91f16700Schasinglulu 382*91f16700Schasinglulu /******************************************************************************* 383*91f16700Schasinglulu * Export the platform handlers via plat_brcm_psci_pm_ops. The ARM Standard 384*91f16700Schasinglulu * platform will take care of registering the handlers with PSCI. 385*91f16700Schasinglulu ******************************************************************************/ 386*91f16700Schasinglulu plat_psci_ops_t plat_brcm_psci_pm_ops = { 387*91f16700Schasinglulu .pwr_domain_on = brcm_pwr_domain_on, 388*91f16700Schasinglulu .pwr_domain_on_finish = brcm_pwr_domain_on_finish, 389*91f16700Schasinglulu .pwr_domain_off = brcm_pwr_domain_off, 390*91f16700Schasinglulu .cpu_standby = brcm_cpu_standby, 391*91f16700Schasinglulu .system_off = brcm_scp_sys_shutdown, 392*91f16700Schasinglulu .system_reset = brcm_system_reset, 393*91f16700Schasinglulu .system_reset2 = brcm_system_reset2, 394*91f16700Schasinglulu .validate_ns_entrypoint = brcm_validate_ns_entrypoint, 395*91f16700Schasinglulu .validate_power_state = brcm_validate_power_state, 396*91f16700Schasinglulu }; 397*91f16700Schasinglulu 398*91f16700Schasinglulu int plat_setup_psci_ops(uintptr_t sec_entrypoint, 399*91f16700Schasinglulu const struct plat_psci_ops **psci_ops) 400*91f16700Schasinglulu { 401*91f16700Schasinglulu *psci_ops = &plat_brcm_psci_pm_ops; 402*91f16700Schasinglulu 403*91f16700Schasinglulu /* Setup mailbox with entry point. */ 404*91f16700Schasinglulu mmio_write_64(CRMU_CFG_BASE + offsetof(M0CFG, core_cfg.rvbar), 405*91f16700Schasinglulu sec_entrypoint); 406*91f16700Schasinglulu 407*91f16700Schasinglulu return 0; 408*91f16700Schasinglulu } 409