PSCI: Unify warm reset entry points
There used to be 2 warm reset entry points:
- the "on finisher", for when the core has been turned on using a
PSCI CPU_ON call;
- the "suspend finisher", entered upon resumption from a previous
PSCI CPU_SUSPEND call.
The appropriate warm reset entry point used to be programmed into the
mailboxes by the power management hooks.
However, it is not required to provide this information to the PSCI
entry point code, as it can figure it out by itself. By querying affinity
info state, a core is able to determine on which execution path it is.
If the state is ON_PENDING then it means it's been turned on else
it is resuming from suspend.
This patch unifies the 2 warm reset entry points into a single one:
psci_entrypoint(). The patch also implements the necessary logic
to distinguish between the 2 types of warm resets in the power up
finisher.
The plat_setup_psci_ops() API now takes the
secure entry point as an additional parameter to enable the platforms
to configure their mailbox. The platform hooks `pwr_domain_on`
and `pwr_domain_suspend` no longer take secure entry point as
a parameter.
Change-Id: I7d1c93787b54213aefdbc046b8cd66a555dfbfd9
diff --git a/services/std_svc/psci1.0/psci_common.c b/services/std_svc/psci1.0/psci_common.c
index 70cc98d..0b885cd 100644
--- a/services/std_svc/psci1.0/psci_common.c
+++ b/services/std_svc/psci1.0/psci_common.c
@@ -189,7 +189,7 @@
* been physically powered up. It is expected to be called immediately after
* reset from assembler code.
******************************************************************************/
-int get_power_on_target_pwrlvl(void)
+static int get_power_on_target_pwrlvl(void)
{
int pwrlvl;
@@ -651,11 +651,26 @@
* code to enable the gic cpu interface and for a cluster it will enable
* coherency at the interconnect level in addition to gic cpu interface.
******************************************************************************/
-void psci_power_up_finish(int end_pwrlvl,
- pwrlvl_power_on_finisher_t power_on_handler)
+void psci_power_up_finish(void)
{
unsigned int cpu_idx = plat_my_core_pos();
psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
+ int end_pwrlvl;
+
+ /*
+ * Verify that we have been explicitly turned ON or resumed from
+ * suspend.
+ */
+ if (psci_get_aff_info_state() == AFF_STATE_OFF) {
+ ERROR("Unexpected affinity info state");
+ panic();
+ }
+
+ /*
+ * Get the maximum power domain level to traverse to after this cpu
+ * has been physically powered up.
+ */
+ end_pwrlvl = get_power_on_target_pwrlvl();
/*
* This function acquires the lock corresponding to each power level so
@@ -668,9 +683,21 @@
psci_get_target_local_pwr_states(end_pwrlvl, &state_info);
/*
- * Perform generic, architecture and platform specific handling.
+ * This CPU could be resuming from suspend or it could have just been
+ * turned on. To distinguish between these 2 cases, we examine the
+ * affinity state of the CPU:
+ * - If the affinity state is ON_PENDING then it has just been
+ * turned on.
+ * - Else it is resuming from suspend.
+ *
+ * Depending on the type of warm reset identified, choose the right set
+ * of power management handler and perform the generic, architecture
+ * and platform specific handling.
*/
- power_on_handler(cpu_idx, &state_info);
+ if (psci_get_aff_info_state() == AFF_STATE_ON_PENDING)
+ psci_cpu_on_finish(cpu_idx, &state_info);
+ else
+ psci_cpu_suspend_finish(cpu_idx, &state_info);
/*
* Set the requested and target state of this CPU and all the higher