summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSoby Mathew <soby.mathew@arm.com>2016-04-27 14:46:28 +0100
committerSoby Mathew <soby.mathew@arm.com>2016-05-25 14:00:00 +0100
commitac1cc8eb76c39bca445478c2dffa9cd18829cff4 (patch)
tree33c404b8b2af247e8c6883d43dbbba2df03082a6
parente141aa0357fd4977ba874f4f86874e2cadc73498 (diff)
PSCI: Add pwr_domain_pwr_down_wfi() hook in plat_psci_ops
This patch adds a new optional platform hook `pwr_domain_pwr_down_wfi()` in the plat_psci_ops structure. This hook allows the platform to perform platform specific actions including the wfi invocation to enter powerdown. This hook is invoked by both psci_do_cpu_off() and psci_cpu_suspend_start() functions. The porting-guide.md is also updated for the same. This patch also modifies the `psci_power_down_wfi()` function to invoke `plat_panic_handler` incase of panic instead of the busy while loop. Fixes ARM-Software/tf-issues#375 Change-Id: Iba104469a1445ee8d59fb3a6fdd0a98e7f24dfa3
-rw-r--r--docs/porting-guide.md16
-rw-r--r--include/bl31/services/psci.h2
-rw-r--r--services/std_svc/psci/psci_entry.S3
-rw-r--r--services/std_svc/psci/psci_off.c15
-rw-r--r--services/std_svc/psci/psci_suspend.c9
5 files changed, 36 insertions, 9 deletions
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index 0cd36134..8947defb 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -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
`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()
This function is called by the PSCI implementation after the calling CPU is
diff --git a/include/bl31/services/psci.h b/include/bl31/services/psci.h
index acf07869..95e77809 100644
--- a/include/bl31/services/psci.h
+++ b/include/bl31/services/psci.h
@@ -265,6 +265,8 @@ typedef struct plat_psci_ops {
void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
void (*pwr_domain_suspend_finish)(
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_reset)(void) __dead2;
int (*validate_power_state)(unsigned int power_state,
diff --git a/services/std_svc/psci/psci_entry.S b/services/std_svc/psci/psci_entry.S
index 5f4f91c5..f8c0afa2 100644
--- a/services/std_svc/psci/psci_entry.S
+++ b/services/std_svc/psci/psci_entry.S
@@ -106,7 +106,6 @@ endfunc psci_entrypoint
func psci_power_down_wfi
dsb sy // ensure write buffer empty
wfi
-wfi_spill:
- b wfi_spill
+ bl plat_panic_handler
endfunc psci_power_down_wfi
diff --git a/services/std_svc/psci/psci_off.c b/services/std_svc/psci/psci_off.c
index cef66689..686666d5 100644
--- a/services/std_svc/psci/psci_off.c
+++ b/services/std_svc/psci/psci_off.c
@@ -138,11 +138,16 @@ exit:
dsbish();
inv_cpu_data(psci_svc_cpu_data.aff_info_state);
- /*
- * Enter a wfi loop which will allow the power controller to
- * physically power down this cpu.
- */
- psci_power_down_wfi();
+ if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi) {
+ /* This function must not return */
+ psci_plat_pm_ops->pwr_domain_pwr_down_wfi(&state_info);
+ } else {
+ /*
+ * Enter a wfi loop which will allow the power
+ * controller to physically power down this cpu.
+ */
+ psci_power_down_wfi();
+ }
}
return rc;
diff --git a/services/std_svc/psci/psci_suspend.c b/services/std_svc/psci/psci_suspend.c
index 367bb32a..8c6ab6b4 100644
--- a/services/std_svc/psci/psci_suspend.c
+++ b/services/std_svc/psci/psci_suspend.c
@@ -189,8 +189,13 @@ exit:
if (skip_wfi)
return;
- if (is_power_down_state)
- psci_power_down_wfi();
+ if (is_power_down_state) {
+ /* 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