summaryrefslogtreecommitdiff
path: root/services/std_svc/psci/psci_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'services/std_svc/psci/psci_main.c')
-rw-r--r--services/std_svc/psci/psci_main.c89
1 files changed, 63 insertions, 26 deletions
diff --git a/services/std_svc/psci/psci_main.c b/services/std_svc/psci/psci_main.c
index 2e700e8a..91d16f46 100644
--- a/services/std_svc/psci/psci_main.c
+++ b/services/std_svc/psci/psci_main.c
@@ -45,26 +45,44 @@ int psci_cpu_on(unsigned long target_cpu,
{
int rc;
unsigned int start_afflvl, end_afflvl;
+ entry_point_info_t ep;
/* Determine if the cpu exists of not */
rc = psci_validate_mpidr(target_cpu, MPIDR_AFFLVL0);
if (rc != PSCI_E_SUCCESS) {
- goto exit;
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ /* Validate the entrypoint using platform pm_ops */
+ if (psci_plat_pm_ops->validate_ns_entrypoint) {
+ rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint);
+ if (rc != PSCI_E_SUCCESS) {
+ assert(rc == PSCI_E_INVALID_PARAMS);
+ return PSCI_E_INVALID_PARAMS;
+ }
}
/*
+ * Verify and derive the re-entry information for
+ * the non-secure world from the non-secure state from
+ * where this call originated.
+ */
+ rc = psci_get_ns_ep_info(&ep, entrypoint, context_id);
+ if (rc != PSCI_E_SUCCESS)
+ return rc;
+
+
+ /*
* To turn this cpu on, specify which affinity
* levels need to be turned on
*/
start_afflvl = MPIDR_AFFLVL0;
end_afflvl = get_max_afflvl();
rc = psci_afflvl_on(target_cpu,
- entrypoint,
- context_id,
+ &ep,
start_afflvl,
end_afflvl);
-exit:
return rc;
}
@@ -79,6 +97,7 @@ int psci_cpu_suspend(unsigned int power_state,
{
int rc;
unsigned int target_afflvl, pstate_type;
+ entry_point_info_t ep;
/* Check SBZ bits in power state are zero */
if (psci_validate_power_state(power_state))
@@ -89,6 +108,24 @@ int psci_cpu_suspend(unsigned int power_state,
if (target_afflvl > get_max_afflvl())
return PSCI_E_INVALID_PARAMS;
+ /* Validate the power_state using platform pm_ops */
+ if (psci_plat_pm_ops->validate_power_state) {
+ rc = psci_plat_pm_ops->validate_power_state(power_state);
+ if (rc != PSCI_E_SUCCESS) {
+ assert(rc == PSCI_E_INVALID_PARAMS);
+ return PSCI_E_INVALID_PARAMS;
+ }
+ }
+
+ /* Validate the entrypoint using platform pm_ops */
+ if (psci_plat_pm_ops->validate_ns_entrypoint) {
+ rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint);
+ if (rc != PSCI_E_SUCCESS) {
+ assert(rc == PSCI_E_INVALID_PARAMS);
+ return PSCI_E_INVALID_PARAMS;
+ }
+ }
+
/* Determine the 'state type' in the 'power_state' parameter */
pstate_type = psci_get_pstate_type(power_state);
@@ -100,25 +137,33 @@ int psci_cpu_suspend(unsigned int power_state,
if (!psci_plat_pm_ops->affinst_standby)
return PSCI_E_INVALID_PARAMS;
- rc = psci_plat_pm_ops->affinst_standby(power_state);
- assert(rc == PSCI_E_INVALID_PARAMS || rc == PSCI_E_SUCCESS);
- return rc;
+ psci_plat_pm_ops->affinst_standby(power_state);
+ return PSCI_E_SUCCESS;
}
/*
+ * Verify and derive the re-entry information for
+ * the non-secure world from the non-secure state from
+ * where this call originated.
+ */
+ rc = psci_get_ns_ep_info(&ep, entrypoint, context_id);
+ if (rc != PSCI_E_SUCCESS)
+ return rc;
+
+ /* Save PSCI power state parameter for the core in suspend context */
+ psci_set_suspend_power_state(power_state);
+
+ /*
* Do what is needed to enter the power down state. Upon success,
- * enter the final wfi which will power down this cpu else return
- * an error.
+ * enter the final wfi which will power down this CPU.
*/
- rc = psci_afflvl_suspend(entrypoint,
- context_id,
- power_state,
- MPIDR_AFFLVL0,
- target_afflvl);
- if (rc == PSCI_E_SUCCESS)
- psci_power_down_wfi();
- assert(rc == PSCI_E_INVALID_PARAMS);
- return rc;
+ psci_afflvl_suspend(&ep,
+ MPIDR_AFFLVL0,
+ target_afflvl);
+
+ /* Reset PSCI power state parameter for the core. */
+ psci_set_suspend_power_state(PSCI_INVALID_DATA);
+ return PSCI_E_SUCCESS;
}
int psci_cpu_off(void)
@@ -135,14 +180,6 @@ int psci_cpu_off(void)
rc = psci_afflvl_off(MPIDR_AFFLVL0, target_afflvl);
/*
- * Check if all actions needed to safely power down this cpu have
- * successfully completed. Enter a wfi loop which will allow the
- * power controller to physically power down this cpu.
- */
- if (rc == PSCI_E_SUCCESS)
- psci_power_down_wfi();
-
- /*
* The only error cpu_off can return is E_DENIED. So check if that's
* indeed the case.
*/