aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Medhurst <tixy@linaro.org>2014-02-11 14:07:59 +0000
committerSandrine Bailleux <sandrine.bailleux@arm.com>2014-03-12 16:03:33 +0000
commita0d586ea45ca29f56519801719bbf04f010b3147 (patch)
treebeb6e153152f0ec0283dcd6c9875c7de544b1638
parent7441ac3a24f510e40e1be712e0318d7d38fcee29 (diff)
juno: Implement PM ops to power down CPUs
Signed-off-by: Jon Medhurst <tixy@linaro.org>
-rw-r--r--plat/juno/plat_pm.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c
index 4d4efec..d4b98fd 100644
--- a/plat/juno/plat_pm.c
+++ b/plat/juno/plat_pm.c
@@ -94,11 +94,61 @@ int pm_on_finish(unsigned long mpidr, unsigned int afflvl, unsigned int state)
}
/*******************************************************************************
+ * 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 apt
+ * actions.
+ *
+ * CAUTION: This function is called with coherent stacks so that caches can be
+ * turned off, flushed and coherency disabled. 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.
+ ******************************************************************************/
+int pm_off(unsigned long mpidr, unsigned int afflvl, unsigned int state)
+{
+ /* We're only interested in power off states */
+ if (state != PSCI_STATE_OFF)
+ return PSCI_E_SUCCESS;
+
+ switch (afflvl) {
+ case MPIDR_AFFLVL1:
+ /* Cluster is to be turned off, so disable coherency */
+ cci_disable_coherency(mpidr);
+
+ break;
+
+ case MPIDR_AFFLVL0:
+ /* Turn off intra-cluster coherency */
+ write_cpuectlr(read_cpuectlr() & ~CPUECTLR_SMP_BIT);
+
+ /* Prevent interrupts from spuriously waking up this cpu */
+ gic_cpuif_deactivate(GICC_BASE);
+
+ /*
+ * Ask SCP to power down CPU.
+ *
+ * Note, we also ask for cluster power down as well because we
+ * know the SCP will only actually do that if this is the last
+ * CPU going down, and also, that final power down won't happen
+ * until this CPU executes the WFI instruction after the PSCI
+ * framework has done it's thing.
+ */
+ scpi_set_css_power_state(mpidr, scpi_power_off, scpi_power_off,
+ scpi_power_retention);
+ break;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
* Export the platform handlers to enable psci to invoke them
******************************************************************************/
static plat_pm_ops pm_ops = {
.affinst_on = pm_on,
- .affinst_on_finish = pm_on_finish
+ .affinst_on_finish = pm_on_finish,
+ .affinst_off = pm_off
};
/*******************************************************************************