Skip to content

Commit

Permalink
PSCI: add core_power_down_wfi() hook for late power-off
Browse files Browse the repository at this point in the history
Without a management processor to pull a core's "plug" remotely, we need
to turn our own power off at some point. Doing this in the middle of
the PSCI handling code during the platform-specific CPU_OFF callback is
a bad idea, as some locks are held at this point. As the core stops executing
instructions immediately when power gated, we never get a chance to
release those locks.
In the style of mainline ATF, introduce a callback function to do some
late platform-specific power-off work. This callback is called as the
last action in the process, just before sending the core to WFI.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
  • Loading branch information
Andre-ARM committed Oct 22, 2017
1 parent 60a1f02 commit 8d3f98e
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
1 change: 1 addition & 0 deletions include/bl31/services/psci.h
Expand Up @@ -163,6 +163,7 @@ typedef struct plat_pm_ops {
int (*affinst_suspend_finish)(unsigned long,
unsigned int,
unsigned int);
void (*core_power_down_wfi)(unsigned long);
void (*system_off)(void) __dead2;
void (*system_reset)(void) __dead2;
} plat_pm_ops_t;
Expand Down
30 changes: 28 additions & 2 deletions services/std_svc/psci/psci_main.c
Expand Up @@ -115,8 +115,22 @@ int psci_cpu_suspend(unsigned int power_state,
power_state,
MPIDR_AFFLVL0,
target_afflvl);
if (rc == PSCI_E_SUCCESS)

if (rc == PSCI_E_SUCCESS) {
/*
* Perform any platform specific, late power-down actions.
* In case this ever returns (it does not need to), fall
* through to the normal WFI sequence.
*/
if (psci_plat_pm_ops->core_power_down_wfi) {
unsigned long mpidr = read_mpidr_el1();

psci_plat_pm_ops->core_power_down_wfi(mpidr);
}

psci_power_down_wfi();
}

assert(rc == PSCI_E_INVALID_PARAMS);
return rc;
}
Expand All @@ -139,8 +153,20 @@ int psci_cpu_off(void)
* successfully completed. Enter a wfi loop which will allow the
* power controller to physically power down this cpu.
*/
if (rc == PSCI_E_SUCCESS)
if (rc == PSCI_E_SUCCESS) {
/*
* Perform any platform specific, late power-down actions.
* In case this ever returns (it does not need to), fall
* through to the normal WFI sequence.
*/
if (psci_plat_pm_ops->core_power_down_wfi) {
unsigned long mpidr = read_mpidr_el1();

psci_plat_pm_ops->core_power_down_wfi(mpidr);
}

psci_power_down_wfi();
}

/*
* The only error cpu_off can return is E_DENIED. So check if that's
Expand Down

0 comments on commit 8d3f98e

Please sign in to comment.