aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c')
-rw-r--r--roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c b/roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c
new file mode 100644
index 000000000..ab102a622
--- /dev/null
+++ b/roms/u-boot/arch/arm/mach-tegra/tegra124/psci.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2015, Siemens AG
+ * Author: Jan Kiszka <jan.kiszka@siemens.com>
+ */
+
+#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 */;
+}