Commit 2ff900f2 authored by danh-arm's avatar danh-arm
Browse files

Merge pull request #633 from soby-mathew/sm/psci_wfi_hook

PSCI: Add pwr_domain_pwr_down_wfi() hook in plat_psci_ops
parents 8c94f82c ac1cc8eb
...@@ -1715,6 +1715,22 @@ latter case, the power domain is expected to save enough state so that it can ...@@ -1715,6 +1715,22 @@ latter case, the power domain is expected to save enough state so that it can
resume execution by restoring this state when its powered on (see resume execution by restoring this state when its powered on (see
`pwr_domain_suspend_finish()`). `pwr_domain_suspend_finish()`).
#### plat_psci_ops.pwr_domain_pwr_down_wfi()
This is an optional function and, if implemented, is expected to perform
platform specific actions including the `wfi` invocation which allows the
CPU to powerdown. Since this function is invoked outside the PSCI locks,
the actions performed in this hook must be local to the CPU or the platform
must ensure that races between multiple CPUs cannot occur.
The `target_state` has a similar meaning as described in the `pwr_domain_off()`
operation and it encodes the platform coordinated target local power states for
the CPU power domain and its parent power domain levels. This function must
not return back to the caller.
If this function is not implemented by the platform, PSCI generic
implementation invokes `psci_power_down_wfi()` for power down.
#### plat_psci_ops.pwr_domain_on_finish() #### plat_psci_ops.pwr_domain_on_finish()
This function is called by the PSCI implementation after the calling CPU is This function is called by the PSCI implementation after the calling CPU is
......
...@@ -265,6 +265,8 @@ typedef struct plat_psci_ops { ...@@ -265,6 +265,8 @@ typedef struct plat_psci_ops {
void (*pwr_domain_on_finish)(const psci_power_state_t *target_state); void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
void (*pwr_domain_suspend_finish)( void (*pwr_domain_suspend_finish)(
const psci_power_state_t *target_state); const psci_power_state_t *target_state);
void (*pwr_domain_pwr_down_wfi)(
const psci_power_state_t *target_state) __dead2;
void (*system_off)(void) __dead2; void (*system_off)(void) __dead2;
void (*system_reset)(void) __dead2; void (*system_reset)(void) __dead2;
int (*validate_power_state)(unsigned int power_state, int (*validate_power_state)(unsigned int power_state,
......
...@@ -106,7 +106,6 @@ endfunc psci_entrypoint ...@@ -106,7 +106,6 @@ endfunc psci_entrypoint
func psci_power_down_wfi func psci_power_down_wfi
dsb sy // ensure write buffer empty dsb sy // ensure write buffer empty
wfi wfi
wfi_spill: bl plat_panic_handler
b wfi_spill
endfunc psci_power_down_wfi endfunc psci_power_down_wfi
...@@ -138,11 +138,16 @@ exit: ...@@ -138,11 +138,16 @@ exit:
dsbish(); dsbish();
inv_cpu_data(psci_svc_cpu_data.aff_info_state); inv_cpu_data(psci_svc_cpu_data.aff_info_state);
/* if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi) {
* Enter a wfi loop which will allow the power controller to /* This function must not return */
* physically power down this cpu. psci_plat_pm_ops->pwr_domain_pwr_down_wfi(&state_info);
*/ } else {
psci_power_down_wfi(); /*
* Enter a wfi loop which will allow the power
* controller to physically power down this cpu.
*/
psci_power_down_wfi();
}
} }
return rc; return rc;
......
...@@ -189,8 +189,13 @@ exit: ...@@ -189,8 +189,13 @@ exit:
if (skip_wfi) if (skip_wfi)
return; return;
if (is_power_down_state) if (is_power_down_state) {
psci_power_down_wfi(); /* The function calls below must not return */
if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi)
psci_plat_pm_ops->pwr_domain_pwr_down_wfi(state_info);
else
psci_power_down_wfi();
}
/* /*
* We will reach here if only retention/standby states have been * We will reach here if only retention/standby states have been
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment