allwinner: Use CPUIDLE hardware when available
This works even on SoCs that do not have an ARISC, and it avoids
clobbering whatever ARISC firmware might be running.
Change-Id: I9f2fed597189bb387de79e8e76a7da3375e1ee91
Signed-off-by: Samuel Holland <samuel@sholland.org>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
index cbad720..43c03ac 100644
--- a/plat/allwinner/common/sunxi_cpu_ops.c
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -15,11 +15,14 @@
#include <lib/utils_def.h>
#include <plat/common/platform.h>
-#include <core_off_arisc.h>
#include <sunxi_cpucfg.h>
#include <sunxi_mmap.h>
#include <sunxi_private.h>
+#ifndef SUNXI_CPUIDLE_EN_REG
+#include <core_off_arisc.h>
+#endif
+
static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core)
{
if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff)
@@ -72,6 +75,14 @@
/* Simplifies assembly, all SoCs so far are single cluster anyway. */
assert(MPIDR_AFFLVL1_VAL(mpidr) == 0);
+#ifdef SUNXI_CPUIDLE_EN_REG
+ /* Enable the CPUIDLE hardware (only really needs to be done once). */
+ mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0x16aa0000);
+ mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0xaa160001);
+
+ /* Trigger power off for this core. */
+ mmio_write_32(SUNXI_CORE_CLOSE_REG, BIT_32(core));
+#else
/*
* If we are supposed to turn ourself off, tell the arisc SCP
* to do that work for us. The code expects the core mask to be
@@ -79,6 +90,7 @@
*/
sunxi_execute_arisc_code(arisc_core_off, sizeof(arisc_core_off),
BIT_32(core));
+#endif
}
void sunxi_cpu_on(u_register_t mpidr)