summaryrefslogtreecommitdiff
path: root/lib/psci/psci_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/psci/psci_main.c')
-rw-r--r--lib/psci/psci_main.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index 4b5fc81d7..fe12f06ba 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -60,6 +60,10 @@ int psci_cpu_suspend(unsigned int power_state,
entry_point_info_t ep;
psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
plat_local_state_t cpu_pd_state;
+#if PSCI_OS_INIT_MODE
+ unsigned int cpu_idx = plat_my_core_pos();
+ plat_local_state_t prev[PLAT_MAX_PWR_LVL];
+#endif
/* Validate the power_state parameter */
rc = psci_validate_power_state(power_state, &state_info);
@@ -95,6 +99,18 @@ int psci_cpu_suspend(unsigned int power_state,
cpu_pd_state = state_info.pwr_domain_state[PSCI_CPU_PWR_LVL];
psci_set_cpu_local_state(cpu_pd_state);
+#if PSCI_OS_INIT_MODE
+ /*
+ * If in OS-initiated mode, save a copy of the previous
+ * requested local power states and update the new requested
+ * local power states for this CPU.
+ */
+ if (psci_suspend_mode == OS_INIT) {
+ psci_update_req_local_pwr_states(target_pwrlvl, cpu_idx,
+ &state_info, prev);
+ }
+#endif
+
#if ENABLE_PSCI_STAT
plat_psci_stat_accounting_start(&state_info);
#endif
@@ -110,6 +126,16 @@ int psci_cpu_suspend(unsigned int power_state,
/* Upon exit from standby, set the state back to RUN. */
psci_set_cpu_local_state(PSCI_LOCAL_STATE_RUN);
+#if PSCI_OS_INIT_MODE
+ /*
+ * If in OS-initiated mode, restore the previous requested
+ * local power states for this CPU.
+ */
+ if (psci_suspend_mode == OS_INIT) {
+ psci_restore_req_local_pwr_states(cpu_idx, prev);
+ }
+#endif
+
#if ENABLE_RUNTIME_INSTRUMENTATION
PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
RT_INSTR_EXIT_HW_LOW_PWR,
@@ -142,12 +168,12 @@ int psci_cpu_suspend(unsigned int power_state,
* might return if the power down was abandoned for any reason, e.g.
* arrival of an interrupt
*/
- psci_cpu_suspend_start(&ep,
- target_pwrlvl,
- &state_info,
- is_power_down_state);
+ rc = psci_cpu_suspend_start(&ep,
+ target_pwrlvl,
+ &state_info,
+ is_power_down_state);
- return PSCI_E_SUCCESS;
+ return rc;
}
@@ -187,12 +213,12 @@ int psci_system_suspend(uintptr_t entrypoint, u_register_t context_id)
* might return if the power down was abandoned for any reason, e.g.
* arrival of an interrupt
*/
- psci_cpu_suspend_start(&ep,
- PLAT_MAX_PWR_LVL,
- &state_info,
- PSTATE_TYPE_POWERDOWN);
+ rc = psci_cpu_suspend_start(&ep,
+ PLAT_MAX_PWR_LVL,
+ &state_info,
+ PSTATE_TYPE_POWERDOWN);
- return PSCI_E_SUCCESS;
+ return rc;
}
int psci_cpu_off(void)