arm-trusted-firmware-sunxi: add Allwinner A523 support
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
@@ -26,6 +26,11 @@ define Trusted-Firmware-A/Default
|
||||
BUILD_SUBTARGET:=cortexa53
|
||||
endef
|
||||
|
||||
define Trusted-Firmware-A/sunxi-a523
|
||||
NAME:=Allwinner A523
|
||||
PLAT:=sun55i_a523
|
||||
endef
|
||||
|
||||
define Trusted-Firmware-A/sunxi-a64
|
||||
NAME:=Allwinner A64
|
||||
PLAT:=sun50i_a64
|
||||
@@ -42,6 +47,7 @@ define Trusted-Firmware-A/sunxi-h616
|
||||
endef
|
||||
|
||||
TFA_TARGETS:= \
|
||||
sunxi-a523 \
|
||||
sunxi-a64 \
|
||||
sunxi-h6 \
|
||||
sunxi-h616
|
||||
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
From 653b8680b2af40c8cde66b56134bd8a2be4f610a Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 12 Jan 2025 21:33:53 +0100
|
||||
Subject: [PATCH] refactor(allwinner): split cortex-a53 and gicv2 config
|
||||
|
||||
Till now all Allwinner 64-bit SoC were Cortex-A53 and used GICv2. In
|
||||
preparation for newer cores with newer GIC split out those settings to
|
||||
separate mk file.
|
||||
|
||||
Change-Id: Ic5e2bd5034c87bc7fe1f64e1867a369fe700848c
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
---
|
||||
plat/allwinner/common/allwinner-common-a53.mk | 20 +++++++++++++++++++
|
||||
plat/allwinner/common/allwinner-common.mk | 13 ------------
|
||||
plat/allwinner/sun50i_a64/platform.mk | 1 +
|
||||
plat/allwinner/sun50i_h6/platform.mk | 1 +
|
||||
plat/allwinner/sun50i_h616/platform.mk | 1 +
|
||||
plat/allwinner/sun50i_r329/platform.mk | 1 +
|
||||
6 files changed, 24 insertions(+), 13 deletions(-)
|
||||
create mode 100644 plat/allwinner/common/allwinner-common-a53.mk
|
||||
|
||||
--- /dev/null
|
||||
+++ b/plat/allwinner/common/allwinner-common-a53.mk
|
||||
@@ -0,0 +1,20 @@
|
||||
+#
|
||||
+# Copyright (c) 2025, ARM Limited and Contributors. All rights reserved.
|
||||
+#
|
||||
+# SPDX-License-Identifier: BSD-3-Clause
|
||||
+#
|
||||
+
|
||||
+include drivers/arm/gic/v2/gicv2.mk
|
||||
+
|
||||
+BL31_SOURCES += ${GICV2_SOURCES} \
|
||||
+ lib/cpus/${ARCH}/cortex_a53.S \
|
||||
+ plat/common/plat_gicv2.c
|
||||
+
|
||||
+# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
|
||||
+ERRATA_A53_835769 := 1
|
||||
+ERRATA_A53_843419 := 1
|
||||
+ERRATA_A53_855873 := 1
|
||||
+ERRATA_A53_1530924 := 1
|
||||
+
|
||||
+# This platform is single-cluster and does not require coherency setup.
|
||||
+WARMBOOT_ENABLE_DCACHE_EARLY := 1
|
||||
--- a/plat/allwinner/common/allwinner-common.mk
|
||||
+++ b/plat/allwinner/common/allwinner-common.mk
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
include lib/libfdt/libfdt.mk
|
||||
-include drivers/arm/gic/v2/gicv2.mk
|
||||
|
||||
AW_PLAT := plat/allwinner
|
||||
|
||||
@@ -20,11 +19,8 @@ PLAT_BL_COMMON_SOURCES := drivers/ti/uar
|
||||
${AW_PLAT}/common/sunxi_common.c
|
||||
|
||||
BL31_SOURCES += drivers/allwinner/axp/common.c \
|
||||
- ${GICV2_SOURCES} \
|
||||
drivers/delay_timer/delay_timer.c \
|
||||
drivers/delay_timer/generic_delay_timer.c \
|
||||
- lib/cpus/${ARCH}/cortex_a53.S \
|
||||
- plat/common/plat_gicv2.c \
|
||||
plat/common/plat_psci_common.c \
|
||||
${AW_PLAT}/common/sunxi_bl31_setup.c \
|
||||
${AW_PLAT}/${PLAT}/sunxi_idle_states.c \
|
||||
@@ -97,12 +93,6 @@ WORKAROUND_CVE_2022_23960 := 0
|
||||
WORKAROUND_CVE_2024_7881 := 0
|
||||
WORKAROUND_CVE_2024_5660 := 0
|
||||
|
||||
-# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
|
||||
-ERRATA_A53_835769 := 1
|
||||
-ERRATA_A53_843419 := 1
|
||||
-ERRATA_A53_855873 := 1
|
||||
-ERRATA_A53_1530924 := 1
|
||||
-
|
||||
# The traditional U-Boot load address is 160MB into DRAM.
|
||||
PRELOADED_BL33_BASE ?= 0x4a000000
|
||||
|
||||
@@ -114,6 +104,3 @@ SEPARATE_CODE_AND_RODATA := 1
|
||||
|
||||
# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL
|
||||
RESET_TO_BL31 := 1
|
||||
-
|
||||
-# This platform is single-cluster and does not require coherency setup.
|
||||
-WARMBOOT_ENABLE_DCACHE_EARLY := 1
|
||||
--- a/plat/allwinner/sun50i_a64/platform.mk
|
||||
+++ b/plat/allwinner/sun50i_a64/platform.mk
|
||||
@@ -10,6 +10,7 @@ SUNXI_AMEND_DTB := 1
|
||||
|
||||
# The differences between the platform are covered by the include files.
|
||||
include plat/allwinner/common/allwinner-common.mk
|
||||
+include plat/allwinner/common/allwinner-common-a53.mk
|
||||
|
||||
BL31_SOURCES += drivers/allwinner/axp/axp803.c \
|
||||
drivers/allwinner/sunxi_rsb.c
|
||||
--- a/plat/allwinner/sun50i_h6/platform.mk
|
||||
+++ b/plat/allwinner/sun50i_h6/platform.mk
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
# The differences between the platform are covered by the include files.
|
||||
include plat/allwinner/common/allwinner-common.mk
|
||||
+include plat/allwinner/common/allwinner-common-a53.mk
|
||||
|
||||
BL31_SOURCES += drivers/allwinner/axp/axp805.c \
|
||||
drivers/allwinner/sunxi_rsb.c
|
||||
--- a/plat/allwinner/sun50i_h616/platform.mk
|
||||
+++ b/plat/allwinner/sun50i_h616/platform.mk
|
||||
@@ -12,6 +12,7 @@ SUNXI_PSCI_USE_NATIVE := 1
|
||||
|
||||
# The differences between the platforms are covered by the include files.
|
||||
include plat/allwinner/common/allwinner-common.mk
|
||||
+include plat/allwinner/common/allwinner-common-a53.mk
|
||||
|
||||
# the above could be overwritten on the command line
|
||||
ifeq (${SUNXI_PSCI_USE_SCPI}, 1)
|
||||
--- a/plat/allwinner/sun50i_r329/platform.mk
|
||||
+++ b/plat/allwinner/sun50i_r329/platform.mk
|
||||
@@ -10,6 +10,7 @@ SUNXI_PSCI_USE_NATIVE := 1
|
||||
|
||||
# The differences between the platforms are covered by the include files.
|
||||
include plat/allwinner/common/allwinner-common.mk
|
||||
+include plat/allwinner/common/allwinner-common-a53.mk
|
||||
|
||||
# the above could be overwritten on the command line
|
||||
ifeq (${SUNXI_PSCI_USE_SCPI}, 1)
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
From 3dfc3c078fc5525f3a30332aeb685d055b736385 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Mon, 27 Oct 2025 20:18:59 +0100
|
||||
Subject: [PATCH] feat(gicv2): Make IRQ groups optional
|
||||
|
||||
Not all platforms define Group 0 interrupts. Make G0 and G1S groups
|
||||
optional so such platforms can use generic driver.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
---
|
||||
drivers/arm/gic/v2/gicv2_base.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/arm/gic/v2/gicv2_base.c
|
||||
+++ b/drivers/arm/gic/v2/gicv2_base.c
|
||||
@@ -20,8 +20,12 @@
|
||||
* interrupts.
|
||||
*****************************************************************************/
|
||||
static const interrupt_prop_t arm_interrupt_props[] = {
|
||||
+#ifdef PLAT_ARM_G1S_IRQ_PROPS
|
||||
PLAT_ARM_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
|
||||
+#endif
|
||||
+#ifdef PLAT_ARM_G0_IRQ_PROPS
|
||||
PLAT_ARM_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
|
||||
+#endif
|
||||
};
|
||||
|
||||
static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
From 4f788f7dd4d3582d6a754af33b85696980363284 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Mon, 27 Oct 2025 20:22:36 +0100
|
||||
Subject: [PATCH] refactor(allwinner): use generic GIC driver
|
||||
|
||||
Using generic GIC driver simplifies code a lot and also allows us to
|
||||
introduce GICv3 platform more easily later.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
---
|
||||
plat/allwinner/common/allwinner-common-a53.mk | 7 ++--
|
||||
plat/allwinner/common/include/platform_def.h | 3 ++
|
||||
plat/allwinner/common/sunxi_bl31_setup.c | 12 ------
|
||||
plat/allwinner/common/sunxi_native_pm.c | 9 ----
|
||||
plat/allwinner/common/sunxi_scpi_pm.c | 41 ++++++++++---------
|
||||
5 files changed, 28 insertions(+), 44 deletions(-)
|
||||
|
||||
--- a/plat/allwinner/common/allwinner-common-a53.mk
|
||||
+++ b/plat/allwinner/common/allwinner-common-a53.mk
|
||||
@@ -4,11 +4,10 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
-include drivers/arm/gic/v2/gicv2.mk
|
||||
+BL31_SOURCES += lib/cpus/${ARCH}/cortex_a53.S
|
||||
|
||||
-BL31_SOURCES += ${GICV2_SOURCES} \
|
||||
- lib/cpus/${ARCH}/cortex_a53.S \
|
||||
- plat/common/plat_gicv2.c
|
||||
+# A53 cores use GICv2
|
||||
+USE_GIC_DRIVER := 2
|
||||
|
||||
# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
|
||||
ERRATA_A53_835769 := 1
|
||||
--- a/plat/allwinner/common/include/platform_def.h
|
||||
+++ b/plat/allwinner/common/include/platform_def.h
|
||||
@@ -81,4 +81,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+#define PLAT_ARM_GICD_BASE SUNXI_GICD_BASE
|
||||
+#define PLAT_ARM_GICC_BASE SUNXI_GICC_BASE
|
||||
+
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
--- a/plat/allwinner/common/sunxi_bl31_setup.c
|
||||
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_fixup.h>
|
||||
-#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/generic_delay_timer.h>
|
||||
#include <drivers/ti/uart/uart_16550.h>
|
||||
@@ -33,11 +32,6 @@ static console_t console;
|
||||
|
||||
static void *fdt;
|
||||
|
||||
-static const gicv2_driver_data_t sunxi_gic_data = {
|
||||
- .gicd_base = SUNXI_GICD_BASE,
|
||||
- .gicc_base = SUNXI_GICC_BASE,
|
||||
-};
|
||||
-
|
||||
/*
|
||||
* Try to find a DTB loaded in memory by previous stages.
|
||||
*
|
||||
@@ -149,12 +143,6 @@ void bl31_platform_setup(void)
|
||||
NOTICE("BL31: No DTB found.\n");
|
||||
}
|
||||
|
||||
- /* Configure the interrupt controller */
|
||||
- gicv2_driver_init(&sunxi_gic_data);
|
||||
- gicv2_distif_init();
|
||||
- gicv2_pcpu_distif_init();
|
||||
- gicv2_cpuif_enable();
|
||||
-
|
||||
sunxi_security_setup();
|
||||
|
||||
/*
|
||||
--- a/plat/allwinner/common/sunxi_native_pm.c
|
||||
+++ b/plat/allwinner/common/sunxi_native_pm.c
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
-#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
@@ -27,21 +26,15 @@ static int sunxi_pwr_domain_on(u_registe
|
||||
|
||||
static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
- gicv2_cpuif_disable();
|
||||
-
|
||||
sunxi_cpu_power_off_self();
|
||||
}
|
||||
|
||||
static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
- gicv2_pcpu_distif_init();
|
||||
- gicv2_cpuif_enable();
|
||||
}
|
||||
|
||||
static void sunxi_system_off(void)
|
||||
{
|
||||
- gicv2_cpuif_disable();
|
||||
-
|
||||
/* Attempt to power down the board (may not return) */
|
||||
sunxi_power_down();
|
||||
|
||||
@@ -52,8 +45,6 @@ static void sunxi_system_off(void)
|
||||
|
||||
static void __dead2 sunxi_system_reset(void)
|
||||
{
|
||||
- gicv2_cpuif_disable();
|
||||
-
|
||||
/* 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) */
|
||||
--- a/plat/allwinner/common/sunxi_scpi_pm.c
|
||||
+++ b/plat/allwinner/common/sunxi_scpi_pm.c
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/css/css_scpi.h>
|
||||
-#include <drivers/arm/gicv2.h>
|
||||
+#include <drivers/arm/gic.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
|
||||
@@ -74,9 +74,19 @@ static void sunxi_pwr_domain_off(const p
|
||||
plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state);
|
||||
plat_local_state_t system_pwr_state = SYSTEM_PWR_STATE(target_state);
|
||||
|
||||
- if (is_local_state_off(cpu_pwr_state)) {
|
||||
- gicv2_cpuif_disable();
|
||||
- }
|
||||
+ scpi_set_css_power_state(read_mpidr(),
|
||||
+ cpu_pwr_state,
|
||||
+ cluster_pwr_state,
|
||||
+ system_pwr_state);
|
||||
+}
|
||||
+
|
||||
+static void sunxi_pwr_domain_suspend(const psci_power_state_t *target_state)
|
||||
+{
|
||||
+ plat_local_state_t cpu_pwr_state = CPU_PWR_STATE(target_state);
|
||||
+ plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state);
|
||||
+ plat_local_state_t system_pwr_state = SYSTEM_PWR_STATE(target_state);
|
||||
+
|
||||
+ gic_save();
|
||||
|
||||
scpi_set_css_power_state(read_mpidr(),
|
||||
cpu_pwr_state,
|
||||
@@ -86,21 +96,18 @@ static void sunxi_pwr_domain_off(const p
|
||||
|
||||
static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
- if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
|
||||
- gicv2_distif_init();
|
||||
- }
|
||||
- if (is_local_state_off(CPU_PWR_STATE(target_state))) {
|
||||
- gicv2_pcpu_distif_init();
|
||||
- gicv2_cpuif_enable();
|
||||
- }
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static void sunxi_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
|
||||
+{
|
||||
+ gic_resume();
|
||||
}
|
||||
|
||||
static void sunxi_system_off(void)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
- gicv2_cpuif_disable();
|
||||
-
|
||||
/* Send the power down request to the SCP. */
|
||||
ret = scpi_sys_power_state(scpi_system_shutdown);
|
||||
if (ret != SCP_OK) {
|
||||
@@ -112,8 +119,6 @@ static void sunxi_system_reset(void)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
- gicv2_cpuif_disable();
|
||||
-
|
||||
/* Send the system reset request to the SCP. */
|
||||
ret = scpi_sys_power_state(scpi_system_reboot);
|
||||
if (ret != SCP_OK) {
|
||||
@@ -128,8 +133,6 @@ static int sunxi_system_reset2(int is_ve
|
||||
if (is_vendor || (reset_type != PSCI_RESET2_SYSTEM_WARM_RESET))
|
||||
return PSCI_E_NOT_SUPPORTED;
|
||||
|
||||
- gicv2_cpuif_disable();
|
||||
-
|
||||
/* Send the system reset request to the SCP. */
|
||||
ret = scpi_sys_power_state(scpi_system_reset);
|
||||
if (ret != SCP_OK) {
|
||||
@@ -190,9 +193,9 @@ static const plat_psci_ops_t sunxi_scpi_
|
||||
.cpu_standby = sunxi_cpu_standby,
|
||||
.pwr_domain_on = sunxi_pwr_domain_on,
|
||||
.pwr_domain_off = sunxi_pwr_domain_off,
|
||||
- .pwr_domain_suspend = sunxi_pwr_domain_off,
|
||||
+ .pwr_domain_suspend = sunxi_pwr_domain_suspend,
|
||||
.pwr_domain_on_finish = sunxi_pwr_domain_on_finish,
|
||||
- .pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish,
|
||||
+ .pwr_domain_suspend_finish = sunxi_pwr_domain_suspend_finish,
|
||||
.system_off = sunxi_system_off,
|
||||
.system_reset = sunxi_system_reset,
|
||||
.system_reset2 = sunxi_system_reset2,
|
||||
+505
@@ -0,0 +1,505 @@
|
||||
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;
|
||||
+}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
From cd69f2aad5f14c53be857cf178c928d6958f6fa3 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Thu, 16 Jan 2025 22:12:42 +0100
|
||||
Subject: [PATCH] refactor(allwinner): allow max cpus to be overridden
|
||||
|
||||
Some Allwinner SoCs, like A523, have more than 4 cores per cluster, so
|
||||
allow this macro to be overridden.
|
||||
|
||||
Change-Id: I384d3907cc7cb5be0a4a76f9081b5164629ec49c
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
---
|
||||
plat/allwinner/common/allwinner-common.mk | 4 ++++
|
||||
plat/allwinner/common/include/platform_def.h | 1 -
|
||||
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/plat/allwinner/common/allwinner-common.mk
|
||||
+++ b/plat/allwinner/common/allwinner-common.mk
|
||||
@@ -99,3 +99,7 @@ SEPARATE_CODE_AND_RODATA := 1
|
||||
|
||||
# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL
|
||||
RESET_TO_BL31 := 1
|
||||
+
|
||||
+# Most Allwinner SoCs have 4 cores, but not all
|
||||
+PLATFORM_MAX_CPUS_PER_CLUSTER ?= 4
|
||||
+$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER))
|
||||
--- a/plat/allwinner/common/include/platform_def.h
|
||||
+++ b/plat/allwinner/common/include/platform_def.h
|
||||
@@ -72,7 +72,6 @@
|
||||
#define PLATFORM_CLUSTER_COUNT U(1)
|
||||
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
|
||||
PLATFORM_MAX_CPUS_PER_CLUSTER)
|
||||
-#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
|
||||
#define PLATFORM_STACK_SIZE (0x1000 / PLATFORM_CORE_COUNT)
|
||||
|
||||
#ifndef SPD_none
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
From 26a5fb2370615b1b20ed6425bc608b333a68d2ca Mon Sep 17 00:00:00 2001
|
||||
From: Andre Przywara <andre.przywara@arm.com>
|
||||
Date: Sun, 14 Sep 2025 12:50:10 +0100
|
||||
Subject: [PATCH] feat(allwinner): plat_core_pos: support MT bit
|
||||
|
||||
So far all CPU cores used in Allwinner SoCs use the older MPIDR
|
||||
affinity style, where the MT bit is clear, and the cores are enumerated
|
||||
using the Aff0 MPIDR field.
|
||||
Newer SoCs use a newer generation of Arm Cortex cores, which set the MT
|
||||
bit and put the core number in the Aff1 field.
|
||||
|
||||
To accommodate both generations within the shared code, query the MT bit
|
||||
during the calculation, and use one or the other calculation method.
|
||||
|
||||
Change-Id: I2aa5de8c759e0ae5d1cd4a04b6dcc82cadf855ef
|
||||
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
plat/allwinner/common/plat_helpers.S | 9 ++++++---
|
||||
plat/allwinner/common/sunxi_topology.c | 18 ++++++++++++------
|
||||
2 files changed, 18 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/plat/allwinner/common/plat_helpers.S
|
||||
+++ b/plat/allwinner/common/plat_helpers.S
|
||||
@@ -32,11 +32,14 @@ func plat_crash_console_flush
|
||||
ret
|
||||
endfunc plat_crash_console_flush
|
||||
|
||||
+/* All Allwinner SoCs group all their cores in one affinity level */
|
||||
func plat_my_core_pos
|
||||
mrs x0, mpidr_el1
|
||||
- and x1, x0, #MPIDR_CLUSTER_MASK
|
||||
- and x0, x0, #MPIDR_CPU_MASK
|
||||
- add x0, x0, x1, LSR #6
|
||||
+ /* shift MPIDR left by 8 bits if needed to always place cores in Aff1 */
|
||||
+ tst x0, #MPIDR_MT_MASK
|
||||
+ lsl x1, x0, #MPIDR_AFFINITY_BITS
|
||||
+ csel x1, x1, x0, eq
|
||||
+ ubfx x0, x1, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ret
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
--- a/plat/allwinner/common/sunxi_topology.c
|
||||
+++ b/plat/allwinner/common/sunxi_topology.c
|
||||
@@ -18,19 +18,25 @@ static const unsigned char plat_power_do
|
||||
PLATFORM_MAX_CPUS_PER_CLUSTER,
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * All Allwinner SoCs place all their cores in one affinity level. Which one
|
||||
+ * this is just differs depending on whether they use the "new" MPDIR encoding
|
||||
+ * (cores in Aff1, clusters in Aff2) or the traditional one (cores in Aff0).
|
||||
+ */
|
||||
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
- unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
- unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
+ if (!(read_mpidr() & MPIDR_MT_MASK)) {
|
||||
+ mpidr <<= MPIDR_AFFINITY_BITS;
|
||||
+ }
|
||||
|
||||
- if (MPIDR_AFFLVL3_VAL(mpidr) > 0 ||
|
||||
+ if (MPIDR_AFFLVL0_VAL(mpidr) > 0 ||
|
||||
+ MPIDR_AFFLVL1_VAL(mpidr) >= PLATFORM_CORE_COUNT ||
|
||||
MPIDR_AFFLVL2_VAL(mpidr) > 0 ||
|
||||
- cluster >= PLATFORM_CLUSTER_COUNT ||
|
||||
- core >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
|
||||
+ MPIDR_AFFLVL3_VAL(mpidr) > 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
- return cluster * PLATFORM_MAX_CPUS_PER_CLUSTER + core;
|
||||
+ return MPIDR_AFFLVL1_VAL(mpidr);
|
||||
}
|
||||
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
From bb80445f8308e27127c36e902c5a76ce0458bf53 Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Mon, 27 Oct 2025 21:54:32 +0100
|
||||
Subject: [PATCH] feat(allwinner): add plat_arm_calc_core_pos helper
|
||||
|
||||
This helper is just generalized version of plat_my_core_pos().
|
||||
|
||||
It will be needed for generic gic driver for gicv3.
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
---
|
||||
plat/allwinner/common/plat_helpers.S | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/plat/allwinner/common/plat_helpers.S
|
||||
+++ b/plat/allwinner/common/plat_helpers.S
|
||||
@@ -12,6 +12,7 @@
|
||||
.globl plat_crash_console_init
|
||||
.globl plat_crash_console_putc
|
||||
.globl plat_crash_console_flush
|
||||
+ .globl plat_arm_calc_core_pos
|
||||
.globl plat_my_core_pos
|
||||
.globl platform_mem_init
|
||||
.globl plat_report_exception
|
||||
@@ -33,14 +34,18 @@ func plat_crash_console_flush
|
||||
endfunc plat_crash_console_flush
|
||||
|
||||
/* All Allwinner SoCs group all their cores in one affinity level */
|
||||
-func plat_my_core_pos
|
||||
- mrs x0, mpidr_el1
|
||||
+func plat_arm_calc_core_pos
|
||||
/* shift MPIDR left by 8 bits if needed to always place cores in Aff1 */
|
||||
tst x0, #MPIDR_MT_MASK
|
||||
lsl x1, x0, #MPIDR_AFFINITY_BITS
|
||||
csel x1, x1, x0, eq
|
||||
ubfx x0, x1, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ret
|
||||
+endfunc plat_arm_calc_core_pos
|
||||
+
|
||||
+func plat_my_core_pos
|
||||
+ mrs x0, mpidr_el1
|
||||
+ b plat_arm_calc_core_pos
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
func platform_mem_init
|
||||
+463
@@ -0,0 +1,463 @@
|
||||
From e019f64d91ff7c2dfbbfe7f76a14f240761b9edc Mon Sep 17 00:00:00 2001
|
||||
From: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Date: Sun, 12 Jan 2025 21:48:24 +0100
|
||||
Subject: [PATCH] feat(allwinner): add A523 support
|
||||
|
||||
The Allwinner A523 features two clusters with four Cortex-A55 cores
|
||||
each, also use an Arm GIC-600 for the interrupt controller. The memory
|
||||
map changes a bit, but most of the peripherals are compatible as far as
|
||||
TF-A is concerned.
|
||||
An exception are the CPU ops, which turn the power of cores on or off,
|
||||
they use a separate implementation, dictated by the DSU interconnect.
|
||||
|
||||
Add a new build platform, enabling the Cortex-A55 cores, and provide an
|
||||
A55 specific Makefile snippet. Describe the new memory map, and add the
|
||||
new CPU ops implementation.
|
||||
|
||||
Change-Id: I10d5bd1224e21593ab96ec62b986e01b141bf8d8
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
|
||||
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
|
||||
---
|
||||
docs/plat/allwinner.rst | 2 +
|
||||
plat/allwinner/common/allwinner-common-a55.mk | 25 ++++
|
||||
plat/allwinner/common/include/plat_macros.S | 4 +
|
||||
plat/allwinner/common/include/sunxi_def.h | 1 +
|
||||
plat/allwinner/common/sunxi_bl31_setup.c | 15 +++
|
||||
plat/allwinner/common/sunxi_native_pm_a55.c | 118 ++++++++++++++++++
|
||||
plat/allwinner/common/sunxi_security.c | 17 +++
|
||||
.../allwinner/sun55i_a523/include/sunxi_ccu.h | 14 +++
|
||||
.../sun55i_a523/include/sunxi_cpucfg.h | 7 ++
|
||||
.../sun55i_a523/include/sunxi_mmap.h | 50 ++++++++
|
||||
.../allwinner/sun55i_a523/include/sunxi_spc.h | 17 +++
|
||||
plat/allwinner/sun55i_a523/platform.mk | 25 ++++
|
||||
.../allwinner/sun55i_a523/sunxi_idle_states.c | 11 ++
|
||||
plat/allwinner/sun55i_a523/sunxi_power.c | 20 +++
|
||||
14 files changed, 326 insertions(+)
|
||||
create mode 100644 plat/allwinner/common/allwinner-common-a55.mk
|
||||
create mode 100644 plat/allwinner/common/sunxi_native_pm_a55.c
|
||||
create mode 100644 plat/allwinner/sun55i_a523/include/sunxi_ccu.h
|
||||
create mode 100644 plat/allwinner/sun55i_a523/include/sunxi_cpucfg.h
|
||||
create mode 100644 plat/allwinner/sun55i_a523/include/sunxi_mmap.h
|
||||
create mode 100644 plat/allwinner/sun55i_a523/include/sunxi_spc.h
|
||||
create mode 100644 plat/allwinner/sun55i_a523/platform.mk
|
||||
create mode 100644 plat/allwinner/sun55i_a523/sunxi_idle_states.c
|
||||
create mode 100644 plat/allwinner/sun55i_a523/sunxi_power.c
|
||||
|
||||
--- a/docs/plat/allwinner.rst
|
||||
+++ b/docs/plat/allwinner.rst
|
||||
@@ -27,6 +27,8 @@ There is one build target per supported
|
||||
+------+-------------------+
|
||||
| R329 | sun50i_r329 |
|
||||
+------+-------------------+
|
||||
+| A523 | sun55i_a523 |
|
||||
++------+-------------------+
|
||||
|
||||
To build with the default settings for a particular SoC:
|
||||
|
||||
--- /dev/null
|
||||
+++ b/plat/allwinner/common/allwinner-common-a55.mk
|
||||
@@ -0,0 +1,25 @@
|
||||
+#
|
||||
+# Copyright (c) 2025, ARM Limited and Contributors. All rights reserved.
|
||||
+#
|
||||
+# SPDX-License-Identifier: BSD-3-Clause
|
||||
+#
|
||||
+
|
||||
+BL31_SOURCES += lib/cpus/${ARCH}/cortex_a55.S
|
||||
+
|
||||
+ifeq (${SUNXI_PSCI_USE_NATIVE},1)
|
||||
+BL31_SOURCES += ${AW_PLAT}/common/sunxi_native_pm_a55.c
|
||||
+endif
|
||||
+
|
||||
+# A55 cores use GIC-600
|
||||
+USE_GIC_DRIVER := 3
|
||||
+GICV3_SUPPORT_GIC600 := 1
|
||||
+
|
||||
+# ARISC SCP not yet supported
|
||||
+SUNXI_PSCI_USE_SCPI := 0
|
||||
+
|
||||
+# Enable workarounds for Cortex-A55 errata. Allwinner uses at least r2p0.
|
||||
+ERRATA_A55_1530923 := 1
|
||||
+
|
||||
+USE_COHERENT_MEM := 0
|
||||
+WARMBOOT_ENABLE_DCACHE_EARLY := 1
|
||||
+HW_ASSISTED_COHERENCY := 1
|
||||
--- a/plat/allwinner/common/include/plat_macros.S
|
||||
+++ b/plat/allwinner/common/include/plat_macros.S
|
||||
@@ -19,7 +19,11 @@
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
.macro plat_crash_print_regs
|
||||
+#if USE_GIC_DRIVER == 3
|
||||
+ mov_imm x17, SUNXI_GICR_BASE
|
||||
+#else
|
||||
mov_imm x17, SUNXI_GICC_BASE
|
||||
+#endif
|
||||
mov_imm x16, SUNXI_GICD_BASE
|
||||
arm_print_gic_regs
|
||||
.endm
|
||||
--- a/plat/allwinner/common/include/sunxi_def.h
|
||||
+++ b/plat/allwinner/common/include/sunxi_def.h
|
||||
@@ -19,6 +19,7 @@
|
||||
#define SUNXI_SOC_H6 0x1728
|
||||
#define SUNXI_SOC_H616 0x1823
|
||||
#define SUNXI_SOC_R329 0x1851
|
||||
+#define SUNXI_SOC_A523 0x1890
|
||||
|
||||
#define SUNXI_VER_BITS_MASK 0xffU
|
||||
#define JEDEC_ALLWINNER_BKID 9U
|
||||
--- a/plat/allwinner/common/sunxi_bl31_setup.c
|
||||
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <drivers/generic_delay_timer.h>
|
||||
#include <drivers/ti/uart/uart_16550.h>
|
||||
#include <lib/mmio.h>
|
||||
+#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <sunxi_def.h>
|
||||
@@ -32,6 +33,13 @@ static console_t console;
|
||||
|
||||
static void *fdt;
|
||||
|
||||
+#if USE_GIC_DRIVER == 3
|
||||
+static const uintptr_t sunxi_gicr_base_addrs[2] = {
|
||||
+ SUNXI_GICR_BASE,
|
||||
+ 0U
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Try to find a DTB loaded in memory by previous stages.
|
||||
*
|
||||
@@ -123,6 +131,9 @@ void bl31_platform_setup(void)
|
||||
case SUNXI_SOC_R329:
|
||||
soc_name = "R329";
|
||||
break;
|
||||
+ case SUNXI_SOC_A523:
|
||||
+ soc_name = "A523";
|
||||
+ break;
|
||||
default:
|
||||
soc_name = "unknown";
|
||||
break;
|
||||
@@ -166,6 +177,10 @@ void bl31_platform_setup(void)
|
||||
|
||||
sunxi_pmic_setup(soc_id, fdt);
|
||||
|
||||
+#if USE_GIC_DRIVER == 3
|
||||
+ gic_set_gicr_frames(sunxi_gicr_base_addrs);
|
||||
+#endif
|
||||
+
|
||||
INFO("BL31: Platform setup done\n");
|
||||
}
|
||||
|
||||
--- /dev/null
|
||||
+++ b/plat/allwinner/common/sunxi_native_pm_a55.c
|
||||
@@ -0,0 +1,118 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2025, ARM Limited and Contributors. All rights reserved.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ */
|
||||
+
|
||||
+#include <arch_helpers.h>
|
||||
+#include <common/debug.h>
|
||||
+#include <lib/mmio.h>
|
||||
+#include <lib/psci/psci.h>
|
||||
+#include <lib/utils_def.h>
|
||||
+#include <plat/common/platform.h>
|
||||
+
|
||||
+#include <platform_def.h>
|
||||
+#include <sunxi_cpucfg.h>
|
||||
+#include <sunxi_mmap.h>
|
||||
+#include <sunxi_private.h>
|
||||
+
|
||||
+#define SUNXI_WDOG0_SRST_REG (SUNXI_R_WDOG_BASE + 0x0008)
|
||||
+
|
||||
+#define SUNXI_INITARCH_REG(n) (SUNXI_CPUCFG_BASE + 0x0020 + (n) * 4)
|
||||
+#define HOTPLUG_CONTROL_REG(n) (SUNXI_R_CPUCFG_BASE + 0x200 + (n) * 4)
|
||||
+#define HOTPLUG_POWERMODE_REG(n) (SUNXI_R_CPUCFG_BASE + 0x220 + (n) * 4)
|
||||
+#define PPU_PWSR(n) (SUNXI_R_CPUCFG_BASE + (n) * 0x1000 + 0x1008)
|
||||
+
|
||||
+#define STATE_ON 8
|
||||
+#define STATE_OFF 0
|
||||
+
|
||||
+#define GIC_WAKEUP_DISABLE BIT(1)
|
||||
+#define POWER_ON BIT(0)
|
||||
+
|
||||
+#define HOTPLUG_EN BIT(0)
|
||||
+
|
||||
+#define AARCH64 BIT(0)
|
||||
+
|
||||
+static void sunxi_cpu_off(u_register_t mpidr)
|
||||
+{
|
||||
+ unsigned int core = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
+
|
||||
+ mmio_clrbits_32(HOTPLUG_POWERMODE_REG(core), POWER_ON);
|
||||
+
|
||||
+ mmio_setbits_32(HOTPLUG_CONTROL_REG(core), GIC_WAKEUP_DISABLE);
|
||||
+}
|
||||
+
|
||||
+static int sunxi_pwr_domain_on(u_register_t mpidr)
|
||||
+{
|
||||
+ unsigned int core = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
+
|
||||
+ mmio_setbits_32(SUNXI_INITARCH_REG(core), AARCH64);
|
||||
+
|
||||
+ while ((mmio_read_32(PPU_PWSR(core + 1)) & 0xf) != STATE_OFF)
|
||||
+ ;
|
||||
+
|
||||
+ mmio_setbits_32(HOTPLUG_POWERMODE_REG(core), POWER_ON);
|
||||
+ mmio_setbits_32(HOTPLUG_CONTROL_REG(core), HOTPLUG_EN);
|
||||
+
|
||||
+ while ((mmio_read_32(PPU_PWSR(core + 1)) & 0xf) != STATE_ON)
|
||||
+ ;
|
||||
+
|
||||
+ mmio_clrbits_32(HOTPLUG_CONTROL_REG(core), HOTPLUG_EN);
|
||||
+ mmio_clrbits_32(HOTPLUG_POWERMODE_REG(core), POWER_ON);
|
||||
+
|
||||
+ return PSCI_E_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
+{
|
||||
+ sunxi_cpu_off(read_mpidr());
|
||||
+}
|
||||
+
|
||||
+static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
+{
|
||||
+ unsigned int core = plat_my_core_pos();
|
||||
+
|
||||
+ mmio_clrbits_32(HOTPLUG_CONTROL_REG(core), GIC_WAKEUP_DISABLE);
|
||||
+}
|
||||
+
|
||||
+static void sunxi_system_off(void)
|
||||
+{
|
||||
+ unsigned int cluster;
|
||||
+ unsigned int core;
|
||||
+
|
||||
+ /* Attempt to power down the board (may not return) */
|
||||
+ sunxi_power_down();
|
||||
+
|
||||
+ /* Turn off all CPUs */
|
||||
+ for (cluster = 0; cluster < PLATFORM_CLUSTER_COUNT; ++cluster) {
|
||||
+ for (core = 0; core < PLATFORM_MAX_CPUS_PER_CLUSTER; ++core) {
|
||||
+ u_register_t mpidr = (cluster << MPIDR_AFF2_SHIFT) |
|
||||
+ (core << MPIDR_AFF1_SHIFT) |
|
||||
+ BIT(24) | BIT(31);
|
||||
+ sunxi_cpu_off(mpidr);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void __dead2 sunxi_system_reset(void)
|
||||
+{
|
||||
+ /* Reset the whole system when using watchdog reset */
|
||||
+ mmio_write_32(SUNXI_WDOG0_SRST_REG, 0x16aa0001);
|
||||
+
|
||||
+ 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;
|
||||
+}
|
||||
--- a/plat/allwinner/common/sunxi_security.c
|
||||
+++ b/plat/allwinner/common/sunxi_security.c
|
||||
@@ -37,4 +37,21 @@ void sunxi_security_setup(void)
|
||||
|
||||
/* Set all DMA channels (16 max.) to non-secure */
|
||||
mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff);
|
||||
+
|
||||
+ /* Some SoCs feature more protection bits in the PRCM block */
|
||||
+#ifdef SUNXI_R_TZMA_BASE
|
||||
+ mmio_write_32(SUNXI_R_TZMA_BASE + 0, 0);
|
||||
+ mmio_write_32(SUNXI_R_TZMA_BASE + 4, 0);
|
||||
+ mmio_write_32(SUNXI_R_TZMA_BASE + 8, 0);
|
||||
+#endif
|
||||
+
|
||||
+#ifdef SUNXI_R_SPC_BASE
|
||||
+ mmio_write_32(SUNXI_R_SPC_BASE + 0x04, 0xffffffff);
|
||||
+ mmio_write_32(SUNXI_R_SPC_BASE + 0x14, 0xffffffff);
|
||||
+ mmio_write_32(SUNXI_R_SPC_BASE + 0x24, 0xffffffff);
|
||||
+#endif
|
||||
+
|
||||
+#ifdef SUNXI_DSP_PRCM_BASE
|
||||
+ mmio_write_32(SUNXI_DSP_PRCM_BASE + 8, 7);
|
||||
+#endif
|
||||
}
|
||||
--- /dev/null
|
||||
+++ b/plat/allwinner/sun55i_a523/include/sunxi_ccu.h
|
||||
@@ -0,0 +1,14 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2025, ARM Limited and Contributors. All rights reserved.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ */
|
||||
+
|
||||
+#ifndef SUNXI_CCU_H
|
||||
+#define SUNXI_CCU_H
|
||||
+
|
||||
+#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00)
|
||||
+
|
||||
+#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290)
|
||||
+
|
||||
+#endif /* SUNXI_CCU_H */
|
||||
--- /dev/null
|
||||
+++ b/plat/allwinner/sun55i_a523/include/sunxi_cpucfg.h
|
||||
@@ -0,0 +1,7 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2025, ARM Limited and Contributors. All rights reserved.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ */
|
||||
+
|
||||
+#include <sunxi_cpucfg_ncat2.h>
|
||||
--- /dev/null
|
||||
+++ b/plat/allwinner/sun55i_a523/include/sunxi_mmap.h
|
||||
@@ -0,0 +1,50 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2025, ARM Limited and Contributors. All rights reserved.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ */
|
||||
+
|
||||
+#ifndef SUNXI_MMAP_H
|
||||
+#define SUNXI_MMAP_H
|
||||
+
|
||||
+/* Memory regions */
|
||||
+#define SUNXI_ROM_BASE 0x00000000
|
||||
+#define SUNXI_ROM_SIZE 0x00010000
|
||||
+#define SUNXI_SRAM_BASE 0x00020000
|
||||
+#define SUNXI_SRAM_SIZE 0x00044000
|
||||
+#define SUNXI_SRAM_A1_BASE 0x00020000
|
||||
+#define SUNXI_SRAM_A1_SIZE 0x00020000
|
||||
+#define SUNXI_SRAM_A2_BASE 0x00040000
|
||||
+#define SUNXI_SRAM_A2_BL31_OFFSET 0x00014000
|
||||
+#define SUNXI_SRAM_A2_SIZE 0x00024000
|
||||
+#define SUNXI_DEV_BASE 0x01000000
|
||||
+#define SUNXI_DEV_SIZE 0x09000000
|
||||
+#define SUNXI_DRAM_BASE 0x40000000
|
||||
+#define SUNXI_DRAM_VIRT_BASE 0x0a000000
|
||||
+
|
||||
+/* Memory-mapped devices */
|
||||
+#define SUNXI_PIO_BASE 0x02000000
|
||||
+#define SUNXI_SPC_BASE 0x02000800
|
||||
+#define SUNXI_CCU_BASE 0x02001000
|
||||
+#define SUNXI_WDOG_BASE 0x02050000
|
||||
+#define SUNXI_UART0_BASE 0x02500000
|
||||
+#define SUNXI_SYSCON_BASE 0x03000000
|
||||
+#define SUNXI_DMA_BASE 0x03002000
|
||||
+#define SUNXI_SID_BASE 0x03006000
|
||||
+#define SUNXI_GICD_BASE 0x03400000
|
||||
+#define SUNXI_GICR_BASE 0x03460000
|
||||
+#define SUNXI_SPI0_BASE 0x04025000
|
||||
+#define SUNXI_R_SPC_BASE 0x07002000
|
||||
+#define SUNXI_R_TZMA_BASE 0x07002400
|
||||
+#define SUNXI_R_PRCM_BASE 0x07010000
|
||||
+#define SUNXI_R_WDOG_BASE 0x07020400
|
||||
+#define SUNXI_R_PIO_BASE 0x07022000
|
||||
+#define SUNXI_R_CPUCFG_BASE 0x07050000
|
||||
+#define SUNXI_R_UART_BASE 0x07080000
|
||||
+#define SUNXI_R_I2C_BASE 0x07081400
|
||||
+#define SUNXI_MSGBOX_BASE 0x07094000
|
||||
+#define SUNXI_DSP_PRCM_BASE 0x07102000
|
||||
+#define SUNXI_CPUCFG_BASE 0x08000000
|
||||
+#define SUNXI_C0_CPUXCFG_BASE 0x09010000
|
||||
+
|
||||
+#endif /* SUNXI_MMAP_H */
|
||||
--- /dev/null
|
||||
+++ b/plat/allwinner/sun55i_a523/include/sunxi_spc.h
|
||||
@@ -0,0 +1,17 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2025 ARM Limited and Contributors. All rights reserved.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ */
|
||||
+
|
||||
+#ifndef SUNXI_SPC_H
|
||||
+#define SUNXI_SPC_H
|
||||
+
|
||||
+/* Get by REing stock ATF and checking initialization loop boundary */
|
||||
+#define SUNXI_SPC_NUM_PORTS 14
|
||||
+
|
||||
+#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
|
||||
+#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
|
||||
+#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
|
||||
+
|
||||
+#endif /* SUNXI_SPC_H */
|
||||
--- /dev/null
|
||||
+++ b/plat/allwinner/sun55i_a523/platform.mk
|
||||
@@ -0,0 +1,25 @@
|
||||
+#
|
||||
+# Copyright (c) 2025, ARM Limited and Contributors. All rights reserved.
|
||||
+#
|
||||
+# SPDX-License-Identifier: BSD-3-Clause
|
||||
+#
|
||||
+
|
||||
+# Allwinner A523 supports Armv8.2 extensions
|
||||
+ARM_ARCH_MAJOR := 8
|
||||
+ARM_ARCH_MINOR := 2
|
||||
+
|
||||
+# There are 8 cores in 1 cluster
|
||||
+PLATFORM_MAX_CPUS_PER_CLUSTER := 8
|
||||
+
|
||||
+SUNXI_SETUP_REGULATORS := 0
|
||||
+
|
||||
+# No ARISC SCP support at the moment
|
||||
+SUNXI_PSCI_USE_SCPI := 0
|
||||
+SUNXI_PSCI_USE_NATIVE := 1
|
||||
+
|
||||
+# The differences between the platforms are covered by the include files.
|
||||
+include plat/allwinner/common/allwinner-common.mk
|
||||
+include plat/allwinner/common/allwinner-common-a55.mk
|
||||
+
|
||||
+# Put NOBITS memory in the first 64K of SRAM A2, overwriting U-Boot's SPL.
|
||||
+SEPARATE_NOBITS_REGION := 1
|
||||
--- /dev/null
|
||||
+++ b/plat/allwinner/sun55i_a523/sunxi_idle_states.c
|
||||
@@ -0,0 +1,11 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2025, ARM Limited and Contributors. All rights reserved.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ */
|
||||
+
|
||||
+#include <sunxi_private.h>
|
||||
+
|
||||
+const struct psci_cpu_idle_state sunxi_idle_states[] = {
|
||||
+ {}
|
||||
+};
|
||||
--- /dev/null
|
||||
+++ b/plat/allwinner/sun55i_a523/sunxi_power.c
|
||||
@@ -0,0 +1,20 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2025, ARM Limited and Contributors. All rights reserved.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: BSD-3-Clause
|
||||
+ */
|
||||
+
|
||||
+#include <platform_def.h>
|
||||
+#include <sunxi_mmap.h>
|
||||
+#include <sunxi_cpucfg.h>
|
||||
+#include <sunxi_private.h>
|
||||
+
|
||||
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
|
||||
+{
|
||||
+ /* PMIC not yet supported */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void sunxi_power_down(void)
|
||||
+{
|
||||
+}
|
||||
Reference in New Issue
Block a user