diff options
Diffstat (limited to 'services/psci/psci_afflvl_suspend.c')
-rw-r--r-- | services/psci/psci_afflvl_suspend.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/services/psci/psci_afflvl_suspend.c b/services/psci/psci_afflvl_suspend.c index 4391580..62d270f 100644 --- a/services/psci/psci_afflvl_suspend.c +++ b/services/psci/psci_afflvl_suspend.c @@ -94,6 +94,19 @@ static int psci_afflvl0_suspend(unsigned long mpidr, /* Sanity check to safeguard against data corruption */ assert(cpu_node->level == MPIDR_AFFLVL0); + /* + * Generic management: Store the re-entry information for the non-secure + * world and allow the secure world to suspend itself + */ + + /* + * Call the cpu suspend handler registered by the Secure Payload + * Dispatcher to let it do any bookeeping. If the handler encounters an + * error, it's expected to assert within + */ + if (spd_pm.svc_suspend) + spd_pm.svc_suspend(power_state); + /* State management: mark this cpu as suspended */ psci_set_state(cpu_node, PSCI_STATE_SUSPEND); @@ -395,6 +408,7 @@ static unsigned int psci_afflvl0_suspend_finish(unsigned long mpidr, aff_map_node *cpu_node) { unsigned int index, plat_state, state, rc = PSCI_E_SUCCESS; + int32_t suspend_level; assert(cpu_node->level == MPIDR_AFFLVL0); @@ -430,6 +444,27 @@ static unsigned int psci_afflvl0_suspend_finish(unsigned long mpidr, rc = PSCI_E_SUCCESS; /* + * Use the more complex exception vectors to enable SPD + * initialisation. SP_EL3 should point to a 'cpu_context' + * structure which has an exception stack allocated. The + * non-secure context should have been set on this cpu + * prior to suspension. + */ + assert(cm_get_context(mpidr, NON_SECURE)); + cm_set_next_eret_context(NON_SECURE); + write_vbar_el3((uint64_t) runtime_exceptions); + + /* + * Call the cpu suspend finish handler registered by the Secure Payload + * Dispatcher to let it do any bookeeping. If the handler encounters an + * error, it's expected to assert within + */ + if (spd_pm.svc_suspend) { + suspend_level = psci_get_suspend_afflvl(cpu_node); + spd_pm.svc_suspend_finish(suspend_level); + } + + /* * Generic management: Now we just need to retrieve the * information that we had stashed away during the suspend * call to set this cpu on its way. |