506 lines
16 KiB
Diff
506 lines
16 KiB
Diff
From a36c863db5fbbfb85cb509ce23955fbad29e5a63 Mon Sep 17 00:00:00 2001
|
|
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
|
Date: Mon, 27 Oct 2025 20:34:52 +0100
|
|
Subject: [PATCH] refactor(allwinner): Make native PM A53 specific
|
|
|
|
Native PM callbacks are tailored to A53 based SoCs. With new A55
|
|
platform, concept is slightly changed.
|
|
|
|
Mark current native PM as A53 specific. Later, A55 specific variant will
|
|
be added.
|
|
|
|
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
|
---
|
|
plat/allwinner/common/allwinner-common-a53.mk | 5 +++++
|
|
plat/allwinner/common/allwinner-common.mk | 5 -----
|
|
.../common/{sunxi_cpu_ops.c => sunxi_cpu_ops_a53.c} | 0
|
|
.../common/{sunxi_native_pm.c => sunxi_native_pm_a53.c} | 0
|
|
4 files changed, 5 insertions(+), 5 deletions(-)
|
|
rename plat/allwinner/common/{sunxi_cpu_ops.c => sunxi_cpu_ops_a53.c} (100%)
|
|
rename plat/allwinner/common/{sunxi_native_pm.c => sunxi_native_pm_a53.c} (100%)
|
|
|
|
--- a/plat/allwinner/common/allwinner-common-a53.mk
|
|
+++ b/plat/allwinner/common/allwinner-common-a53.mk
|
|
@@ -6,6 +6,11 @@
|
|
|
|
BL31_SOURCES += lib/cpus/${ARCH}/cortex_a53.S
|
|
|
|
+ifeq (${SUNXI_PSCI_USE_NATIVE},1)
|
|
+BL31_SOURCES += ${AW_PLAT}/common/sunxi_cpu_ops_a53.c \
|
|
+ ${AW_PLAT}/common/sunxi_native_pm_a53.c
|
|
+endif
|
|
+
|
|
# A53 cores use GICv2
|
|
USE_GIC_DRIVER := 2
|
|
|
|
--- a/plat/allwinner/common/allwinner-common.mk
|
|
+++ b/plat/allwinner/common/allwinner-common.mk
|
|
@@ -47,11 +47,6 @@ ifeq (${SUNXI_PSCI_USE_NATIVE}${SUNXI_PS
|
|
$(error "At least one of SCPI or native PSCI ops must be enabled")
|
|
endif
|
|
|
|
-ifeq (${SUNXI_PSCI_USE_NATIVE},1)
|
|
-BL31_SOURCES += ${AW_PLAT}/common/sunxi_cpu_ops.c \
|
|
- ${AW_PLAT}/common/sunxi_native_pm.c
|
|
-endif
|
|
-
|
|
ifeq (${SUNXI_PSCI_USE_SCPI},1)
|
|
BL31_SOURCES += drivers/allwinner/sunxi_msgbox.c \
|
|
drivers/arm/css/scpi/css_scpi.c \
|
|
--- a/plat/allwinner/common/sunxi_cpu_ops.c
|
|
+++ /dev/null
|
|
@@ -1,151 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
|
|
- *
|
|
- * SPDX-License-Identifier: BSD-3-Clause
|
|
- */
|
|
-
|
|
-#include <assert.h>
|
|
-
|
|
-#include <platform_def.h>
|
|
-
|
|
-#include <arch_helpers.h>
|
|
-#include <common/debug.h>
|
|
-#include <drivers/delay_timer.h>
|
|
-#include <lib/mmio.h>
|
|
-#include <lib/utils_def.h>
|
|
-#include <plat/common/platform.h>
|
|
-
|
|
-#include <sunxi_cpucfg.h>
|
|
-#include <sunxi_mmap.h>
|
|
-#include <sunxi_private.h>
|
|
-
|
|
-#ifndef SUNXI_C0_CPU_CTRL_REG
|
|
-#define SUNXI_C0_CPU_CTRL_REG(n) 0
|
|
-#define SUNXI_CPU_UNK_REG(n) 0
|
|
-#define SUNXI_CPU_CTRL_REG(n) 0
|
|
-#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)
|
|
- return;
|
|
-
|
|
- VERBOSE("PSCI: Disabling power to cluster %d core %d\n", cluster, core);
|
|
-
|
|
- mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff);
|
|
-}
|
|
-
|
|
-static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core)
|
|
-{
|
|
- if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0)
|
|
- return;
|
|
-
|
|
- VERBOSE("PSCI: Enabling power to cluster %d core %d\n", cluster, core);
|
|
-
|
|
- /* Power enable sequence from original Allwinner sources */
|
|
- mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe);
|
|
- mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xf8);
|
|
- mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0);
|
|
- mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80);
|
|
- mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00);
|
|
- udelay(1);
|
|
-}
|
|
-
|
|
-/* We can't turn ourself off like this, but it works for other cores. */
|
|
-static void sunxi_cpu_off(u_register_t mpidr)
|
|
-{
|
|
- unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
|
- unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
|
|
-
|
|
- VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core);
|
|
-
|
|
- if (sunxi_cpucfg_has_per_cluster_regs()) {
|
|
- /* Deassert DBGPWRDUP */
|
|
- mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
|
|
- /* Activate the core output clamps, but not for core 0. */
|
|
- if (core != 0) {
|
|
- mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster),
|
|
- BIT(core));
|
|
- }
|
|
- /* Assert CPU power-on reset */
|
|
- mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
|
|
- /* Remove power from the CPU */
|
|
- sunxi_cpu_disable_power(cluster, core);
|
|
- } else {
|
|
- /* power down(?) debug core */
|
|
- mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8));
|
|
- /* ??? Activate the core output clamps, but not for core 0 */
|
|
- if (core != 0) {
|
|
- mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(1));
|
|
- }
|
|
- /* ??? Assert CPU power-on reset ??? */
|
|
- mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0));
|
|
- /* Remove power from the CPU */
|
|
- sunxi_cpu_disable_power(cluster, core);
|
|
- }
|
|
-}
|
|
-
|
|
-void sunxi_cpu_on(u_register_t mpidr)
|
|
-{
|
|
- unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
|
- unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
|
|
-
|
|
- VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core);
|
|
-
|
|
- if (sunxi_cpucfg_has_per_cluster_regs()) {
|
|
- /* Assert CPU core reset */
|
|
- mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
|
|
- /* Assert CPU power-on reset */
|
|
- mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
|
|
- /* Set CPU to start in AArch64 mode */
|
|
- mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster),
|
|
- BIT(SUNXI_AA64nAA32_OFFSET + core));
|
|
- /* Apply power to the CPU */
|
|
- sunxi_cpu_enable_power(cluster, core);
|
|
- /* Release the core output clamps */
|
|
- mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
|
|
- /* Deassert CPU power-on reset */
|
|
- mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
|
|
- /* Deassert CPU core reset */
|
|
- mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
|
|
- /* Assert DBGPWRDUP */
|
|
- mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
|
|
- } else {
|
|
- /* Assert CPU core reset */
|
|
- mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0));
|
|
- /* ??? Assert CPU power-on reset ??? */
|
|
- mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0));
|
|
-
|
|
- /* Set CPU to start in AArch64 mode */
|
|
- mmio_setbits_32(SUNXI_CPU_CTRL_REG(core), BIT(0));
|
|
-
|
|
- /* Apply power to the CPU */
|
|
- sunxi_cpu_enable_power(cluster, core);
|
|
-
|
|
- /* ??? Release the core output clamps ??? */
|
|
- mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(1));
|
|
- /* ??? Deassert CPU power-on reset ??? */
|
|
- mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(0));
|
|
- /* Deassert CPU core reset */
|
|
- mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0));
|
|
- /* power up(?) debug core */
|
|
- mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8));
|
|
- }
|
|
-}
|
|
-
|
|
-void sunxi_cpu_power_off_others(void)
|
|
-{
|
|
- u_register_t self = read_mpidr();
|
|
- unsigned int cluster;
|
|
- unsigned int core;
|
|
-
|
|
- for (cluster = 0; cluster < PLATFORM_CLUSTER_COUNT; ++cluster) {
|
|
- for (core = 0; core < PLATFORM_MAX_CPUS_PER_CLUSTER; ++core) {
|
|
- u_register_t mpidr = (cluster << MPIDR_AFF1_SHIFT) |
|
|
- (core << MPIDR_AFF0_SHIFT) |
|
|
- BIT(31);
|
|
- if (mpidr != self)
|
|
- sunxi_cpu_off(mpidr);
|
|
- }
|
|
- }
|
|
-}
|
|
--- /dev/null
|
|
+++ b/plat/allwinner/common/sunxi_cpu_ops_a53.c
|
|
@@ -0,0 +1,151 @@
|
|
+/*
|
|
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <assert.h>
|
|
+
|
|
+#include <platform_def.h>
|
|
+
|
|
+#include <arch_helpers.h>
|
|
+#include <common/debug.h>
|
|
+#include <drivers/delay_timer.h>
|
|
+#include <lib/mmio.h>
|
|
+#include <lib/utils_def.h>
|
|
+#include <plat/common/platform.h>
|
|
+
|
|
+#include <sunxi_cpucfg.h>
|
|
+#include <sunxi_mmap.h>
|
|
+#include <sunxi_private.h>
|
|
+
|
|
+#ifndef SUNXI_C0_CPU_CTRL_REG
|
|
+#define SUNXI_C0_CPU_CTRL_REG(n) 0
|
|
+#define SUNXI_CPU_UNK_REG(n) 0
|
|
+#define SUNXI_CPU_CTRL_REG(n) 0
|
|
+#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)
|
|
+ return;
|
|
+
|
|
+ VERBOSE("PSCI: Disabling power to cluster %d core %d\n", cluster, core);
|
|
+
|
|
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff);
|
|
+}
|
|
+
|
|
+static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core)
|
|
+{
|
|
+ if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0)
|
|
+ return;
|
|
+
|
|
+ VERBOSE("PSCI: Enabling power to cluster %d core %d\n", cluster, core);
|
|
+
|
|
+ /* Power enable sequence from original Allwinner sources */
|
|
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe);
|
|
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xf8);
|
|
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0);
|
|
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80);
|
|
+ mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00);
|
|
+ udelay(1);
|
|
+}
|
|
+
|
|
+/* We can't turn ourself off like this, but it works for other cores. */
|
|
+static void sunxi_cpu_off(u_register_t mpidr)
|
|
+{
|
|
+ unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
|
+ unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
|
|
+
|
|
+ VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core);
|
|
+
|
|
+ if (sunxi_cpucfg_has_per_cluster_regs()) {
|
|
+ /* Deassert DBGPWRDUP */
|
|
+ mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
|
|
+ /* Activate the core output clamps, but not for core 0. */
|
|
+ if (core != 0) {
|
|
+ mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster),
|
|
+ BIT(core));
|
|
+ }
|
|
+ /* Assert CPU power-on reset */
|
|
+ mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
|
|
+ /* Remove power from the CPU */
|
|
+ sunxi_cpu_disable_power(cluster, core);
|
|
+ } else {
|
|
+ /* power down(?) debug core */
|
|
+ mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8));
|
|
+ /* ??? Activate the core output clamps, but not for core 0 */
|
|
+ if (core != 0) {
|
|
+ mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(1));
|
|
+ }
|
|
+ /* ??? Assert CPU power-on reset ??? */
|
|
+ mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0));
|
|
+ /* Remove power from the CPU */
|
|
+ sunxi_cpu_disable_power(cluster, core);
|
|
+ }
|
|
+}
|
|
+
|
|
+void sunxi_cpu_on(u_register_t mpidr)
|
|
+{
|
|
+ unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
|
+ unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
|
|
+
|
|
+ VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core);
|
|
+
|
|
+ if (sunxi_cpucfg_has_per_cluster_regs()) {
|
|
+ /* Assert CPU core reset */
|
|
+ mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
|
|
+ /* Assert CPU power-on reset */
|
|
+ mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
|
|
+ /* Set CPU to start in AArch64 mode */
|
|
+ mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster),
|
|
+ BIT(SUNXI_AA64nAA32_OFFSET + core));
|
|
+ /* Apply power to the CPU */
|
|
+ sunxi_cpu_enable_power(cluster, core);
|
|
+ /* Release the core output clamps */
|
|
+ mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
|
|
+ /* Deassert CPU power-on reset */
|
|
+ mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
|
|
+ /* Deassert CPU core reset */
|
|
+ mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
|
|
+ /* Assert DBGPWRDUP */
|
|
+ mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
|
|
+ } else {
|
|
+ /* Assert CPU core reset */
|
|
+ mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0));
|
|
+ /* ??? Assert CPU power-on reset ??? */
|
|
+ mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0));
|
|
+
|
|
+ /* Set CPU to start in AArch64 mode */
|
|
+ mmio_setbits_32(SUNXI_CPU_CTRL_REG(core), BIT(0));
|
|
+
|
|
+ /* Apply power to the CPU */
|
|
+ sunxi_cpu_enable_power(cluster, core);
|
|
+
|
|
+ /* ??? Release the core output clamps ??? */
|
|
+ mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(1));
|
|
+ /* ??? Deassert CPU power-on reset ??? */
|
|
+ mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(0));
|
|
+ /* Deassert CPU core reset */
|
|
+ mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0));
|
|
+ /* power up(?) debug core */
|
|
+ mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8));
|
|
+ }
|
|
+}
|
|
+
|
|
+void sunxi_cpu_power_off_others(void)
|
|
+{
|
|
+ u_register_t self = read_mpidr();
|
|
+ unsigned int cluster;
|
|
+ unsigned int core;
|
|
+
|
|
+ for (cluster = 0; cluster < PLATFORM_CLUSTER_COUNT; ++cluster) {
|
|
+ for (core = 0; core < PLATFORM_MAX_CPUS_PER_CLUSTER; ++core) {
|
|
+ u_register_t mpidr = (cluster << MPIDR_AFF1_SHIFT) |
|
|
+ (core << MPIDR_AFF0_SHIFT) |
|
|
+ BIT(31);
|
|
+ if (mpidr != self)
|
|
+ sunxi_cpu_off(mpidr);
|
|
+ }
|
|
+ }
|
|
+}
|
|
--- a/plat/allwinner/common/sunxi_native_pm.c
|
|
+++ /dev/null
|
|
@@ -1,71 +0,0 @@
|
|
-/*
|
|
- * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
|
|
- *
|
|
- * SPDX-License-Identifier: BSD-3-Clause
|
|
- */
|
|
-
|
|
-#include <arch_helpers.h>
|
|
-#include <common/debug.h>
|
|
-#include <drivers/delay_timer.h>
|
|
-#include <lib/mmio.h>
|
|
-#include <lib/psci/psci.h>
|
|
-
|
|
-#include <sunxi_mmap.h>
|
|
-#include <sunxi_private.h>
|
|
-
|
|
-#define SUNXI_WDOG0_CTRL_REG (SUNXI_R_WDOG_BASE + 0x0010)
|
|
-#define SUNXI_WDOG0_CFG_REG (SUNXI_R_WDOG_BASE + 0x0014)
|
|
-#define SUNXI_WDOG0_MODE_REG (SUNXI_R_WDOG_BASE + 0x0018)
|
|
-
|
|
-static int sunxi_pwr_domain_on(u_register_t mpidr)
|
|
-{
|
|
- sunxi_cpu_on(mpidr);
|
|
-
|
|
- return PSCI_E_SUCCESS;
|
|
-}
|
|
-
|
|
-static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
|
|
-{
|
|
- sunxi_cpu_power_off_self();
|
|
-}
|
|
-
|
|
-static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
|
-{
|
|
-}
|
|
-
|
|
-static void sunxi_system_off(void)
|
|
-{
|
|
- /* Attempt to power down the board (may not return) */
|
|
- sunxi_power_down();
|
|
-
|
|
- /* Turn off all CPUs */
|
|
- sunxi_cpu_power_off_others();
|
|
- sunxi_cpu_power_off_self();
|
|
-}
|
|
-
|
|
-static void __dead2 sunxi_system_reset(void)
|
|
-{
|
|
- /* Reset the whole system when the watchdog times out */
|
|
- mmio_write_32(SUNXI_WDOG0_CFG_REG, 1);
|
|
- /* Enable the watchdog with the shortest timeout (0.5 seconds) */
|
|
- mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1);
|
|
- /* Wait for twice the watchdog timeout before panicking */
|
|
- mdelay(1000);
|
|
-
|
|
- ERROR("PSCI: System reset failed\n");
|
|
- panic();
|
|
-}
|
|
-
|
|
-static const plat_psci_ops_t sunxi_native_psci_ops = {
|
|
- .pwr_domain_on = sunxi_pwr_domain_on,
|
|
- .pwr_domain_off = sunxi_pwr_domain_off,
|
|
- .pwr_domain_on_finish = sunxi_pwr_domain_on_finish,
|
|
- .system_off = sunxi_system_off,
|
|
- .system_reset = sunxi_system_reset,
|
|
- .validate_ns_entrypoint = sunxi_validate_ns_entrypoint,
|
|
-};
|
|
-
|
|
-void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops)
|
|
-{
|
|
- *psci_ops = &sunxi_native_psci_ops;
|
|
-}
|
|
--- /dev/null
|
|
+++ b/plat/allwinner/common/sunxi_native_pm_a53.c
|
|
@@ -0,0 +1,71 @@
|
|
+/*
|
|
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-3-Clause
|
|
+ */
|
|
+
|
|
+#include <arch_helpers.h>
|
|
+#include <common/debug.h>
|
|
+#include <drivers/delay_timer.h>
|
|
+#include <lib/mmio.h>
|
|
+#include <lib/psci/psci.h>
|
|
+
|
|
+#include <sunxi_mmap.h>
|
|
+#include <sunxi_private.h>
|
|
+
|
|
+#define SUNXI_WDOG0_CTRL_REG (SUNXI_R_WDOG_BASE + 0x0010)
|
|
+#define SUNXI_WDOG0_CFG_REG (SUNXI_R_WDOG_BASE + 0x0014)
|
|
+#define SUNXI_WDOG0_MODE_REG (SUNXI_R_WDOG_BASE + 0x0018)
|
|
+
|
|
+static int sunxi_pwr_domain_on(u_register_t mpidr)
|
|
+{
|
|
+ sunxi_cpu_on(mpidr);
|
|
+
|
|
+ return PSCI_E_SUCCESS;
|
|
+}
|
|
+
|
|
+static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
|
|
+{
|
|
+ sunxi_cpu_power_off_self();
|
|
+}
|
|
+
|
|
+static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
|
+{
|
|
+}
|
|
+
|
|
+static void sunxi_system_off(void)
|
|
+{
|
|
+ /* Attempt to power down the board (may not return) */
|
|
+ sunxi_power_down();
|
|
+
|
|
+ /* Turn off all CPUs */
|
|
+ sunxi_cpu_power_off_others();
|
|
+ sunxi_cpu_power_off_self();
|
|
+}
|
|
+
|
|
+static void __dead2 sunxi_system_reset(void)
|
|
+{
|
|
+ /* Reset the whole system when the watchdog times out */
|
|
+ mmio_write_32(SUNXI_WDOG0_CFG_REG, 1);
|
|
+ /* Enable the watchdog with the shortest timeout (0.5 seconds) */
|
|
+ mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1);
|
|
+ /* Wait for twice the watchdog timeout before panicking */
|
|
+ mdelay(1000);
|
|
+
|
|
+ ERROR("PSCI: System reset failed\n");
|
|
+ panic();
|
|
+}
|
|
+
|
|
+static const plat_psci_ops_t sunxi_native_psci_ops = {
|
|
+ .pwr_domain_on = sunxi_pwr_domain_on,
|
|
+ .pwr_domain_off = sunxi_pwr_domain_off,
|
|
+ .pwr_domain_on_finish = sunxi_pwr_domain_on_finish,
|
|
+ .system_off = sunxi_system_off,
|
|
+ .system_reset = sunxi_system_reset,
|
|
+ .validate_ns_entrypoint = sunxi_validate_ns_entrypoint,
|
|
+};
|
|
+
|
|
+void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops)
|
|
+{
|
|
+ *psci_ops = &sunxi_native_psci_ops;
|
|
+}
|