Skip to content
Permalink
Browse files

PSCI: add core_power_down_wfi() hook for late power-off

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 17, 2017
1 parent 60a1f02 commit 8d3f98e90f9e19284d8e20c040a7c28d7763d944
Showing with 29 additions and 2 deletions.
  1. +1 −0 include/bl31/services/psci.h
  2. +28 −2 services/std_svc/psci/psci_main.c
@@ -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;
@@ -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;
}
@@ -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

0 comments on commit 8d3f98e

Please sign in to comment.
You can’t perform that action at this time.