1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015-2023, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * Copyright (C) 2017-2023 Nuvoton Ltd. 5*91f16700Schasinglulu * 6*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 7*91f16700Schasinglulu */ 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <assert.h> 10*91f16700Schasinglulu #include <stdbool.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <arch.h> 13*91f16700Schasinglulu #include <arch_helpers.h> 14*91f16700Schasinglulu #include <common/debug.h> 15*91f16700Schasinglulu #include <drivers/arm/gicv2.h> 16*91f16700Schasinglulu #include <lib/mmio.h> 17*91f16700Schasinglulu #include <lib/psci/psci.h> 18*91f16700Schasinglulu #include <lib/semihosting.h> 19*91f16700Schasinglulu #include <npcm845x_clock.h> 20*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h> 21*91f16700Schasinglulu #include <plat/common/platform.h> 22*91f16700Schasinglulu #include <plat_npcm845x.h> 23*91f16700Schasinglulu 24*91f16700Schasinglulu #define ADP_STOPPED_APPLICATION_EXIT 0x20026 25*91f16700Schasinglulu 26*91f16700Schasinglulu /* Make composite power state parameter till power level 0 */ 27*91f16700Schasinglulu #if PSCI_EXTENDED_STATE_ID 28*91f16700Schasinglulu /* Not Extended */ 29*91f16700Schasinglulu #define npcm845x_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ 30*91f16700Schasinglulu (((lvl0_state) << PSTATE_ID_SHIFT) | \ 31*91f16700Schasinglulu ((type) << PSTATE_TYPE_SHIFT)) 32*91f16700Schasinglulu #else 33*91f16700Schasinglulu #define npcm845x_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ 34*91f16700Schasinglulu (((lvl0_state) << PSTATE_ID_SHIFT) | \ 35*91f16700Schasinglulu ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \ 36*91f16700Schasinglulu ((type) << PSTATE_TYPE_SHIFT)) 37*91f16700Schasinglulu #endif /* PSCI_EXTENDED_STATE_ID */ 38*91f16700Schasinglulu 39*91f16700Schasinglulu #define npcm845x_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ 40*91f16700Schasinglulu (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \ 41*91f16700Schasinglulu npcm845x_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) 42*91f16700Schasinglulu 43*91f16700Schasinglulu /* 44*91f16700Schasinglulu * The table storing the valid idle power states. Ensure that the 45*91f16700Schasinglulu * array entries are populated in ascending order of state-id to 46*91f16700Schasinglulu * enable us to use binary search during power state validation. 47*91f16700Schasinglulu * The table must be terminated by a NULL entry. 48*91f16700Schasinglulu */ 49*91f16700Schasinglulu static const unsigned int npcm845x_pm_idle_states[] = { 50*91f16700Schasinglulu /* 51*91f16700Schasinglulu * Cluster = 0 (RUN) CPU=1 (RET, higest in idle) - 52*91f16700Schasinglulu * Retention. The Power state is Stand-by 53*91f16700Schasinglulu */ 54*91f16700Schasinglulu 55*91f16700Schasinglulu /* State-id - 0x01 */ 56*91f16700Schasinglulu npcm845x_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET, 57*91f16700Schasinglulu MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), 58*91f16700Schasinglulu 59*91f16700Schasinglulu /* 60*91f16700Schasinglulu * For testing purposes. 61*91f16700Schasinglulu * Only CPU suspend to standby is supported by NPCM845x 62*91f16700Schasinglulu */ 63*91f16700Schasinglulu /* State-id - 0x02 */ 64*91f16700Schasinglulu npcm845x_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF, 65*91f16700Schasinglulu MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), 66*91f16700Schasinglulu 0, 67*91f16700Schasinglulu }; 68*91f16700Schasinglulu 69*91f16700Schasinglulu /******************************************************************************* 70*91f16700Schasinglulu * Platform handler called to check the validity of the non secure 71*91f16700Schasinglulu * entrypoint. 72*91f16700Schasinglulu ******************************************************************************/ 73*91f16700Schasinglulu int npcm845x_validate_ns_entrypoint(uintptr_t entrypoint) 74*91f16700Schasinglulu { 75*91f16700Schasinglulu /* 76*91f16700Schasinglulu * Check if the non secure entrypoint lies within the non 77*91f16700Schasinglulu * secure DRAM. 78*91f16700Schasinglulu */ 79*91f16700Schasinglulu NOTICE("%s() nuvoton_psci\n", __func__); 80*91f16700Schasinglulu #ifdef PLAT_ARM_TRUSTED_DRAM_BASE 81*91f16700Schasinglulu if ((entrypoint >= PLAT_ARM_TRUSTED_DRAM_BASE) && 82*91f16700Schasinglulu (entrypoint < (PLAT_ARM_TRUSTED_DRAM_BASE + 83*91f16700Schasinglulu PLAT_ARM_TRUSTED_DRAM_SIZE))) { 84*91f16700Schasinglulu return PSCI_E_INVALID_ADDRESS; 85*91f16700Schasinglulu } 86*91f16700Schasinglulu #endif /* PLAT_ARM_TRUSTED_DRAM_BASE */ 87*91f16700Schasinglulu /* For TFTS purposes, '0' is also illegal */ 88*91f16700Schasinglulu #ifdef SPD_tspd 89*91f16700Schasinglulu if (entrypoint == 0) { 90*91f16700Schasinglulu return PSCI_E_INVALID_ADDRESS; 91*91f16700Schasinglulu } 92*91f16700Schasinglulu #endif /* SPD_tspd */ 93*91f16700Schasinglulu return PSCI_E_SUCCESS; 94*91f16700Schasinglulu } 95*91f16700Schasinglulu 96*91f16700Schasinglulu /******************************************************************************* 97*91f16700Schasinglulu * Platform handler called when a CPU is about to enter standby. 98*91f16700Schasinglulu ******************************************************************************/ 99*91f16700Schasinglulu void npcm845x_cpu_standby(plat_local_state_t cpu_state) 100*91f16700Schasinglulu { 101*91f16700Schasinglulu NOTICE("%s() nuvoton_psci\n", __func__); 102*91f16700Schasinglulu 103*91f16700Schasinglulu uint64_t scr; 104*91f16700Schasinglulu 105*91f16700Schasinglulu scr = read_scr_el3(); 106*91f16700Schasinglulu write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); 107*91f16700Schasinglulu 108*91f16700Schasinglulu /* 109*91f16700Schasinglulu * Enter standby state 110*91f16700Schasinglulu * dsb is good practice before using wfi to enter low power states 111*91f16700Schasinglulu */ 112*91f16700Schasinglulu isb(); 113*91f16700Schasinglulu dsb(); 114*91f16700Schasinglulu wfi(); 115*91f16700Schasinglulu 116*91f16700Schasinglulu /* Once awake */ 117*91f16700Schasinglulu write_scr_el3(scr); 118*91f16700Schasinglulu } 119*91f16700Schasinglulu 120*91f16700Schasinglulu /******************************************************************************* 121*91f16700Schasinglulu * Platform handler called when a power domain is about to be turned on. The 122*91f16700Schasinglulu * mpidr determines the CPU to be turned on. 123*91f16700Schasinglulu ******************************************************************************/ 124*91f16700Schasinglulu int npcm845x_pwr_domain_on(u_register_t mpidr) 125*91f16700Schasinglulu { 126*91f16700Schasinglulu int rc = PSCI_E_SUCCESS; 127*91f16700Schasinglulu int cpu_id = plat_core_pos_by_mpidr(mpidr); 128*91f16700Schasinglulu 129*91f16700Schasinglulu if ((unsigned int)cpu_id >= PLATFORM_CORE_COUNT) { 130*91f16700Schasinglulu ERROR("%s() CPU 0x%X\n", __func__, cpu_id); 131*91f16700Schasinglulu return PSCI_E_INVALID_PARAMS; 132*91f16700Schasinglulu } 133*91f16700Schasinglulu 134*91f16700Schasinglulu if (cpu_id == -1) { 135*91f16700Schasinglulu /* domain on was not called by a CPU */ 136*91f16700Schasinglulu ERROR("%s() was not per CPU 0x%X\n", __func__, cpu_id); 137*91f16700Schasinglulu return PSCI_E_INVALID_PARAMS; 138*91f16700Schasinglulu } 139*91f16700Schasinglulu 140*91f16700Schasinglulu unsigned int pos = (unsigned int)plat_core_pos_by_mpidr(mpidr); 141*91f16700Schasinglulu uintptr_t hold_base = PLAT_NPCM_TM_HOLD_BASE; 142*91f16700Schasinglulu 143*91f16700Schasinglulu assert(pos < PLATFORM_CORE_COUNT); 144*91f16700Schasinglulu 145*91f16700Schasinglulu hold_base += pos * PLAT_NPCM_TM_HOLD_ENTRY_SIZE; 146*91f16700Schasinglulu 147*91f16700Schasinglulu mmio_write_64(hold_base, PLAT_NPCM_TM_HOLD_STATE_GO); 148*91f16700Schasinglulu /* No cache maintenance here, hold_base is mapped as device memory. */ 149*91f16700Schasinglulu 150*91f16700Schasinglulu /* Make sure that the write has completed */ 151*91f16700Schasinglulu dsb(); 152*91f16700Schasinglulu isb(); 153*91f16700Schasinglulu 154*91f16700Schasinglulu sev(); 155*91f16700Schasinglulu 156*91f16700Schasinglulu return rc; 157*91f16700Schasinglulu } 158*91f16700Schasinglulu 159*91f16700Schasinglulu 160*91f16700Schasinglulu /******************************************************************************* 161*91f16700Schasinglulu * Platform handler called when a power domain is about to be suspended. The 162*91f16700Schasinglulu * target_state encodes the power state that each level should transition to. 163*91f16700Schasinglulu ******************************************************************************/ 164*91f16700Schasinglulu void npcm845x_pwr_domain_suspend(const psci_power_state_t *target_state) 165*91f16700Schasinglulu { 166*91f16700Schasinglulu NOTICE("%s() nuvoton_psci\n", __func__); 167*91f16700Schasinglulu 168*91f16700Schasinglulu for (size_t i = 0; (uint64_t)i <= PLAT_MAX_PWR_LVL; i++) { 169*91f16700Schasinglulu INFO("%s: target_state->pwr_domain_state[%lu]=%x\n", 170*91f16700Schasinglulu __func__, i, target_state->pwr_domain_state[i]); 171*91f16700Schasinglulu } 172*91f16700Schasinglulu 173*91f16700Schasinglulu gicv2_cpuif_disable(); 174*91f16700Schasinglulu 175*91f16700Schasinglulu NOTICE("%s() Out of suspend\n", __func__); 176*91f16700Schasinglulu } 177*91f16700Schasinglulu 178*91f16700Schasinglulu 179*91f16700Schasinglulu /******************************************************************************* 180*91f16700Schasinglulu * Platform handler called when a power domain has just been powered on after 181*91f16700Schasinglulu * being turned off earlier. The target_state encodes the low power state that 182*91f16700Schasinglulu * each level has woken up from. 183*91f16700Schasinglulu ******************************************************************************/ 184*91f16700Schasinglulu void npcm845x_pwr_domain_on_finish(const psci_power_state_t *target_state) 185*91f16700Schasinglulu { 186*91f16700Schasinglulu NOTICE("%s() nuvoton_psci\n", __func__); 187*91f16700Schasinglulu 188*91f16700Schasinglulu for (size_t i = 0; (uint64_t)i <= PLAT_MAX_PWR_LVL; i++) { 189*91f16700Schasinglulu INFO("%s: target_state->pwr_domain_state[%lu]=%x\n", 190*91f16700Schasinglulu __func__, i, target_state->pwr_domain_state[i]); 191*91f16700Schasinglulu } 192*91f16700Schasinglulu 193*91f16700Schasinglulu assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == 194*91f16700Schasinglulu PLAT_LOCAL_STATE_OFF); 195*91f16700Schasinglulu 196*91f16700Schasinglulu gicv2_pcpu_distif_init(); 197*91f16700Schasinglulu gicv2_cpuif_enable(); 198*91f16700Schasinglulu } 199*91f16700Schasinglulu 200*91f16700Schasinglulu 201*91f16700Schasinglulu /******************************************************************************* 202*91f16700Schasinglulu * Platform handler called when a power domain has just been powered on after 203*91f16700Schasinglulu * having been suspended earlier. The target_state encodes the low power state 204*91f16700Schasinglulu * that each level has woken up from. 205*91f16700Schasinglulu ******************************************************************************/ 206*91f16700Schasinglulu void npcm845x_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 207*91f16700Schasinglulu { 208*91f16700Schasinglulu NOTICE("%s() nuvoton_psci\n", __func__); 209*91f16700Schasinglulu 210*91f16700Schasinglulu for (size_t i = 0; (uint64_t)i <= PLAT_MAX_PWR_LVL; i++) { 211*91f16700Schasinglulu INFO("%s: target_state->pwr_domain_state[%lu]=%x\n", 212*91f16700Schasinglulu __func__, i, target_state->pwr_domain_state[i]); 213*91f16700Schasinglulu } 214*91f16700Schasinglulu 215*91f16700Schasinglulu assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == 216*91f16700Schasinglulu PLAT_LOCAL_STATE_OFF); 217*91f16700Schasinglulu 218*91f16700Schasinglulu gicv2_pcpu_distif_init(); 219*91f16700Schasinglulu gicv2_cpuif_enable(); 220*91f16700Schasinglulu } 221*91f16700Schasinglulu 222*91f16700Schasinglulu 223*91f16700Schasinglulu void __dead2 npcm845x_system_reset(void) 224*91f16700Schasinglulu { 225*91f16700Schasinglulu uintptr_t RESET_BASE_ADDR; 226*91f16700Schasinglulu uint32_t val; 227*91f16700Schasinglulu 228*91f16700Schasinglulu NOTICE("%s() nuvoton_psci\n", __func__); 229*91f16700Schasinglulu console_flush(); 230*91f16700Schasinglulu 231*91f16700Schasinglulu dsbsy(); 232*91f16700Schasinglulu isb(); 233*91f16700Schasinglulu 234*91f16700Schasinglulu /* 235*91f16700Schasinglulu * In future - support all reset types. For now, SW1 reset 236*91f16700Schasinglulu * Enable software reset 1 to reboot the BMC 237*91f16700Schasinglulu */ 238*91f16700Schasinglulu RESET_BASE_ADDR = (uintptr_t)0xF0801000; 239*91f16700Schasinglulu 240*91f16700Schasinglulu /* Read SW1 control register */ 241*91f16700Schasinglulu val = mmio_read_32(RESET_BASE_ADDR + 0x44); 242*91f16700Schasinglulu /* Keep SPI BMC & MC persist*/ 243*91f16700Schasinglulu val &= 0xFBFFFFDF; 244*91f16700Schasinglulu /* Setting SW1 control register */ 245*91f16700Schasinglulu mmio_write_32(RESET_BASE_ADDR + 0x44, val); 246*91f16700Schasinglulu /* Set SW1 reset */ 247*91f16700Schasinglulu mmio_write_32(RESET_BASE_ADDR + 0x14, 0x8); 248*91f16700Schasinglulu dsb(); 249*91f16700Schasinglulu 250*91f16700Schasinglulu while (1) { 251*91f16700Schasinglulu ; 252*91f16700Schasinglulu } 253*91f16700Schasinglulu } 254*91f16700Schasinglulu 255*91f16700Schasinglulu int npcm845x_validate_power_state(unsigned int power_state, 256*91f16700Schasinglulu psci_power_state_t *req_state) 257*91f16700Schasinglulu { 258*91f16700Schasinglulu unsigned int state_id; 259*91f16700Schasinglulu int i; 260*91f16700Schasinglulu 261*91f16700Schasinglulu NOTICE("%s() nuvoton_psci\n", __func__); 262*91f16700Schasinglulu assert(req_state); 263*91f16700Schasinglulu 264*91f16700Schasinglulu /* 265*91f16700Schasinglulu * Currently we are using a linear search for finding the matching 266*91f16700Schasinglulu * entry in the idle power state array. This can be made a binary 267*91f16700Schasinglulu * search if the number of entries justify the additional complexity. 268*91f16700Schasinglulu */ 269*91f16700Schasinglulu for (i = 0; !!npcm845x_pm_idle_states[i]; i++) { 270*91f16700Schasinglulu if (power_state == npcm845x_pm_idle_states[i]) { 271*91f16700Schasinglulu break; 272*91f16700Schasinglulu } 273*91f16700Schasinglulu } 274*91f16700Schasinglulu 275*91f16700Schasinglulu /* Return error if entry not found in the idle state array */ 276*91f16700Schasinglulu if (!npcm845x_pm_idle_states[i]) { 277*91f16700Schasinglulu return PSCI_E_INVALID_PARAMS; 278*91f16700Schasinglulu } 279*91f16700Schasinglulu 280*91f16700Schasinglulu i = 0; 281*91f16700Schasinglulu state_id = psci_get_pstate_id(power_state); 282*91f16700Schasinglulu 283*91f16700Schasinglulu /* Parse the State ID and populate the state info parameter */ 284*91f16700Schasinglulu while (state_id) { 285*91f16700Schasinglulu req_state->pwr_domain_state[i++] = (uint8_t)state_id & 286*91f16700Schasinglulu PLAT_LOCAL_PSTATE_MASK; 287*91f16700Schasinglulu state_id >>= PLAT_LOCAL_PSTATE_WIDTH; 288*91f16700Schasinglulu } 289*91f16700Schasinglulu 290*91f16700Schasinglulu return PSCI_E_SUCCESS; 291*91f16700Schasinglulu } 292*91f16700Schasinglulu 293*91f16700Schasinglulu /* 294*91f16700Schasinglulu * The NPCM845 doesn't truly support power management at SYSTEM power domain. 295*91f16700Schasinglulu * The SYSTEM_SUSPEND will be down-graded to the cluster level within 296*91f16700Schasinglulu * the platform layer. The `fake` SYSTEM_SUSPEND allows us to validate 297*91f16700Schasinglulu * some of the driver save and restore sequences on FVP. 298*91f16700Schasinglulu */ 299*91f16700Schasinglulu #if !ARM_BL31_IN_DRAM 300*91f16700Schasinglulu void npcm845x_get_sys_suspend_power_state(psci_power_state_t *req_state) 301*91f16700Schasinglulu { 302*91f16700Schasinglulu unsigned int i; 303*91f16700Schasinglulu 304*91f16700Schasinglulu NOTICE("%s() nuvoton_psci\n", __func__); 305*91f16700Schasinglulu 306*91f16700Schasinglulu for (i = ARM_PWR_LVL0; (uint64_t)i <= PLAT_MAX_PWR_LVL; i++) { 307*91f16700Schasinglulu req_state->pwr_domain_state[i] = (uint8_t)PLAT_LOCAL_STATE_OFF; 308*91f16700Schasinglulu } 309*91f16700Schasinglulu } 310*91f16700Schasinglulu #endif /* !ARM_BL31_IN_DRAM */ 311*91f16700Schasinglulu 312*91f16700Schasinglulu /* 313*91f16700Schasinglulu * The rest of the PSCI implementation are for testing purposes only. 314*91f16700Schasinglulu * Not supported in Arbel 315*91f16700Schasinglulu */ 316*91f16700Schasinglulu void __dead2 npcm845x_system_off(void) 317*91f16700Schasinglulu { 318*91f16700Schasinglulu console_flush(); 319*91f16700Schasinglulu 320*91f16700Schasinglulu dsbsy(); 321*91f16700Schasinglulu isb(); 322*91f16700Schasinglulu 323*91f16700Schasinglulu /* NPCM845 doesn't allow real system off, Do reaset instead */ 324*91f16700Schasinglulu /* Do reset here TBD which, in the meanwhile SW1 reset */ 325*91f16700Schasinglulu for (;;) { 326*91f16700Schasinglulu wfi(); 327*91f16700Schasinglulu } 328*91f16700Schasinglulu } 329*91f16700Schasinglulu 330*91f16700Schasinglulu void __dead2 plat_secondary_cold_boot_setup(void); 331*91f16700Schasinglulu 332*91f16700Schasinglulu void __dead2 npcm845x_pwr_down_wfi( 333*91f16700Schasinglulu const psci_power_state_t *target_state) 334*91f16700Schasinglulu { 335*91f16700Schasinglulu uintptr_t hold_base = PLAT_NPCM_TM_HOLD_BASE; 336*91f16700Schasinglulu unsigned int pos = plat_my_core_pos(); 337*91f16700Schasinglulu 338*91f16700Schasinglulu if (pos == 0) { 339*91f16700Schasinglulu /* 340*91f16700Schasinglulu * The secondaries will always be in a wait 341*91f16700Schasinglulu * for warm boot on reset, but the BSP needs 342*91f16700Schasinglulu * to be able to distinguish between waiting 343*91f16700Schasinglulu * for warm boot (e.g. after psci_off, waiting 344*91f16700Schasinglulu * for psci_on) and a cold boot. 345*91f16700Schasinglulu */ 346*91f16700Schasinglulu mmio_write_64(hold_base, PLAT_NPCM_TM_HOLD_STATE_BSP_OFF); 347*91f16700Schasinglulu /* No cache maintenance here, we run with caches off already. */ 348*91f16700Schasinglulu dsb(); 349*91f16700Schasinglulu isb(); 350*91f16700Schasinglulu } 351*91f16700Schasinglulu 352*91f16700Schasinglulu wfe(); 353*91f16700Schasinglulu 354*91f16700Schasinglulu while (1) { 355*91f16700Schasinglulu ; 356*91f16700Schasinglulu } 357*91f16700Schasinglulu } 358*91f16700Schasinglulu 359*91f16700Schasinglulu /******************************************************************************* 360*91f16700Schasinglulu * Platform handler called when a power domain is about to be turned off. The 361*91f16700Schasinglulu * target_state encodes the power state that each level should transition to. 362*91f16700Schasinglulu ******************************************************************************/ 363*91f16700Schasinglulu void npcm845x_pwr_domain_off(const psci_power_state_t *target_state) 364*91f16700Schasinglulu { 365*91f16700Schasinglulu NOTICE("%s() nuvoton_psci\n", __func__); 366*91f16700Schasinglulu 367*91f16700Schasinglulu for (size_t i = 0; (uint64_t)i <= PLAT_MAX_PWR_LVL; i++) { 368*91f16700Schasinglulu INFO("%s: target_state->pwr_domain_state[%lu]=%x\n", 369*91f16700Schasinglulu __func__, i, target_state->pwr_domain_state[i]); 370*91f16700Schasinglulu } 371*91f16700Schasinglulu 372*91f16700Schasinglulu plat_secondary_cold_boot_setup(); 373*91f16700Schasinglulu } 374*91f16700Schasinglulu 375*91f16700Schasinglulu static const plat_psci_ops_t npcm845x_plat_psci_ops = { 376*91f16700Schasinglulu .cpu_standby = npcm845x_cpu_standby, 377*91f16700Schasinglulu .pwr_domain_on = npcm845x_pwr_domain_on, 378*91f16700Schasinglulu .pwr_domain_suspend = npcm845x_pwr_domain_suspend, 379*91f16700Schasinglulu .pwr_domain_on_finish = npcm845x_pwr_domain_on_finish, 380*91f16700Schasinglulu .pwr_domain_suspend_finish = npcm845x_pwr_domain_suspend_finish, 381*91f16700Schasinglulu .system_reset = npcm845x_system_reset, 382*91f16700Schasinglulu .validate_power_state = npcm845x_validate_power_state, 383*91f16700Schasinglulu .validate_ns_entrypoint = npcm845x_validate_ns_entrypoint, 384*91f16700Schasinglulu 385*91f16700Schasinglulu /* For testing purposes only This PSCI states are not supported */ 386*91f16700Schasinglulu .pwr_domain_off = npcm845x_pwr_domain_off, 387*91f16700Schasinglulu .pwr_domain_pwr_down_wfi = npcm845x_pwr_down_wfi, 388*91f16700Schasinglulu }; 389*91f16700Schasinglulu 390*91f16700Schasinglulu /* For reference only 391*91f16700Schasinglulu * typedef struct plat_psci_ops { 392*91f16700Schasinglulu * void (*cpu_standby)(plat_local_state_t cpu_state); 393*91f16700Schasinglulu * int (*pwr_domain_on)(u_register_t mpidr); 394*91f16700Schasinglulu * void (*pwr_domain_off)(const psci_power_state_t *target_state); 395*91f16700Schasinglulu * void (*pwr_domain_suspend_pwrdown_early)( 396*91f16700Schasinglulu * const psci_power_state_t *target_state); 397*91f16700Schasinglulu * void (*pwr_domain_suspend)(const psci_power_state_t *target_state); 398*91f16700Schasinglulu * void (*pwr_domain_on_finish)(const psci_power_state_t *target_state); 399*91f16700Schasinglulu * void (*pwr_domain_on_finish_late)( 400*91f16700Schasinglulu * const psci_power_state_t *target_state); 401*91f16700Schasinglulu * void (*pwr_domain_suspend_finish)( 402*91f16700Schasinglulu * const psci_power_state_t *target_state); 403*91f16700Schasinglulu * void __dead2 (*pwr_domain_pwr_down_wfi)( 404*91f16700Schasinglulu * const psci_power_state_t *target_state); 405*91f16700Schasinglulu * void __dead2 (*system_off)(void); 406*91f16700Schasinglulu * void __dead2 (*system_reset)(void); 407*91f16700Schasinglulu * int (*validate_power_state)(unsigned int power_state, 408*91f16700Schasinglulu * psci_power_state_t *req_state); 409*91f16700Schasinglulu * int (*validate_ns_entrypoint)(uintptr_t ns_entrypoint); 410*91f16700Schasinglulu * void (*get_sys_suspend_power_state)( 411*91f16700Schasinglulu * psci_power_state_t *req_state); 412*91f16700Schasinglulu * int (*get_pwr_lvl_state_idx)(plat_local_state_t pwr_domain_state, 413*91f16700Schasinglulu * int pwrlvl); 414*91f16700Schasinglulu * int (*translate_power_state_by_mpidr)(u_register_t mpidr, 415*91f16700Schasinglulu * unsigned int power_state, 416*91f16700Schasinglulu * psci_power_state_t *output_state); 417*91f16700Schasinglulu * int (*get_node_hw_state)(u_register_t mpidr, unsigned int power_level); 418*91f16700Schasinglulu * int (*mem_protect_chk)(uintptr_t base, u_register_t length); 419*91f16700Schasinglulu * int (*read_mem_protect)(int *val); 420*91f16700Schasinglulu * int (*write_mem_protect)(int val); 421*91f16700Schasinglulu * int (*system_reset2)(int is_vendor, 422*91f16700Schasinglulu * int reset_type, u_register_t cookie); 423*91f16700Schasinglulu * } plat_psci_ops_t; 424*91f16700Schasinglulu */ 425*91f16700Schasinglulu 426*91f16700Schasinglulu int plat_setup_psci_ops(uintptr_t sec_entrypoint, 427*91f16700Schasinglulu const plat_psci_ops_t **psci_ops) 428*91f16700Schasinglulu { 429*91f16700Schasinglulu uintptr_t *entrypoint = (void *)PLAT_NPCM_TM_ENTRYPOINT; 430*91f16700Schasinglulu 431*91f16700Schasinglulu *entrypoint = sec_entrypoint; 432*91f16700Schasinglulu 433*91f16700Schasinglulu *psci_ops = &npcm845x_plat_psci_ops; 434*91f16700Schasinglulu 435*91f16700Schasinglulu return 0; 436*91f16700Schasinglulu } 437