1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <platform_def.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <arch_helpers.h> 12*91f16700Schasinglulu #include <lib/psci/psci.h> 13*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h> 14*91f16700Schasinglulu #include <plat/common/platform.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu /* Allow ARM Standard platforms to override these functions */ 17*91f16700Schasinglulu #pragma weak plat_arm_program_trusted_mailbox 18*91f16700Schasinglulu 19*91f16700Schasinglulu #if !ARM_RECOM_STATE_ID_ENC 20*91f16700Schasinglulu /******************************************************************************* 21*91f16700Schasinglulu * ARM standard platform handler called to check the validity of the power state 22*91f16700Schasinglulu * parameter. 23*91f16700Schasinglulu ******************************************************************************/ 24*91f16700Schasinglulu int arm_validate_power_state(unsigned int power_state, 25*91f16700Schasinglulu psci_power_state_t *req_state) 26*91f16700Schasinglulu { 27*91f16700Schasinglulu unsigned int pstate = psci_get_pstate_type(power_state); 28*91f16700Schasinglulu unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 29*91f16700Schasinglulu unsigned int i; 30*91f16700Schasinglulu 31*91f16700Schasinglulu assert(req_state != NULL); 32*91f16700Schasinglulu 33*91f16700Schasinglulu if (pwr_lvl > PLAT_MAX_PWR_LVL) 34*91f16700Schasinglulu return PSCI_E_INVALID_PARAMS; 35*91f16700Schasinglulu 36*91f16700Schasinglulu /* Sanity check the requested state */ 37*91f16700Schasinglulu if (pstate == PSTATE_TYPE_STANDBY) { 38*91f16700Schasinglulu /* 39*91f16700Schasinglulu * It's possible to enter standby only on power level 0 40*91f16700Schasinglulu * Ignore any other power level. 41*91f16700Schasinglulu */ 42*91f16700Schasinglulu if (pwr_lvl != ARM_PWR_LVL0) 43*91f16700Schasinglulu return PSCI_E_INVALID_PARAMS; 44*91f16700Schasinglulu 45*91f16700Schasinglulu req_state->pwr_domain_state[ARM_PWR_LVL0] = 46*91f16700Schasinglulu ARM_LOCAL_STATE_RET; 47*91f16700Schasinglulu } else { 48*91f16700Schasinglulu for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++) 49*91f16700Schasinglulu req_state->pwr_domain_state[i] = 50*91f16700Schasinglulu ARM_LOCAL_STATE_OFF; 51*91f16700Schasinglulu } 52*91f16700Schasinglulu 53*91f16700Schasinglulu /* 54*91f16700Schasinglulu * We expect the 'state id' to be zero. 55*91f16700Schasinglulu */ 56*91f16700Schasinglulu if (psci_get_pstate_id(power_state) != 0U) 57*91f16700Schasinglulu return PSCI_E_INVALID_PARAMS; 58*91f16700Schasinglulu 59*91f16700Schasinglulu return PSCI_E_SUCCESS; 60*91f16700Schasinglulu } 61*91f16700Schasinglulu 62*91f16700Schasinglulu #else 63*91f16700Schasinglulu /******************************************************************************* 64*91f16700Schasinglulu * ARM standard platform handler called to check the validity of the power 65*91f16700Schasinglulu * state parameter. The power state parameter has to be a composite power 66*91f16700Schasinglulu * state. 67*91f16700Schasinglulu ******************************************************************************/ 68*91f16700Schasinglulu int arm_validate_power_state(unsigned int power_state, 69*91f16700Schasinglulu psci_power_state_t *req_state) 70*91f16700Schasinglulu { 71*91f16700Schasinglulu unsigned int state_id; 72*91f16700Schasinglulu int i; 73*91f16700Schasinglulu 74*91f16700Schasinglulu assert(req_state != NULL); 75*91f16700Schasinglulu 76*91f16700Schasinglulu /* 77*91f16700Schasinglulu * Currently we are using a linear search for finding the matching 78*91f16700Schasinglulu * entry in the idle power state array. This can be made a binary 79*91f16700Schasinglulu * search if the number of entries justify the additional complexity. 80*91f16700Schasinglulu */ 81*91f16700Schasinglulu for (i = 0; !!arm_pm_idle_states[i]; i++) { 82*91f16700Schasinglulu #if PSCI_OS_INIT_MODE 83*91f16700Schasinglulu if ((power_state & ~ARM_LAST_AT_PLVL_MASK) == 84*91f16700Schasinglulu arm_pm_idle_states[i]) 85*91f16700Schasinglulu #else 86*91f16700Schasinglulu if (power_state == arm_pm_idle_states[i]) 87*91f16700Schasinglulu #endif /* __PSCI_OS_INIT_MODE__ */ 88*91f16700Schasinglulu break; 89*91f16700Schasinglulu } 90*91f16700Schasinglulu 91*91f16700Schasinglulu /* Return error if entry not found in the idle state array */ 92*91f16700Schasinglulu if (!arm_pm_idle_states[i]) 93*91f16700Schasinglulu return PSCI_E_INVALID_PARAMS; 94*91f16700Schasinglulu 95*91f16700Schasinglulu i = 0; 96*91f16700Schasinglulu state_id = psci_get_pstate_id(power_state); 97*91f16700Schasinglulu 98*91f16700Schasinglulu /* Parse the State ID and populate the state info parameter */ 99*91f16700Schasinglulu for (i = ARM_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) { 100*91f16700Schasinglulu req_state->pwr_domain_state[i] = state_id & 101*91f16700Schasinglulu ARM_LOCAL_PSTATE_MASK; 102*91f16700Schasinglulu state_id >>= ARM_LOCAL_PSTATE_WIDTH; 103*91f16700Schasinglulu } 104*91f16700Schasinglulu #if PSCI_OS_INIT_MODE 105*91f16700Schasinglulu req_state->last_at_pwrlvl = state_id & ARM_LOCAL_PSTATE_MASK; 106*91f16700Schasinglulu #endif /* __PSCI_OS_INIT_MODE__ */ 107*91f16700Schasinglulu 108*91f16700Schasinglulu return PSCI_E_SUCCESS; 109*91f16700Schasinglulu } 110*91f16700Schasinglulu #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 111*91f16700Schasinglulu 112*91f16700Schasinglulu /******************************************************************************* 113*91f16700Schasinglulu * ARM standard platform handler called to check the validity of the non secure 114*91f16700Schasinglulu * entrypoint. Returns 0 if the entrypoint is valid, or -1 otherwise. 115*91f16700Schasinglulu ******************************************************************************/ 116*91f16700Schasinglulu int arm_validate_ns_entrypoint(uintptr_t entrypoint) 117*91f16700Schasinglulu { 118*91f16700Schasinglulu /* 119*91f16700Schasinglulu * Check if the non secure entrypoint lies within the non 120*91f16700Schasinglulu * secure DRAM. 121*91f16700Schasinglulu */ 122*91f16700Schasinglulu if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < 123*91f16700Schasinglulu (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) { 124*91f16700Schasinglulu return 0; 125*91f16700Schasinglulu } 126*91f16700Schasinglulu #ifdef __aarch64__ 127*91f16700Schasinglulu if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint < 128*91f16700Schasinglulu (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) { 129*91f16700Schasinglulu return 0; 130*91f16700Schasinglulu } 131*91f16700Schasinglulu #endif 132*91f16700Schasinglulu 133*91f16700Schasinglulu return -1; 134*91f16700Schasinglulu } 135*91f16700Schasinglulu 136*91f16700Schasinglulu int arm_validate_psci_entrypoint(uintptr_t entrypoint) 137*91f16700Schasinglulu { 138*91f16700Schasinglulu return (arm_validate_ns_entrypoint(entrypoint) == 0) ? PSCI_E_SUCCESS : 139*91f16700Schasinglulu PSCI_E_INVALID_ADDRESS; 140*91f16700Schasinglulu } 141*91f16700Schasinglulu 142*91f16700Schasinglulu /****************************************************************************** 143*91f16700Schasinglulu * Helper function to save the platform state before a system suspend. Save the 144*91f16700Schasinglulu * state of the system components which are not in the Always ON power domain. 145*91f16700Schasinglulu *****************************************************************************/ 146*91f16700Schasinglulu void arm_system_pwr_domain_save(void) 147*91f16700Schasinglulu { 148*91f16700Schasinglulu /* Assert system power domain is available on the platform */ 149*91f16700Schasinglulu assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); 150*91f16700Schasinglulu 151*91f16700Schasinglulu plat_arm_gic_save(); 152*91f16700Schasinglulu 153*91f16700Schasinglulu /* 154*91f16700Schasinglulu * Unregister console now so that it is not registered for a second 155*91f16700Schasinglulu * time during resume. 156*91f16700Schasinglulu */ 157*91f16700Schasinglulu arm_console_runtime_end(); 158*91f16700Schasinglulu 159*91f16700Schasinglulu /* 160*91f16700Schasinglulu * All the other peripheral which are configured by ARM TF are 161*91f16700Schasinglulu * re-initialized on resume from system suspend. Hence we 162*91f16700Schasinglulu * don't save their state here. 163*91f16700Schasinglulu */ 164*91f16700Schasinglulu } 165*91f16700Schasinglulu 166*91f16700Schasinglulu /****************************************************************************** 167*91f16700Schasinglulu * Helper function to resume the platform from system suspend. Reinitialize 168*91f16700Schasinglulu * the system components which are not in the Always ON power domain. 169*91f16700Schasinglulu * TODO: Unify the platform setup when waking up from cold boot and system 170*91f16700Schasinglulu * resume in arm_bl31_platform_setup(). 171*91f16700Schasinglulu *****************************************************************************/ 172*91f16700Schasinglulu void arm_system_pwr_domain_resume(void) 173*91f16700Schasinglulu { 174*91f16700Schasinglulu /* Initialize the console */ 175*91f16700Schasinglulu arm_console_runtime_init(); 176*91f16700Schasinglulu 177*91f16700Schasinglulu /* Assert system power domain is available on the platform */ 178*91f16700Schasinglulu assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); 179*91f16700Schasinglulu 180*91f16700Schasinglulu plat_arm_gic_resume(); 181*91f16700Schasinglulu 182*91f16700Schasinglulu plat_arm_security_setup(); 183*91f16700Schasinglulu arm_configure_sys_timer(); 184*91f16700Schasinglulu } 185*91f16700Schasinglulu 186*91f16700Schasinglulu /******************************************************************************* 187*91f16700Schasinglulu * ARM platform function to program the mailbox for a cpu before it is released 188*91f16700Schasinglulu * from reset. This function assumes that the Trusted mail box base is within 189*91f16700Schasinglulu * the ARM_SHARED_RAM region 190*91f16700Schasinglulu ******************************************************************************/ 191*91f16700Schasinglulu void plat_arm_program_trusted_mailbox(uintptr_t address) 192*91f16700Schasinglulu { 193*91f16700Schasinglulu uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE; 194*91f16700Schasinglulu 195*91f16700Schasinglulu *mailbox = address; 196*91f16700Schasinglulu 197*91f16700Schasinglulu /* 198*91f16700Schasinglulu * Ensure that the PLAT_ARM_TRUSTED_MAILBOX_BASE is within 199*91f16700Schasinglulu * ARM_SHARED_RAM region. 200*91f16700Schasinglulu */ 201*91f16700Schasinglulu assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) && 202*91f16700Schasinglulu ((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <= 203*91f16700Schasinglulu (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE))); 204*91f16700Schasinglulu } 205*91f16700Schasinglulu 206*91f16700Schasinglulu /******************************************************************************* 207*91f16700Schasinglulu * The ARM Standard platform definition of platform porting API 208*91f16700Schasinglulu * `plat_setup_psci_ops`. 209*91f16700Schasinglulu ******************************************************************************/ 210*91f16700Schasinglulu int __init plat_setup_psci_ops(uintptr_t sec_entrypoint, 211*91f16700Schasinglulu const plat_psci_ops_t **psci_ops) 212*91f16700Schasinglulu { 213*91f16700Schasinglulu *psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops); 214*91f16700Schasinglulu 215*91f16700Schasinglulu /* Setup mailbox with entry point. */ 216*91f16700Schasinglulu plat_arm_program_trusted_mailbox(sec_entrypoint); 217*91f16700Schasinglulu return 0; 218*91f16700Schasinglulu } 219