summaryrefslogtreecommitdiff
path: root/plat/arm/common/arm_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'plat/arm/common/arm_pm.c')
-rw-r--r--plat/arm/common/arm_pm.c120
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;
+}