diff options
Diffstat (limited to 'plat/arm/common/arm_pm.c')
-rw-r--r-- | plat/arm/common/arm_pm.c | 120 |
1 files changed, 89 insertions, 31 deletions
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c index 67c2b739..b2251700 100644 --- a/plat/arm/common/arm_pm.c +++ b/plat/arm/common/arm_pm.c @@ -29,60 +29,118 @@ */ #include <arch_helpers.h> +#include <arm_def.h> #include <assert.h> #include <errno.h> +#include <plat_arm.h> #include <psci.h> +#if ARM_RECOM_STATE_ID_ENC +extern unsigned int arm_pm_idle_states[]; +#endif /* __ARM_RECOM_STATE_ID_ENC__ */ + +#if !ARM_RECOM_STATE_ID_ENC /******************************************************************************* - * ARM standard platform utility function which is used to determine if any - * platform actions should be performed for the specified affinity instance - * given its state. Nothing needs to be done if the 'state' is not off or if - * this is not the highest affinity level which will enter the 'state'. + * ARM standard platform handler called to check the validity of the power state + * parameter. ******************************************************************************/ -int32_t arm_do_affinst_actions(unsigned int afflvl, unsigned int state) +int arm_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) { - unsigned int max_phys_off_afflvl; + int pstate = psci_get_pstate_type(power_state); + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int i; - assert(afflvl <= MPIDR_AFFLVL1); + assert(req_state); + + if (pwr_lvl > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; - if (state != PSCI_STATE_OFF) - return -EAGAIN; + /* Sanity check the requested state */ + if (pstate == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on power level 0 + * Ignore any other power level. + */ + if (pwr_lvl != ARM_PWR_LVL0) + return PSCI_E_INVALID_PARAMS; + + req_state->pwr_domain_state[ARM_PWR_LVL0] = + ARM_LOCAL_STATE_RET; + } else { + for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++) + req_state->pwr_domain_state[i] = + ARM_LOCAL_STATE_OFF; + } /* - * Find the highest affinity level which will be suspended and postpone - * all the platform specific actions until that level is hit. + * We expect the 'state id' to be zero. */ - max_phys_off_afflvl = psci_get_max_phys_off_afflvl(); - assert(max_phys_off_afflvl != PSCI_INVALID_DATA); - if (afflvl != max_phys_off_afflvl) - return -EAGAIN; + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; - return 0; + return PSCI_E_SUCCESS; } +#else /******************************************************************************* - * ARM standard platform handler called to check the validity of the power state - * parameter. + * ARM standard platform handler called to check the validity of the power + * state parameter. The power state parameter has to be a composite power + * state. ******************************************************************************/ -int arm_validate_power_state(unsigned int power_state) +int arm_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) { - /* Sanity check the requested state */ - if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) { - /* - * It's possible to enter standby only on affinity level 0 - * (i.e. a CPU on ARM standard platforms). - * Ignore any other affinity level. - */ - if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0) - return PSCI_E_INVALID_PARAMS; - } + unsigned int state_id; + int i; + + assert(req_state); /* - * We expect the 'state id' to be zero. + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. */ - if (psci_get_pstate_id(power_state)) + for (i = 0; !!arm_pm_idle_states[i]; i++) { + if (power_state == arm_pm_idle_states[i]) + break; + } + + /* Return error if entry not found in the idle state array */ + if (!arm_pm_idle_states[i]) return PSCI_E_INVALID_PARAMS; + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = state_id & + ARM_LOCAL_PSTATE_MASK; + state_id >>= ARM_LOCAL_PSTATE_WIDTH; + } + return PSCI_E_SUCCESS; } +#endif /* __ARM_RECOM_STATE_ID_ENC__ */ + +/******************************************************************************* + * ARM standard platform handler called to check the validity of the non secure + * entrypoint. + ******************************************************************************/ +int arm_validate_ns_entrypoint(uintptr_t entrypoint) +{ + /* + * Check if the non secure entrypoint lies within the non + * secure DRAM. + */ + if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < + (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) + return PSCI_E_SUCCESS; + if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint < + (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) + return PSCI_E_SUCCESS; + + return PSCI_E_INVALID_ADDRESS; +} |