summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra124
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2015-04-21 05:18:35 (GMT)
committerTom Warren <twarren@nvidia.com>2015-05-13 16:24:15 (GMT)
commitffdf9f9ae057131375534df5f1e798d1e64785e9 (patch)
treed66c519bbabbe39e1d3a7521544a67338bbd39f2 /arch/arm/mach-tegra/tegra124
parentce416fac3802528702e46663882d67cb8561b4c8 (diff)
downloadu-boot-ffdf9f9ae057131375534df5f1e798d1e64785e9.tar.xz
tegra124: Add PSCI support for Tegra124
This is based on Thierry Reding's work and uses Ian Campell's preparatory patches. It comes with full support for CPU_ON/OFF PSCI services. The algorithm used in this version for turning CPUs on and off was proposed by Peter De Schrijver and Thierry Reding in http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/210881. It consists of first enabling CPU1..3 via the PMC, just to powergate them again with the help of the Flow Controller. Once the Flow Controller is in place, we can leave the PMC alone while processing CPU_ON and CPU_OFF PSCI requests. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Tom Warren <twarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra124')
-rw-r--r--arch/arm/mach-tegra/tegra124/Makefile4
-rw-r--r--arch/arm/mach-tegra/tegra124/psci.c59
2 files changed, 63 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/tegra124/Makefile b/arch/arm/mach-tegra/tegra124/Makefile
index ef2da29..f577f45 100644
--- a/arch/arm/mach-tegra/tegra124/Makefile
+++ b/arch/arm/mach-tegra/tegra124/Makefile
@@ -11,3 +11,7 @@ obj-y += clock.o
obj-y += funcmux.o
obj-y += pinmux.o
obj-y += xusb-padctl.o
+
+ifndef CONFIG_SPL_BUILD
+obj-$(CONFIG_ARMV7_NONSEC) += psci.o
+endif
diff --git a/arch/arm/mach-tegra/tegra124/psci.c b/arch/arm/mach-tegra/tegra124/psci.c
new file mode 100644
index 0000000..16d1965
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra124/psci.c
@@ -0,0 +1,59 @@
+/*
+ * (C) Copyright 2015, Siemens AG
+ * Author: Jan Kiszka <jan.kiszka@siemens.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/psci.h>
+#include <asm/arch/flow.h>
+#include <asm/arch/powergate.h>
+#include <asm/arch-tegra/ap.h>
+#include <asm/arch-tegra/pmc.h>
+
+static void park_cpu(void)
+{
+ while (1)
+ asm volatile("wfi");
+}
+
+/**
+ * Initialize power management for application processors
+ */
+void psci_board_init(void)
+{
+ struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
+
+ writel((u32)park_cpu, EXCEP_VECTOR_CPU_RESET_VECTOR);
+
+ /*
+ * The naturally expected order of putting these CPUs under Flow
+ * Controller regime would be
+ * - configure the Flow Controller
+ * - power up the CPUs
+ * - wait for the CPUs to hit wfi and be powered down again
+ *
+ * However, this doesn't work in practice. We rather need to power them
+ * up first and park them in wfi. While they are waiting there, we can
+ * indeed program the Flow Controller to powergate them on wfi, which
+ * will then happen immediately as they are already in that state.
+ */
+ tegra_powergate_power_on(TEGRA_POWERGATE_CPU1);
+ tegra_powergate_power_on(TEGRA_POWERGATE_CPU2);
+ tegra_powergate_power_on(TEGRA_POWERGATE_CPU3);
+
+ writel((2 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu1_csr);
+ writel((4 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu2_csr);
+ writel((8 << CSR_WAIT_WFI_SHIFT) | CSR_ENABLE, &flow->cpu3_csr);
+
+ writel(EVENT_MODE_STOP, &flow->halt_cpu1_events);
+ writel(EVENT_MODE_STOP, &flow->halt_cpu2_events);
+ writel(EVENT_MODE_STOP, &flow->halt_cpu3_events);
+
+ while (!(readl(&flow->cpu1_csr) & CSR_PWR_OFF_STS) ||
+ !(readl(&flow->cpu2_csr) & CSR_PWR_OFF_STS) ||
+ !(readl(&flow->cpu3_csr) & CSR_PWR_OFF_STS))
+ /* wait */;
+}