summaryrefslogtreecommitdiff
path: root/plat
diff options
context:
space:
mode:
authorAchin Gupta <achin.gupta@arm.com>2014-08-18 14:40:27 +0100
committerSoby Mathew <soby.mathew@arm.com>2014-08-21 14:53:48 +0100
commitfef4fdb9cc0f2e4ca9d2864e1e92624da1e96ff5 (patch)
treec232a269e13f316a56fd6b85c4410c5f6a4c5cd1 /plat
parent01b916bff2dca219d4088b8abca0a02ac06dd615 (diff)
Juno: Implement PSCI CPU_OFF and CPU_SUSPEND APIs
This patch adds support for PSCI CPU_OFF and CPU_SUSPEND APIs to the Juno port of the ARM Trusted Firmware. The maximum affinity level that can be suspended is the cluster level (affinity level 1). Support for suspending the system level is not present. Change-Id: Ie2c9da0acd7d1b0d5ac64940cdf40347153e52c8
Diffstat (limited to 'plat')
-rw-r--r--plat/juno/plat_pm.c114
1 files changed, 106 insertions, 8 deletions
diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c
index 61dc13e..27a1227 100644
--- a/plat/juno/plat_pm.c
+++ b/plat/juno/plat_pm.c
@@ -86,11 +86,11 @@ static int32_t juno_do_plat_actions(uint32_t afflvl, uint32_t state)
* Juno handler called when an affinity instance is about to be turned on. The
* level and mpidr determine the affinity instance.
******************************************************************************/
-int32_t juno_on(uint64_t mpidr,
- uint64_t sec_entrypoint,
- uint64_t ns_entrypoint,
- uint32_t afflvl,
- uint32_t state)
+int32_t juno_affinst_on(uint64_t mpidr,
+ uint64_t sec_entrypoint,
+ uint64_t ns_entrypoint,
+ uint32_t afflvl,
+ uint32_t state)
{
/*
* SCP takes care of powering up higher affinity levels so we
@@ -117,7 +117,7 @@ int32_t juno_on(uint64_t mpidr,
* was turned off prior to wakeup and do what's necessary to setup it up
* correctly.
******************************************************************************/
-int32_t juno_on_finish(uint64_t mpidr, uint32_t afflvl, uint32_t state)
+int32_t juno_affinst_on_finish(uint64_t mpidr, uint32_t afflvl, uint32_t state)
{
/* Determine if any platform actions need to be executed. */
if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
@@ -144,11 +144,109 @@ int32_t juno_on_finish(uint64_t mpidr, uint32_t afflvl, uint32_t state)
}
/*******************************************************************************
+ * Common function called while turning a cpu off or suspending it. It is called
+ * from juno_off() or juno_suspend() when these functions in turn are called for
+ * the highest affinity level which will be powered down. It performs the
+ * actions common to the OFF and SUSPEND calls.
+ ******************************************************************************/
+static int32_t juno_power_down_common(uint32_t afflvl)
+{
+ uint32_t cluster_state = scpi_power_on;
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gic_cpuif_deactivate(GICC_BASE);
+
+ /* Cluster is to be turned off, so disable coherency */
+ if (afflvl > MPIDR_AFFLVL0) {
+ cci_disable_cluster_coherency(read_mpidr_el1());
+ cluster_state = scpi_power_off;
+ }
+
+ /*
+ * Ask the SCP to power down the appropriate components depending upon
+ * their state.
+ */
+ scpi_set_css_power_state(read_mpidr_el1(),
+ scpi_power_off,
+ cluster_state,
+ scpi_power_on);
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * Handler called when an affinity instance is about to be turned off. The
+ * level and mpidr determine the affinity instance. The 'state' arg. allows the
+ * platform to decide whether the cluster is being turned off and take
+ * appropriate actions.
+ *
+ * CAUTION: There is no guarantee that caches will remain turned on across calls
+ * to this function as each affinity level is dealt with. So do not write & read
+ * global variables across calls. It will be wise to do flush a write to the
+ * global to prevent unpredictable results.
+ ******************************************************************************/
+static int32_t juno_affinst_off(uint64_t mpidr, uint32_t afflvl, uint32_t state)
+{
+ /* Determine if any platform actions need to be executed */
+ if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
+ return PSCI_E_SUCCESS;
+
+ return juno_power_down_common(afflvl);
+}
+
+/*******************************************************************************
+ * Handler called when an affinity instance is about to be suspended. The
+ * level and mpidr determine the affinity instance. The 'state' arg. allows the
+ * platform to decide whether the cluster is being turned off and take apt
+ * actions. The 'sec_entrypoint' determines the address in BL3-1 from where
+ * execution should resume.
+ *
+ * CAUTION: There is no guarantee that caches will remain turned on across calls
+ * to this function as each affinity level is dealt with. So do not write & read
+ * global variables across calls. It will be wise to do flush a write to the
+ * global to prevent unpredictable results.
+ ******************************************************************************/
+static int32_t juno_affinst_suspend(uint64_t mpidr,
+ uint64_t sec_entrypoint,
+ uint64_t ns_entrypoint,
+ uint32_t afflvl,
+ uint32_t state)
+{
+ /* Determine if any platform actions need to be executed */
+ if (juno_do_plat_actions(afflvl, state) == -EAGAIN)
+ return PSCI_E_SUCCESS;
+
+ /*
+ * Setup mailbox with address for CPU entrypoint when it next powers up.
+ */
+ juno_program_mailbox(mpidr, sec_entrypoint);
+
+ return juno_power_down_common(afflvl);
+}
+
+/*******************************************************************************
+ * Juno handler called when an affinity instance has just been powered on after
+ * having been suspended earlier. The level and mpidr determine the affinity
+ * instance.
+ * TODO: At the moment we reuse the on finisher and reinitialize the secure
+ * context. Need to implement a separate suspend finisher.
+ ******************************************************************************/
+static int32_t juno_affinst_suspend_finish(uint64_t mpidr,
+ uint32_t afflvl,
+ uint32_t state)
+{
+ return juno_affinst_on_finish(mpidr, afflvl, state);
+}
+
+/*******************************************************************************
* Export the platform handlers to enable psci to invoke them
******************************************************************************/
static const plat_pm_ops_t juno_ops = {
- .affinst_on = juno_on,
- .affinst_on_finish = juno_on_finish,
+ .affinst_on = juno_affinst_on,
+ .affinst_on_finish = juno_affinst_on_finish,
+ .affinst_off = juno_affinst_off,
+ .affinst_suspend = juno_affinst_suspend,
+ .affinst_suspend_finish = juno_affinst_suspend_finish
};
/*******************************************************************************