build/patch/u-boot/u-boot-sunxi-crust/h3-scp.patch

1447 lines
41 KiB
Diff
Raw Normal View History

From 566bc30291896e38b62dcf4677a7f99502e88021 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 17 Apr 2021 13:33:54 -0500
Subject: [PATCH 1/9] sunxi: binman: Enable SPL FIT loading for 32-bit SoCs
Now that Crust (SCP firmware) has support for H3, we need a FIT image to
load it. H3 also needs to load a SoC-specific eGon blob to support CPU 0
hotplug. Let's first enable FIT support before adding extra firmware.
Update the binman description to work on either 32-bit or 64-bit SoCs:
- Make BL31 optional, since it is not used on 32-bit SoCs (though BL32
may be used in the future).
- Explicitly set the minimum offset of the FIT to 32 KiB, since SPL on
some boards is still only 24 KiB large even with FIT support enabled.
CONFIG_SPL_PAD_TO cannot be used because it is not defined for H616.
FIT unlocks more features (signatures, multiple DTBs, etc.), so enable
it by default. A10 (sun4i) only has 24 KiB of SRAM A1, so it needs
SPL_FIT_IMAGE_TINY. For simplicity, enable that option everywhere.
Cover-letter:
sunxi: SPL FIT support for 32-bit sunxi SoCs
This series makes the necessary changes so 32-bit sunxi SoCs can load
additional device trees or firmware from SPL along with U-Boot proper.
There was no existing binman entry property that put the FIT at the
right offset. The minimum offset is 32k, but this matches neither the
SPL size (which is no more than 24k on some SoCs) nor the FIT alignment
(which is 512 bytes in practice due to SPL size constraints). So instead
of adding a new property, I fixed what is arguably a bug in the offset
property -- though this strategy will not work if someone is
intentionally creating overlapping entries.
END
Series-to: sunxi
Series-to: sjg
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm/Kconfig | 1 +
arch/arm/dts/sunxi-u-boot.dtsi | 44 ++++++++++++++++++++++------------
common/spl/Kconfig | 7 +++---
3 files changed, 34 insertions(+), 18 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index da8efdea71..309df7b05d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1169,6 +1169,7 @@ config ARCH_SUNXI
imply SPL_GPIO
imply SPL_LIBCOMMON_SUPPORT
imply SPL_LIBGENERIC_SUPPORT
+ imply SPL_LOAD_FIT
imply SPL_MMC if MMC
imply SPL_POWER
imply SPL_SERIAL
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index af419c7e59..1353d6e668 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -1,13 +1,19 @@
#include <config.h>
-#ifdef CONFIG_MACH_SUN50I_H6
-#define BL31_ADDR 0x104000
-#define SCP_ADDR 0x114000
-#elif defined(CONFIG_MACH_SUN50I_H616)
-#define BL31_ADDR 0x40000000
+#ifdef CONFIG_ARM64
+#define ARCH "arm64"
#else
-#define BL31_ADDR 0x44000
-#define SCP_ADDR 0x50000
+#define ARCH "arm"
+#endif
+
+#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H5)
+#define BL31_ADDR 0x00044000
+#define SCP_ADDR 0x00050000
+#elif defined(CONFIG_MACH_SUN50I_H6)
+#define BL31_ADDR 0x00104000
+#define SCP_ADDR 0x00114000
+#elif defined(CONFIG_MACH_SUN50I_H616)
+#define BL31_ADDR 0x40000000
#endif
/ {
@@ -37,30 +43,33 @@
filename = "spl/sunxi-spl.bin";
};
-#ifdef CONFIG_ARM64
+#ifdef CONFIG_SPL_LOAD_FIT
fit {
- description = "Configuration to load ATF before U-Boot";
+ description = "Configuration to load U-Boot and firmware";
+ offset = <32768>;
#address-cells = <1>;
fit,fdt-list = "of-list";
images {
uboot {
- description = "U-Boot (64-bit)";
+ description = "U-Boot";
type = "standalone";
os = "u-boot";
- arch = "arm64";
+ arch = ARCH;
compression = "none";
load = <CONFIG_TEXT_BASE>;
+ entry = <CONFIG_TEXT_BASE>;
u-boot-nodtb {
};
};
+#ifdef BL31_ADDR
atf {
description = "ARM Trusted Firmware";
type = "firmware";
os = "arm-trusted-firmware";
- arch = "arm64";
+ arch = ARCH;
compression = "none";
load = <BL31_ADDR>;
entry = <BL31_ADDR>;
@@ -70,6 +79,7 @@
missing-msg = "atf-bl31-sunxi";
};
};
+#endif
#ifdef SCP_ADDR
scp {
@@ -98,12 +108,16 @@
@config-SEQ {
description = "NAME";
+#ifdef BL31_ADDR
firmware = "atf";
-#ifndef SCP_ADDR
- loadables = "uboot";
#else
- loadables = "scp", "uboot";
+ firmware = "uboot";
+#endif
+ loadables =
+#ifdef SCP_ADDR
+ "scp",
#endif
+ "uboot";
fdt = "fdt-SEQ";
};
};
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 2c042ad306..4e52529e69 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -76,7 +76,9 @@ config SPL_SIZE_LIMIT_PROVIDE_STACK
config SPL_MAX_SIZE
hex "Maximum size of the SPL image, excluding BSS"
+ default 0x37fa0 if MACH_SUN50I_H616
default 0x30000 if ARCH_MX6 && MX6_OCRAM_256KB
+ default 0x25fa0 if MACH_SUN50I_H6
default 0x1b000 if AM33XX && !TI_SECURE_DEVICE
default 0x10000 if ARCH_MX6 && !MX6_OCRAM_256KB
default 0x7fa0 if SUNXI_SRAM_ADDRESS = 0x10000
@@ -97,7 +99,7 @@ config SPL_PAD_TO
default 0x31000 if ARCH_MX6 && MX6_OCRAM_256KB
default 0x11000 if ARCH_MX7 || (ARCH_MX6 && !MX6_OCRAM_256KB)
default 0x10000 if ARCH_KEYSTONE
- default 0x8000 if ARCH_SUNXI && !MACH_SUN50I_H616
+ default 0x0 if ARCH_SUNXI
default 0x0 if ARCH_MTMIPS
default TPL_MAX_SIZE if TPL_MAX_SIZE > SPL_MAX_SIZE
default SPL_MAX_SIZE
@@ -576,8 +578,7 @@ config SPL_MD5
config SPL_FIT_IMAGE_TINY
bool "Remove functionality from SPL FIT loading to reduce size"
depends on SPL_FIT
- default y if MACH_SUN50I || MACH_SUN50I_H5 || SUN50I_GEN_H6
- default y if ARCH_IMX8M || ARCH_IMX9
+ default y if ARCH_IMX8M || ARCH_IMX9 || ARCH_SUNXI
help
Enable this to reduce the size of the FIT image loading code
in SPL, if space for the SPL binary is very tight.
--
2.34.1
From 501729188de546502d939c3cedee7ec1ecb04a7b Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 9 Oct 2021 22:00:22 -0500
Subject: [PATCH 2/9] sunxi: psci: Avoid hanging when CPU 0 is hot-unplugged
Do not try to send an SGI from CPU 0 to itself. Since FIQs are masked
when entering monitor mode, this will hang. Plus, CPU 0 cannot fully
power itself off anyway. Instead, have it turn FIQs back on and continue
servicing SGIs from other cores.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm/cpu/armv7/sunxi/psci.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
index e1d3638b5c..738ea8f281 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -38,6 +38,15 @@
#define SUN8I_R40_PWR_CLAMP(cpu) (0x120 + (cpu) * 0x4)
#define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0 (0xbc)
+static inline u32 __secure cp15_read_mpidr(void)
+{
+ u32 val;
+
+ asm volatile ("mrc p15, 0, %0, c0, c0, 5" : "=r" (val));
+
+ return val;
+}
+
static void __secure cp15_write_cntp_tval(u32 tval)
{
asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval));
@@ -281,9 +290,14 @@ s32 __secure psci_cpu_off(void)
{
psci_cpu_off_common();
- /* Ask CPU0 via SGI15 to pull the rug... */
- writel(BIT(16) | 15, GICD_BASE + GICD_SGIR);
- dsb();
+ if (cp15_read_mpidr() & 3) {
+ /* Ask CPU0 via SGI15 to pull the rug... */
+ writel(BIT(16) | 15, GICD_BASE + GICD_SGIR);
+ dsb();
+ } else {
+ /* Unmask FIQs to service SGI15. */
+ asm volatile ("cpsie f");
+ }
/* Wait to be turned off */
while (1)
--
2.34.1
From e9e05a2a43d1641d2d864a06d38f190ee8538211 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 9 Oct 2021 17:12:57 -0500
Subject: [PATCH 3/9] sunxi: psci: Add support for H3 CPU 0 hotplug
Due to a bug in the H3 SoC, where the CPU 0 hotplug flag cannot be
written, resuming CPU 0 requires using the "Super Standby" code path in
the BROM instead of the hotplug path. This path requires jumping to an
eGON image in SRAM.
Add support to the build system to generate this eGON image and include
it in the FIT, and add code to direct the BROM to its location in SRAM.
Since the Super Standby code path in the BROM initializes the CPU and
AHB1 clocks to 24 MHz, those registers need to be restored after control
passes back to U-Boot. Furthermore, because the BROM lowers the AHB1
clock divider to /1 before switching to the lower-frequency parent,
PLL_PERIPH0 must be bypassed to prevent AHB1 from temporarily running at
600 MHz. Otherwise, this locks up the SoC.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
Makefile | 17 +++++++++++++++++
arch/arm/cpu/armv7/sunxi/psci.c | 31 +++++++++++++++++++++++++++++++
arch/arm/dts/sunxi-u-boot.dtsi | 23 ++++++++++++++++++++++-
include/configs/sun8i.h | 4 ++++
4 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 8b030f31be..6810784142 100644
--- a/Makefile
+++ b/Makefile
@@ -1014,6 +1014,23 @@ ifeq ($(CONFIG_ARCH_ROCKCHIP)_$(CONFIG_SPL_FRAMEWORK),y_)
INPUTS-y += u-boot.img
endif
+ifeq ($(CONFIG_MACH_SUN8I_H3)$(CONFIG_ARMV7_PSCI),yy)
+INPUTS-$(CONFIG_ARMV7_PSCI) += u-boot-resume.img
+
+MKIMAGEFLAGS_u-boot-resume.img := -B 0x400 -T sunxi_egon
+
+u-boot-resume.img: u-boot-resume.bin
+ $(call if_changed,mkimage)
+
+OBJCOPYFLAGS_u-boot-resume.bin := -O binary
+
+u-boot-resume.bin: u-boot-resume.o
+ $(call if_changed,objcopy)
+
+u-boot-resume.S: u-boot
+ @sed -En 's/(0x[[:xdigit:]]+) +psci_cpu_entry/ldr pc, =\1/p' $<.map > $@
+endif
+
INPUTS-$(CONFIG_X86) += u-boot-x86-start16.bin u-boot-x86-reset16.bin \
$(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \
$(if $(CONFIG_TPL_X86_16BIT_INIT),tpl/u-boot-tpl.bin)
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
index 738ea8f281..e6bfd193e4 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <asm/cache.h>
+#include <asm/arch/clock.h>
#include <asm/arch/cpu.h>
#include <asm/arch/cpucfg.h>
#include <asm/arch/prcm.h>
@@ -141,6 +142,13 @@ static void __secure sunxi_set_entry_address(void *entry)
(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
writel((u32)entry, &cpucfg->priv0);
+
+#ifdef CONFIG_MACH_SUN8I_H3
+ /* Redirect CPU 0 to the secure monitor via the resume shim. */
+ writel(0x16aaefe8, &cpucfg->super_standy_flag);
+ writel(0xaa16efe8, &cpucfg->super_standy_flag);
+ writel(SUNXI_RESUME_BASE, &cpucfg->priv1);
+#endif
}
#endif
@@ -255,9 +263,12 @@ out:
int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc,
u32 context_id)
{
+ struct sunxi_ccm_reg *ccu = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
struct sunxi_cpucfg_reg *cpucfg =
(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
u32 cpu = (mpidr & 0x3);
+ u32 cpu_clk;
+ u32 bus_clk;
/* store target PC and context id */
psci_save(cpu, pc, context_id);
@@ -274,12 +285,32 @@ int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc,
/* Lock CPU (Disable external debug access) */
clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_H3) && cpu == 0) {
+ /* Save registers that will be clobbered by the BROM. */
+ cpu_clk = readl(&ccu->cpu_axi_cfg);
+ bus_clk = readl(&ccu->ahb1_apb1_div);
+
+ /* Bypass PLL_PERIPH0 so AHB1 frequency does not spike. */
+ setbits_le32(&ccu->pll6_cfg, BIT(25));
+ }
+
/* Power up target CPU */
sunxi_cpu_set_power(cpu, true);
/* De-assert reset on target CPU */
writel(BIT(1) | BIT(0), &cpucfg->cpu[cpu].rst);
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_H3) && cpu == 0) {
+ /* Spin until the BROM has clobbered the clock registers. */
+ while (readl(&ccu->ahb1_apb1_div) != 0x00001100);
+
+ /* Restore the registers and turn off PLL_PERIPH0 bypass. */
+ writel(cpu_clk, &ccu->cpu_axi_cfg);
+ writel(bus_clk, &ccu->ahb1_apb1_div);
+
+ clrbits_le32(&ccu->pll6_cfg, BIT(25));
+ }
+
/* Unlock CPU (Disable external debug access) */
setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index 1353d6e668..5d45157598 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -6,7 +6,11 @@
#define ARCH "arm"
#endif
-#if defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H5)
+#if defined(CONFIG_MACH_SUN8I_H3)
+#ifdef CONFIG_ARMV7_PSCI
+#define RESUME_ADDR SUNXI_RESUME_BASE
+#endif
+#elif defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H5)
#define BL31_ADDR 0x00044000
#define SCP_ADDR 0x00050000
#elif defined(CONFIG_MACH_SUN50I_H6)
@@ -81,6 +85,20 @@
};
#endif
+#ifdef RESUME_ADDR
+ resume {
+ description = "Super Standby resume image";
+ type = "standalone";
+ arch = ARCH;
+ compression = "none";
+ load = <RESUME_ADDR>;
+
+ blob-ext {
+ filename = "u-boot-resume.img";
+ };
+ };
+#endif
+
#ifdef SCP_ADDR
scp {
description = "SCP firmware";
@@ -114,6 +132,9 @@
firmware = "uboot";
#endif
loadables =
+#ifdef RESUME_ADDR
+ "resume",
+#endif
#ifdef SCP_ADDR
"scp",
#endif
diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h
index 608a055892..98e68e068b 100644
--- a/include/configs/sun8i.h
+++ b/include/configs/sun8i.h
@@ -8,6 +8,10 @@
#ifndef __CONFIG_H
#define __CONFIG_H
+#define SUNXI_RESUME_BASE (CONFIG_ARMV7_SECURE_BASE + \
+ CONFIG_ARMV7_SECURE_MAX_SIZE)
+#define SUNXI_RESUME_SIZE 1024
+
#include <configs/sunxi-common.h>
#define CONFIG_MACH_TYPE (0x1029)
--
2.34.1
From 1ebddf814b3f2efeeeabf473c34c366a734688f5 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 9 Oct 2021 14:58:27 -0500
Subject: [PATCH 4/9] remoteproc: Add a driver for the Allwinner AR100
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
drivers/remoteproc/Kconfig | 9 ++
drivers/remoteproc/Makefile | 1 +
drivers/remoteproc/sun6i_ar100_rproc.c | 111 +++++++++++++++++++++++++
3 files changed, 121 insertions(+)
create mode 100644 drivers/remoteproc/sun6i_ar100_rproc.c
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 27e4a60ff5..bcaf6a2753 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -41,6 +41,15 @@ config REMOTEPROC_STM32_COPRO
Say 'y' here to add support for STM32 Cortex-M4 coprocessors via the
remoteproc framework.
+config REMOTEPROC_SUN6I_AR100
+ bool "Support for Allwinner AR100 SCP"
+ select REMOTEPROC
+ depends on ARCH_SUNXI
+ help
+ Say 'y' here to support Allwinner's AR100 System Control Processor
+ (SCP), found in various sun6i/sun8i/sun50i family SoCs, through the
+ remoteproc framework.
+
config REMOTEPROC_TI_K3_ARM64
bool "Support for TI's K3 based ARM64 remoteproc driver"
select REMOTEPROC
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index fbe9c172bc..9529844b2a 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_$(SPL_)REMOTEPROC) += rproc-uclass.o rproc-elf-loader.o
obj-$(CONFIG_K3_SYSTEM_CONTROLLER) += k3_system_controller.o
obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o
obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o
+obj-$(CONFIG_REMOTEPROC_SUN6I_AR100) += sun6i_ar100_rproc.o
obj-$(CONFIG_REMOTEPROC_TI_K3_ARM64) += ti_k3_arm64_rproc.o
obj-$(CONFIG_REMOTEPROC_TI_K3_DSP) += ti_k3_dsp_rproc.o
obj-$(CONFIG_REMOTEPROC_TI_K3_R5F) += ti_k3_r5f_rproc.o
diff --git a/drivers/remoteproc/sun6i_ar100_rproc.c b/drivers/remoteproc/sun6i_ar100_rproc.c
new file mode 100644
index 0000000000..c94f6c752b
--- /dev/null
+++ b/drivers/remoteproc/sun6i_ar100_rproc.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dm.h>
+#include <errno.h>
+#include <remoteproc.h>
+#include <asm/io.h>
+
+#define SUNXI_SCP_MAGIC 0xb4400012
+
+#define OR1K_VEC_FIRST 0x01
+#define OR1K_VEC_LAST 0x0e
+#define OR1K_VEC_ADDR(n) (0x100 * (n))
+
+struct sun6i_ar100_rproc_priv {
+ void *cfg_base;
+ ulong sram_base;
+};
+
+static int sun6i_ar100_rproc_load(struct udevice *dev, ulong addr, ulong size)
+{
+ struct sun6i_ar100_rproc_priv *priv = dev_get_priv(dev);
+
+ /* Check for a valid SCP firmware. */
+ if (readl_relaxed(addr) != SUNXI_SCP_MAGIC)
+ return -ENOENT;
+
+ /* Program exception vectors to the firmware entry point. */
+ for (u32 i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) {
+ ulong vector = priv->sram_base + OR1K_VEC_ADDR(i);
+ ulong offset = addr - vector;
+
+ writel_relaxed(offset >> 2, vector);
+ }
+
+ return 0;
+}
+
+static int sun6i_ar100_rproc_start(struct udevice *dev)
+{
+ struct sun6i_ar100_rproc_priv *priv = dev_get_priv(dev);
+
+ setbits_le32(priv->cfg_base, BIT(0));
+
+ return 0;
+}
+
+static int sun6i_ar100_rproc_stop(struct udevice *dev)
+{
+ struct sun6i_ar100_rproc_priv *priv = dev_get_priv(dev);
+
+ clrbits_le32(priv->cfg_base, BIT(0));
+
+ return 0;
+}
+
+static int sun6i_ar100_rproc_reset(struct udevice *dev)
+{
+ int ret;
+
+ ret = sun6i_ar100_rproc_stop(dev);
+ if (ret)
+ return ret;
+
+ return sun6i_ar100_rproc_start(dev);
+}
+
+static int sun6i_ar100_rproc_is_running(struct udevice *dev)
+{
+ struct sun6i_ar100_rproc_priv *priv = dev_get_priv(dev);
+
+ return !(readl_relaxed(priv->cfg_base) & BIT(0));
+}
+
+static const struct dm_rproc_ops sun6i_ar100_rproc_ops = {
+ .load = sun6i_ar100_rproc_load,
+ .start = sun6i_ar100_rproc_start,
+ .stop = sun6i_ar100_rproc_stop,
+ .reset = sun6i_ar100_rproc_reset,
+ .is_running = sun6i_ar100_rproc_is_running,
+};
+
+static int sun6i_ar100_rproc_probe(struct udevice *dev)
+{
+ struct sun6i_ar100_rproc_priv *priv = dev_get_priv(dev);
+ struct ofnode_phandle_args sram_handle;
+ int ret;
+
+ priv->cfg_base = dev_read_addr_ptr(dev);
+
+ ret = dev_read_phandle_with_args(dev, "sram", NULL, 0, 0, &sram_handle);
+ if (ret)
+ return ret;
+
+ priv->sram_base = ofnode_get_addr(sram_handle.node);
+
+ return 0;
+}
+
+static const struct udevice_id sun6i_ar100_rproc_ids[] = {
+ { .compatible = "allwinner,sun6i-a31-ar100" },
+ { }
+};
+
+U_BOOT_DRIVER(sun6i_ar100_rproc) = {
+ .name = "sun6i_ar100_rproc",
+ .id = UCLASS_REMOTEPROC,
+ .of_match = sun6i_ar100_rproc_ids,
+ .probe = sun6i_ar100_rproc_probe,
+ .priv_auto = sizeof(struct sun6i_ar100_rproc_priv),
+ .ops = &sun6i_ar100_rproc_ops,
+};
--
2.34.1
From 53bf73ab3356bc4c05cf4570661cf52e5a0ddc8e Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 9 Oct 2021 15:04:16 -0500
Subject: [PATCH 5/9] arm: dts: sunxi: h3: Add nodes for AR100 remoteproc
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm/dts/sun8i-h3.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm/dts/sun8i-h3.dtsi b/arch/arm/dts/sun8i-h3.dtsi
index eac2349a23..b88dcd4272 100644
--- a/arch/arm/dts/sun8i-h3.dtsi
+++ b/arch/arm/dts/sun8i-h3.dtsi
@@ -170,6 +170,14 @@
#size-cells = <1>;
ranges;
+ sram_a2: sram@40000 {
+ compatible = "mmio-sram";
+ reg = <0x00040000 0xc000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x00040000 0xc000>;
+ };
+
sram_c: sram@1d00000 {
compatible = "mmio-sram";
reg = <0x01d00000 0x80000>;
@@ -239,6 +247,12 @@
nvmem-cell-names = "calibration";
#thermal-sensor-cells = <0>;
};
+
+ remoteproc@1f01c00 {
+ compatible = "allwinner,sun6i-a31-ar100";
+ reg = <0x01f01c00 0x400>;
+ sram = <&sram_a2>;
+ };
};
thermal-zones {
--
2.34.1
From 681163212274988bb6d826232da09289c6c2b0ea Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 17 Apr 2021 13:33:54 -0500
Subject: [PATCH 6/9] sunxi: Enable support for SCP firmware on H3
Now that issues with the BROM have been sorted out, we can implement
PSCI system suspend on H3 by delegating to SCP firmware. Let's start by
including the firmware in the FIT image and starting the coprocessor if
valid firmware is loaded.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm/dts/sunxi-u-boot.dtsi | 1 +
board/sunxi/board.c | 8 ++++++++
include/configs/sun8i.h | 3 +++
3 files changed, 12 insertions(+)
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index 5d45157598..36b55c8b80 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -9,6 +9,7 @@
#if defined(CONFIG_MACH_SUN8I_H3)
#ifdef CONFIG_ARMV7_PSCI
#define RESUME_ADDR SUNXI_RESUME_BASE
+#define SCP_ADDR SUNXI_SCP_BASE
#endif
#elif defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H5)
#define BL31_ADDR 0x00044000
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index ca9c1cd9e2..289a9d93cb 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -19,6 +19,7 @@
#include <init.h>
#include <log.h>
#include <mmc.h>
+#include <remoteproc.h>
#include <axp_pmic.h>
#include <generic-phy.h>
#include <phy-sun4i-usb.h>
@@ -881,6 +882,13 @@ int board_late_init(void)
usb_ether_init();
#endif
+#ifdef CONFIG_REMOTEPROC_SUN6I_AR100
+ if (!rproc_load(0, SUNXI_SCP_BASE, SUNXI_SCP_MAX_SIZE)) {
+ puts("Starting SCP...\n");
+ rproc_start(0);
+ }
+#endif
+
return 0;
}
diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h
index 98e68e068b..506ce35707 100644
--- a/include/configs/sun8i.h
+++ b/include/configs/sun8i.h
@@ -12,6 +12,9 @@
CONFIG_ARMV7_SECURE_MAX_SIZE)
#define SUNXI_RESUME_SIZE 1024
+#define SUNXI_SCP_BASE (SUNXI_RESUME_BASE + SUNXI_RESUME_SIZE)
+#define SUNXI_SCP_MAX_SIZE (16 * 1024)
+
#include <configs/sunxi-common.h>
#define CONFIG_MACH_TYPE (0x1029)
--
2.34.1
From 56b6ac0956fe69cb30d42042d8e20c4fdca4b906 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 9 Oct 2021 22:43:26 -0500
Subject: [PATCH 7/9] arm: psci: Add definitions for PSCI v1.1
Add the new option, function IDs, and prototypes for PSCI v1.1
implementations. In the process, fix some issues with the existing
definitions:
- Fix the incorrectly-named ARM_PSCI_0_2_FN64_SYSTEM_RESET2.
- Replace the deprecated "affinity_level" naming with "power_level".
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm/cpu/armv7/Kconfig | 3 +++
arch/arm/include/asm/psci.h | 5 +++--
arch/arm/include/asm/system.h | 14 +++++++++-----
arch/arm/lib/psci-dt.c | 2 ++
4 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig
index e33e53636a..7d58d1837b 100644
--- a/arch/arm/cpu/armv7/Kconfig
+++ b/arch/arm/cpu/armv7/Kconfig
@@ -80,6 +80,9 @@ choice
help
Select the supported PSCI version.
+config ARMV7_PSCI_1_1
+ bool "PSCI V1.1"
+
config ARMV7_PSCI_1_0
bool "PSCI V1.0"
diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h
index 7343b941ef..27c2d15521 100644
--- a/arch/arm/include/asm/psci.h
+++ b/arch/arm/include/asm/psci.h
@@ -22,9 +22,9 @@
#include <linux/bitops.h>
#endif
-#define ARM_PSCI_VER_1_1 (0x00010001)
-#define ARM_PSCI_VER_1_0 (0x00010000)
#define ARM_PSCI_VER_0_2 (0x00000002)
+#define ARM_PSCI_VER_1_0 (0x00010000)
+#define ARM_PSCI_VER_1_1 (0x00010001)
/* PSCI 0.1 interface */
#define ARM_PSCI_FN_BASE 0x95c1ba5e
@@ -87,6 +87,7 @@
#define ARM_PSCI_1_0_FN64_STAT_COUNT ARM_PSCI_0_2_FN64(17)
/* PSCI 1.1 interface */
+#define ARM_PSCI_1_1_FN_SYSTEM_RESET2 ARM_PSCI_0_2_FN(18)
#define ARM_PSCI_1_1_FN64_SYSTEM_RESET2 ARM_PSCI_0_2_FN64(18)
/* 1KB stack per core */
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 87d1c77e8b..bcbb999b49 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -557,16 +557,20 @@ void mmu_page_table_flush(unsigned long start, unsigned long stop);
#ifdef CONFIG_ARMV7_PSCI
void psci_arch_cpu_entry(void);
void psci_arch_init(void);
+
u32 psci_version(void);
-s32 psci_features(u32 function_id, u32 psci_fid);
+s32 psci_cpu_suspend(u32 function_id, u32 power_state, u32 pc, u32 context_id);
s32 psci_cpu_off(void);
-s32 psci_cpu_on(u32 function_id, u32 target_cpu, u32 pc,
- u32 context_id);
-s32 psci_affinity_info(u32 function_id, u32 target_affinity,
- u32 lowest_affinity_level);
+s32 psci_cpu_on(u32 function_id, u32 target_cpu, u32 pc, u32 context_id);
+s32 psci_affinity_info(u32 function_id, u32 target_affinity, u32 power_level);
u32 psci_migrate_info_type(void);
void psci_system_off(void);
void psci_system_reset(void);
+s32 psci_features(u32 function_id, u32 psci_fid);
+s32 psci_cpu_default_suspend(u32 function_id, u32 pc, u32 context_id);
+s32 psci_node_hw_state(u32 function_id, u32 target_cpu, u32 power_level);
+s32 psci_system_suspend(u32 function_id, u32 pc, u32 context_id);
+s32 psci_system_reset2(u32 function_id, u32 reset_type, u32 cookie);
#endif
#endif /* __ASSEMBLY__ */
diff --git a/arch/arm/lib/psci-dt.c b/arch/arm/lib/psci-dt.c
index 903b335704..ea9d1c8355 100644
--- a/arch/arm/lib/psci-dt.c
+++ b/arch/arm/lib/psci-dt.c
@@ -66,6 +66,8 @@ int fdt_psci(void *fdt)
init_psci_node:
#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)
psci_ver = sec_firmware_support_psci_version();
+#elif defined(CONFIG_ARMV7_PSCI_1_1)
+ psci_ver = ARM_PSCI_VER_1_1;
#elif defined(CONFIG_ARMV7_PSCI_1_0) || defined(CONFIG_ARMV8_PSCI)
psci_ver = ARM_PSCI_VER_1_0;
#elif defined(CONFIG_ARMV7_PSCI_0_2)
--
2.34.1
From d40b63cac6dcffa2f3b199cca3775138edccbbeb Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Sat, 9 Oct 2021 23:01:05 -0500
Subject: [PATCH 8/9] sunxi: psci: Delegate PSCI to SCPI
This adds a new PSCI implementation which communicates with SCP firmware
running on the AR100 using the SCPI protocol. This allows it to support
the full set of PSCI v1.1 features, including CPU idle states, system
suspend, and multiple reset methods.
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm/cpu/armv7/Kconfig | 1 +
arch/arm/cpu/armv7/sunxi/Makefile | 4 +
arch/arm/cpu/armv7/sunxi/psci-scpi.c | 451 +++++++++++++++++++++++++++
3 files changed, 456 insertions(+)
create mode 100644 arch/arm/cpu/armv7/sunxi/psci-scpi.c
diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig
index 7d58d1837b..cbcae209dc 100644
--- a/arch/arm/cpu/armv7/Kconfig
+++ b/arch/arm/cpu/armv7/Kconfig
@@ -75,6 +75,7 @@ config ARMV7_PSCI
choice
prompt "Supported PSCI version"
depends on ARMV7_PSCI
+ default ARMV7_PSCI_1_1 if MACH_SUN8I_H3
default ARMV7_PSCI_0_1 if ARCH_SUNXI
default ARMV7_PSCI_1_0
help
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 3e975b366c..6473b9acbd 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -13,8 +13,12 @@ obj-$(CONFIG_MACH_SUN6I) += sram.o
obj-$(CONFIG_MACH_SUN8I) += sram.o
ifndef CONFIG_SPL_BUILD
+ifdef CONFIG_MACH_SUN8I_H3
+obj-$(CONFIG_ARMV7_PSCI) += psci-scpi.o
+else
obj-$(CONFIG_ARMV7_PSCI) += psci.o
endif
+endif
ifdef CONFIG_SPL_BUILD
obj-y += fel_utils.o
diff --git a/arch/arm/cpu/armv7/sunxi/psci-scpi.c b/arch/arm/cpu/armv7/sunxi/psci-scpi.c
new file mode 100644
index 0000000000..cf85292a8f
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/psci-scpi.c
@@ -0,0 +1,451 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 Chen-Yu Tsai <wens@csie.org>
+ * Copyright (C) 2018-2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#include <common.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/cpucfg.h>
+#include <asm/armv7.h>
+#include <asm/gic.h>
+#include <asm/io.h>
+#include <asm/psci.h>
+#include <asm/secure.h>
+#include <asm/system.h>
+
+#define GICD_BASE (SUNXI_GIC400_BASE + GIC_DIST_OFFSET)
+#define GICC_BASE (SUNXI_GIC400_BASE + GIC_CPU_OFFSET_A15)
+
+#define HW_ON 0
+#define HW_OFF 1
+#define HW_STANDBY 2
+
+#define MPIDR_AFFLVL0(mpidr) (mpidr & 0xf)
+#define MPIDR_AFFLVL1(mpidr) (mpidr >> 8 & 0xf)
+
+#define SCPI_SHMEM_BASE 0x0004be00
+#define SCPI_SHMEM ((struct scpi_shmem *)SCPI_SHMEM_BASE)
+
+#define SCPI_RX_CHANNEL 1
+#define SCPI_TX_CHANNEL 0
+#define SCPI_VIRTUAL_CHANNEL BIT(0)
+
+#define SCPI_MESSAGE_SIZE 0x100
+#define SCPI_PAYLOAD_SIZE (SCPI_MESSAGE_SIZE - sizeof(struct scpi_header))
+
+#define SUNXI_MSGBOX_BASE 0x01c17000
+#define REMOTE_IRQ_STAT_REG (SUNXI_MSGBOX_BASE + 0x0050)
+#define LOCAL_IRQ_STAT_REG (SUNXI_MSGBOX_BASE + 0x0070)
+#define MSG_STAT_REG(n) (SUNXI_MSGBOX_BASE + 0x0140 + 0x4 * (n))
+#define MSG_DATA_REG(n) (SUNXI_MSGBOX_BASE + 0x0180 + 0x4 * (n))
+
+#define RX_IRQ(n) BIT(0 + 2 * (n))
+#define TX_IRQ(n) BIT(1 + 2 * (n))
+
+enum {
+ CORE_POWER_LEVEL = 0,
+ CLUSTER_POWER_LEVEL = 1,
+ CSS_POWER_LEVEL = 2,
+};
+
+enum {
+ SCPI_CMD_SCP_READY = 0x01,
+ SCPI_CMD_SET_CSS_POWER_STATE = 0x03,
+ SCPI_CMD_GET_CSS_POWER_STATE = 0x04,
+ SCPI_CMD_SET_SYS_POWER_STATE = 0x05,
+};
+
+enum {
+ SCPI_E_OK = 0,
+ SCPI_E_PARAM = 1,
+ SCPI_E_ALIGN = 2,
+ SCPI_E_SIZE = 3,
+ SCPI_E_HANDLER = 4,
+ SCPI_E_ACCESS = 5,
+ SCPI_E_RANGE = 6,
+ SCPI_E_TIMEOUT = 7,
+ SCPI_E_NOMEM = 8,
+ SCPI_E_PWRSTATE = 9,
+ SCPI_E_SUPPORT = 10,
+ SCPI_E_DEVICE = 11,
+ SCPI_E_BUSY = 12,
+ SCPI_E_OS = 13,
+ SCPI_E_DATA = 14,
+ SCPI_E_STATE = 15,
+};
+
+enum {
+ SCPI_POWER_ON = 0x00,
+ SCPI_POWER_RETENTION = 0x01,
+ SCPI_POWER_OFF = 0x03,
+};
+
+enum {
+ SCPI_SYSTEM_SHUTDOWN = 0x00,
+ SCPI_SYSTEM_REBOOT = 0x01,
+ SCPI_SYSTEM_RESET = 0x02,
+};
+
+struct scpi_header {
+ u8 command;
+ u8 sender;
+ u16 size;
+ u32 status;
+};
+
+struct scpi_message {
+ struct scpi_header header;
+ u8 payload[SCPI_PAYLOAD_SIZE];
+};
+
+struct scpi_shmem {
+ struct scpi_message rx;
+ struct scpi_message tx;
+};
+
+static bool __secure_data gic_dist_init;
+
+static u32 __secure_data lock;
+
+static inline u32 __secure read_mpidr(void)
+{
+ u32 val;
+
+ asm volatile ("mrc p15, 0, %0, c0, c0, 5" : "=r" (val));
+
+ return val;
+}
+
+static void __secure scpi_begin_command(void)
+{
+ u32 mpidr = read_mpidr();
+
+ do {
+ while (readl(&lock));
+ writel(mpidr, &lock);
+ dsb();
+ } while (readl(&lock) != mpidr);
+ while (readl(REMOTE_IRQ_STAT_REG) & RX_IRQ(SCPI_TX_CHANNEL));
+}
+
+static void __secure scpi_send_command(void)
+{
+ writel(SCPI_VIRTUAL_CHANNEL, MSG_DATA_REG(SCPI_TX_CHANNEL));
+}
+
+static void __secure scpi_wait_response(void)
+{
+ while (!readl(MSG_STAT_REG(SCPI_RX_CHANNEL)));
+}
+
+static void __secure scpi_end_command(void)
+{
+ while (readl(MSG_STAT_REG(SCPI_RX_CHANNEL)))
+ readl(MSG_DATA_REG(SCPI_RX_CHANNEL));
+ writel(RX_IRQ(SCPI_RX_CHANNEL), LOCAL_IRQ_STAT_REG);
+ writel(0, &lock);
+}
+
+static void __secure scpi_set_css_power_state(u32 target_cpu, u32 core_state,
+ u32 cluster_state, u32 css_state)
+{
+ struct scpi_shmem *shmem = SCPI_SHMEM;
+
+ scpi_begin_command();
+
+ shmem->tx.header.command = SCPI_CMD_SET_CSS_POWER_STATE;
+ shmem->tx.header.size = 4;
+
+ shmem->tx.payload[0] = target_cpu >> 4 | target_cpu;
+ shmem->tx.payload[1] = cluster_state << 4 | core_state;
+ shmem->tx.payload[2] = css_state;
+ shmem->tx.payload[3] = 0;
+
+ scpi_send_command();
+ scpi_end_command();
+}
+
+static s32 __secure scpi_get_css_power_state(u32 target_cpu, u8 *core_states,
+ u8 *cluster_state)
+{
+ struct scpi_shmem *shmem = SCPI_SHMEM;
+ u32 cluster = MPIDR_AFFLVL1(target_cpu);
+ u32 offset;
+ s32 ret;
+
+ scpi_begin_command();
+
+ shmem->tx.header.command = SCPI_CMD_GET_CSS_POWER_STATE;
+ shmem->tx.header.size = 0;
+
+ scpi_send_command();
+ scpi_wait_response();
+
+ for (offset = 0; offset < shmem->rx.header.size; offset += 2) {
+ if ((shmem->rx.payload[offset] & 0xf) == cluster) {
+ *cluster_state = shmem->rx.payload[offset+0] >> 4;
+ *core_states = shmem->rx.payload[offset+1];
+
+ break;
+ }
+ }
+
+ ret = shmem->rx.header.status;
+
+ scpi_end_command();
+
+ return ret;
+}
+
+static s32 __secure scpi_set_sys_power_state(u32 sys_state)
+{
+ struct scpi_shmem *shmem = SCPI_SHMEM;
+ s32 ret;
+
+ scpi_begin_command();
+
+ shmem->tx.header.command = SCPI_CMD_SET_SYS_POWER_STATE;
+ shmem->tx.header.size = 1;
+
+ shmem->tx.payload[0] = sys_state;
+
+ scpi_send_command();
+ scpi_wait_response();
+
+ ret = shmem->rx.header.status;
+
+ scpi_end_command();
+
+ return ret;
+}
+
+void psci_enable_smp(void);
+
+static s32 __secure psci_suspend_common(u32 pc, u32 context_id, u32 core_state,
+ u32 cluster_state, u32 css_state)
+
+{
+ u32 target_cpu = read_mpidr();
+
+ if (core_state == SCPI_POWER_OFF)
+ psci_save(MPIDR_AFFLVL0(target_cpu), pc, context_id);
+ if (css_state == SCPI_POWER_OFF)
+ gic_dist_init = true;
+
+ scpi_set_css_power_state(target_cpu, core_state,
+ cluster_state, css_state);
+
+ psci_cpu_off_common();
+
+ wfi();
+
+ psci_enable_smp();
+
+ return ARM_PSCI_RET_SUCCESS;
+}
+
+u32 __secure psci_version(void)
+{
+ return ARM_PSCI_VER_1_1;
+}
+
+s32 __secure psci_cpu_suspend(u32 __always_unused function_id,
+ u32 power_state, u32 pc, u32 context_id)
+{
+ return psci_suspend_common(pc, context_id,
+ power_state >> 0 & 0xf,
+ power_state >> 4 & 0xf,
+ power_state >> 8 & 0xf);
+}
+
+s32 __secure psci_cpu_off(void)
+{
+ u32 pc = 0, context_id = 0;
+
+ return psci_suspend_common(pc, context_id, SCPI_POWER_OFF,
+ SCPI_POWER_OFF, SCPI_POWER_ON);
+}
+
+s32 __secure psci_cpu_on(u32 __always_unused function_id,
+ u32 target_cpu, u32 pc, u32 context_id)
+{
+ psci_save(MPIDR_AFFLVL0(target_cpu), pc, context_id);
+
+ scpi_set_css_power_state(target_cpu, SCPI_POWER_ON,
+ SCPI_POWER_ON, SCPI_POWER_ON);
+
+ return ARM_PSCI_RET_SUCCESS;
+}
+
+s32 __secure psci_affinity_info(u32 function_id,
+ u32 target_cpu, u32 power_level)
+{
+ if (power_level != CORE_POWER_LEVEL)
+ return ARM_PSCI_RET_INVAL;
+
+ /* This happens to have the same HW_ON/HW_OFF encoding. */
+ return psci_node_hw_state(function_id, target_cpu, power_level);
+}
+
+void __secure psci_system_off(void)
+{
+ scpi_set_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
+
+ /* Wait to be turned off. */
+ for (;;) wfi();
+}
+
+void __secure psci_system_reset(void)
+{
+ scpi_set_sys_power_state(SCPI_SYSTEM_REBOOT);
+
+ /* Wait to be turned off. */
+ for (;;) wfi();
+}
+
+s32 __secure psci_features(u32 __always_unused function_id,
+ u32 psci_fid)
+{
+ switch (psci_fid) {
+ case ARM_PSCI_0_2_FN_PSCI_VERSION:
+ case ARM_PSCI_0_2_FN_CPU_SUSPEND:
+ case ARM_PSCI_0_2_FN_CPU_OFF:
+ case ARM_PSCI_0_2_FN_CPU_ON:
+ case ARM_PSCI_0_2_FN_AFFINITY_INFO:
+ case ARM_PSCI_0_2_FN_SYSTEM_OFF:
+ case ARM_PSCI_0_2_FN_SYSTEM_RESET:
+ case ARM_PSCI_1_0_FN_PSCI_FEATURES:
+ case ARM_PSCI_1_0_FN_CPU_DEFAULT_SUSPEND:
+ case ARM_PSCI_1_0_FN_NODE_HW_STATE:
+ case ARM_PSCI_1_0_FN_SYSTEM_SUSPEND:
+ case ARM_PSCI_1_1_FN_SYSTEM_RESET2:
+ return ARM_PSCI_RET_SUCCESS;
+ default:
+ return ARM_PSCI_RET_NI;
+ }
+}
+
+s32 __secure psci_cpu_default_suspend(u32 __always_unused function_id,
+ u32 pc, u32 context_id)
+{
+ return psci_suspend_common(pc, context_id, SCPI_POWER_OFF,
+ SCPI_POWER_OFF, SCPI_POWER_RETENTION);
+}
+
+s32 __secure psci_node_hw_state(u32 __always_unused function_id,
+ u32 target_cpu, u32 power_level)
+{
+ u32 core = MPIDR_AFFLVL0(target_cpu);
+ u8 core_states, cluster_state;
+
+ if (power_level >= CSS_POWER_LEVEL)
+ return HW_ON;
+ if (scpi_get_css_power_state(target_cpu, &core_states, &cluster_state))
+ return ARM_PSCI_RET_NI;
+ if (power_level == CLUSTER_POWER_LEVEL) {
+ if (cluster_state == SCPI_POWER_ON)
+ return HW_ON;
+ if (cluster_state < SCPI_POWER_OFF)
+ return HW_STANDBY;
+ return HW_OFF;
+ }
+
+ return (core_states & BIT(core)) ? HW_ON : HW_OFF;
+}
+
+s32 __secure psci_system_suspend(u32 __always_unused function_id,
+ u32 pc, u32 context_id)
+{
+ return psci_suspend_common(pc, context_id, SCPI_POWER_OFF,
+ SCPI_POWER_OFF, SCPI_POWER_OFF);
+}
+
+s32 __secure psci_system_reset2(u32 __always_unused function_id,
+ u32 reset_type, u32 cookie)
+{
+ s32 ret;
+
+ if (reset_type)
+ return ARM_PSCI_RET_INVAL;
+
+ ret = scpi_set_sys_power_state(SCPI_SYSTEM_RESET);
+ if (ret)
+ return ARM_PSCI_RET_INVAL;
+
+ /* Wait to be turned off. */
+ for (;;) wfi();
+}
+
+/*
+ * R40 is different from other single cluster SoCs. The secondary core
+ * entry address register is in the SRAM controller address range.
+ */
+#define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0 (0xbc)
+
+#ifdef CONFIG_MACH_SUN8I_R40
+/* secondary core entry address is programmed differently on R40 */
+static void __secure sunxi_set_entry_address(void *entry)
+{
+ writel((u32)entry,
+ SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
+}
+#else
+static void __secure sunxi_set_entry_address(void *entry)
+{
+ struct sunxi_cpucfg_reg *cpucfg =
+ (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+ writel((u32)entry, &cpucfg->priv0);
+
+#ifdef CONFIG_MACH_SUN8I_H3
+ /* Redirect CPU 0 to the secure monitor via the resume shim. */
+ writel(0x16aaefe8, &cpucfg->super_standy_flag);
+ writel(0xaa16efe8, &cpucfg->super_standy_flag);
+ writel(SUNXI_RESUME_BASE, &cpucfg->priv1);
+#endif
+}
+#endif
+
+void __secure psci_arch_init(void)
+{
+ static bool __secure_data one_time_init = true;
+
+ if (one_time_init) {
+ /* Set secondary core power-on PC. */
+ sunxi_set_entry_address(psci_cpu_entry);
+
+ /* Wait for the SCP firmware to boot. */
+ scpi_begin_command();
+ scpi_wait_response();
+ scpi_end_command();
+
+ one_time_init = false;
+ }
+
+ /*
+ * Copied from arch/arm/cpu/armv7/virt-v7.c
+ * See also gic_resume() in arch/arm/mach-imx/mx7/psci-mx7.c
+ */
+ if (gic_dist_init) {
+ u32 i, itlinesnr;
+
+ /* enable the GIC distributor */
+ writel(readl(GICD_BASE + GICD_CTLR) | 0x03, GICD_BASE + GICD_CTLR);
+
+ /* TYPER[4:0] contains an encoded number of available interrupts */
+ itlinesnr = readl(GICD_BASE + GICD_TYPER) & 0x1f;
+
+ /* set all bits in the GIC group registers to one to allow access
+ * from non-secure state. The first 32 interrupts are private per
+ * CPU and will be set later when enabling the GIC for each core
+ */
+ for (i = 1; i <= itlinesnr; i++)
+ writel((unsigned)-1, GICD_BASE + GICD_IGROUPRn + 4 * i);
+
+ gic_dist_init = false;
+ }
+
+ /* Be cool with non-secure. */
+ writel(0xff, GICC_BASE + GICC_PMR);
+}
--
2.34.1
From adc8ea72a2d4c0600339a7afed8b1f98f3c07844 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
Date: Wed, 8 Jun 2022 07:55:54 -0500
Subject: [PATCH 9/9] sunxi: Enable SCP/SCPI on A33 as well
Signed-off-by: Samuel Holland <samuel@sholland.org>
---
arch/arm/cpu/armv7/Kconfig | 2 +-
arch/arm/cpu/armv7/sunxi/Makefile | 2 +-
arch/arm/cpu/armv7/sunxi/psci-scpi.c | 4 ++++
arch/arm/dts/sun8i-a23-a33.dtsi | 14 ++++++++++++++
arch/arm/dts/sunxi-u-boot.dtsi | 4 ++--
5 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig
index cbcae209dc..6a515ed6d5 100644
--- a/arch/arm/cpu/armv7/Kconfig
+++ b/arch/arm/cpu/armv7/Kconfig
@@ -75,7 +75,7 @@ config ARMV7_PSCI
choice
prompt "Supported PSCI version"
depends on ARMV7_PSCI
- default ARMV7_PSCI_1_1 if MACH_SUN8I_H3
+ default ARMV7_PSCI_1_1 if MACH_SUN8I_A33 || MACH_SUN8I_H3
default ARMV7_PSCI_0_1 if ARCH_SUNXI
default ARMV7_PSCI_1_0
help
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 6473b9acbd..033042666f 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_MACH_SUN6I) += sram.o
obj-$(CONFIG_MACH_SUN8I) += sram.o
ifndef CONFIG_SPL_BUILD
-ifdef CONFIG_MACH_SUN8I_H3
+ifneq ($(CONFIG_MACH_SUN8I_A33)$(CONFIG_MACH_SUN8I_H3),)
obj-$(CONFIG_ARMV7_PSCI) += psci-scpi.o
else
obj-$(CONFIG_ARMV7_PSCI) += psci.o
diff --git a/arch/arm/cpu/armv7/sunxi/psci-scpi.c b/arch/arm/cpu/armv7/sunxi/psci-scpi.c
index cf85292a8f..717c37c124 100644
--- a/arch/arm/cpu/armv7/sunxi/psci-scpi.c
+++ b/arch/arm/cpu/armv7/sunxi/psci-scpi.c
@@ -24,7 +24,11 @@
#define MPIDR_AFFLVL0(mpidr) (mpidr & 0xf)
#define MPIDR_AFFLVL1(mpidr) (mpidr >> 8 & 0xf)
+#if defined(CONFIG_MACH_SUN8I_H3)
#define SCPI_SHMEM_BASE 0x0004be00
+#else
+#define SCPI_SHMEM_BASE 0x00053e00
+#endif
#define SCPI_SHMEM ((struct scpi_shmem *)SCPI_SHMEM_BASE)
#define SCPI_RX_CHANNEL 1
diff --git a/arch/arm/dts/sun8i-a23-a33.dtsi b/arch/arm/dts/sun8i-a23-a33.dtsi
index 84c6d9379a..826bcddcdf 100644
--- a/arch/arm/dts/sun8i-a23-a33.dtsi
+++ b/arch/arm/dts/sun8i-a23-a33.dtsi
@@ -138,6 +138,14 @@
#size-cells = <1>;
ranges;
+ sram_a2: sram@40000 {
+ compatible = "mmio-sram";
+ reg = <0x00040000 0x14000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x00040000 0x14000>;
+ };
+
sram_c: sram@1d00000 {
compatible = "mmio-sram";
reg = <0x01d00000 0x80000>;
@@ -847,5 +855,11 @@
#address-cells = <1>;
#size-cells = <0>;
};
+
+ remoteproc@1f01c00 {
+ compatible = "allwinner,sun6i-a31-ar100";
+ reg = <0x01f01c00 0x400>;
+ sram = <&sram_a2>;
+ };
};
};
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index 36b55c8b80..a152b1f787 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -6,11 +6,11 @@
#define ARCH "arm"
#endif
+#if defined(CONFIG_ARMV7_PSCI) && (defined(CONFIG_MACH_SUN8I_A33) || defined(CONFIG_MACH_SUN8I_H3))
#if defined(CONFIG_MACH_SUN8I_H3)
-#ifdef CONFIG_ARMV7_PSCI
#define RESUME_ADDR SUNXI_RESUME_BASE
-#define SCP_ADDR SUNXI_SCP_BASE
#endif
+#define SCP_ADDR SUNXI_SCP_BASE
#elif defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUN50I_H5)
#define BL31_ADDR 0x00044000
#define SCP_ADDR 0x00050000
--
2.34.1