* [PATCH v3 1/4] sunxi: psci: clean away preprocessor macros
2023-09-30 18:34 [PATCH v3 0/4] Allwinner R528/T113s PSCI Sam Edwards
@ 2023-09-30 18:34 ` Sam Edwards
2023-09-30 18:34 ` [PATCH v3 2/4] sunxi: psci: refactor register access to separate functions Sam Edwards
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Sam Edwards @ 2023-09-30 18:34 UTC (permalink / raw)
To: u-boot, Andre Przywara, Jagan Teki
Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maksim Kiselev,
Sam Edwards
This patch restructures psci.c to get away from the "many different
function definitions switched by #ifdef" paradigm to the preferred style
of having a single function definition with `if (IS_ENABLED(...))` to
make the optimizer include only the appropriate function bodies instead.
There are no functional changes here.
Signed-off-by: Sam Edwards <CFSworks@gmail.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
---
arch/arm/cpu/armv7/sunxi/psci.c | 103 +++++++++++++-------------------
1 file changed, 43 insertions(+), 60 deletions(-)
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
index e1d3638b5c..69fa3f3c2e 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -76,11 +76,8 @@ static void __secure __mdelay(u32 ms)
isb();
}
-static void __secure clamp_release(u32 __maybe_unused *clamp)
+static void __secure clamp_release(u32 *clamp)
{
-#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
- defined(CONFIG_MACH_SUN8I_H3) || \
- defined(CONFIG_MACH_SUN8I_R40)
u32 tmp = 0x1ff;
do {
tmp >>= 1;
@@ -88,83 +85,69 @@ static void __secure clamp_release(u32 __maybe_unused *clamp)
} while (tmp);
__mdelay(10);
-#endif
}
-static void __secure clamp_set(u32 __maybe_unused *clamp)
+static void __secure clamp_set(u32 *clamp)
{
-#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
- defined(CONFIG_MACH_SUN8I_H3) || \
- defined(CONFIG_MACH_SUN8I_R40)
writel(0xff, clamp);
-#endif
}
-static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
- int cpu)
+static void __secure sunxi_set_entry_address(void *entry)
{
- if (on) {
- /* Release power clamp */
- clamp_release(clamp);
-
- /* Clear power gating */
- clrbits_le32(pwroff, BIT(cpu));
+ /* secondary core entry address is programmed differently on R40 */
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
+ writel((u32)entry,
+ SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
} else {
- /* Set power gating */
- setbits_le32(pwroff, BIT(cpu));
+ struct sunxi_cpucfg_reg *cpucfg =
+ (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
- /* Activate power clamp */
- clamp_set(clamp);
+ writel((u32)entry, &cpucfg->priv0);
}
}
-#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)
+static void __secure sunxi_cpu_set_power(int cpu, bool on)
{
+ u32 *clamp = NULL;
+ u32 *pwroff;
struct sunxi_cpucfg_reg *cpucfg =
(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
- writel((u32)entry, &cpucfg->priv0);
-}
-#endif
+ /* sun7i (A20) is different from other single cluster SoCs */
+ if (IS_ENABLED(CONFIG_MACH_SUN7I)) {
+ clamp = &cpucfg->cpu1_pwr_clamp;
+ pwroff = &cpucfg->cpu1_pwroff;
+ cpu = 0;
+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
+ clamp = (void *)cpucfg + SUN8I_R40_PWR_CLAMP(cpu);
+ pwroff = (void *)cpucfg + SUN8I_R40_PWROFF;
+ } else {
+ struct sunxi_prcm_reg *prcm =
+ (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
-#ifdef CONFIG_MACH_SUN7I
-/* sun7i (A20) is different from other single cluster SoCs */
-static void __secure sunxi_cpu_set_power(int __always_unused cpu, bool on)
-{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+ if (IS_ENABLED(CONFIG_MACH_SUN6I) ||
+ IS_ENABLED(CONFIG_MACH_SUN8I_H3))
+ clamp = &prcm->cpu_pwr_clamp[cpu];
- sunxi_power_switch(&cpucfg->cpu1_pwr_clamp, &cpucfg->cpu1_pwroff,
- on, 0);
-}
-#elif defined CONFIG_MACH_SUN8I_R40
-static void __secure sunxi_cpu_set_power(int cpu, bool on)
-{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+ pwroff = &prcm->cpu_pwroff;
+ }
- sunxi_power_switch((void *)cpucfg + SUN8I_R40_PWR_CLAMP(cpu),
- (void *)cpucfg + SUN8I_R40_PWROFF,
- on, cpu);
-}
-#else /* ! CONFIG_MACH_SUN7I && ! CONFIG_MACH_SUN8I_R40 */
-static void __secure sunxi_cpu_set_power(int cpu, bool on)
-{
- struct sunxi_prcm_reg *prcm =
- (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+ if (on) {
+ /* Release power clamp */
+ if (clamp)
+ clamp_release(clamp);
- sunxi_power_switch(&prcm->cpu_pwr_clamp[cpu], &prcm->cpu_pwroff,
- on, cpu);
+ /* Clear power gating */
+ clrbits_le32(pwroff, BIT(cpu));
+ } else {
+ /* Set power gating */
+ setbits_le32(pwroff, BIT(cpu));
+
+ /* Activate power clamp */
+ if (clamp)
+ clamp_set(clamp);
+ }
}
-#endif /* CONFIG_MACH_SUN7I */
void __secure sunxi_cpu_power_off(u32 cpuid)
{
--
2.41.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v3 2/4] sunxi: psci: refactor register access to separate functions
2023-09-30 18:34 [PATCH v3 0/4] Allwinner R528/T113s PSCI Sam Edwards
2023-09-30 18:34 ` [PATCH v3 1/4] sunxi: psci: clean away preprocessor macros Sam Edwards
@ 2023-09-30 18:34 ` Sam Edwards
2023-09-30 18:34 ` [PATCH v3 3/4] sunxi: psci: stop modeling register layout with C structs Sam Edwards
2023-09-30 18:34 ` [PATCH v3 4/4] sunxi: psci: implement PSCI on R528 Sam Edwards
3 siblings, 0 replies; 5+ messages in thread
From: Sam Edwards @ 2023-09-30 18:34 UTC (permalink / raw)
To: u-boot, Andre Przywara, Jagan Teki
Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maksim Kiselev,
Sam Edwards
This is to prepare for R528, which does not have the typical
"CPUCFG" block; it has a "CPUX" block which provides these
same functions but is organized differently.
Moving the hardware-access bits to their own functions separates the
logic from the hardware so we can reuse the same logic.
Signed-off-by: Sam Edwards <CFSworks@gmail.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
---
arch/arm/cpu/armv7/sunxi/psci.c | 66 +++++++++++++++++++++++----------
1 file changed, 47 insertions(+), 19 deletions(-)
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
index 69fa3f3c2e..27ca9c39e1 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -92,7 +92,7 @@ static void __secure clamp_set(u32 *clamp)
writel(0xff, clamp);
}
-static void __secure sunxi_set_entry_address(void *entry)
+static void __secure sunxi_cpu_set_entry(int __always_unused cpu, void *entry)
{
/* secondary core entry address is programmed differently on R40 */
if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
@@ -149,30 +149,60 @@ static void __secure sunxi_cpu_set_power(int cpu, bool on)
}
}
-void __secure sunxi_cpu_power_off(u32 cpuid)
+static void __secure sunxi_cpu_set_reset(int cpu, bool reset)
{
struct sunxi_cpucfg_reg *cpucfg =
(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+ writel(reset ? 0b00 : 0b11, &cpucfg->cpu[cpu].rst);
+}
+
+static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
+{
+ struct sunxi_cpucfg_reg *cpucfg =
+ (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+ if (lock)
+ clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ else
+ setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+}
+
+static bool __secure sunxi_cpu_poll_wfi(int cpu)
+{
+ struct sunxi_cpucfg_reg *cpucfg =
+ (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+ return !!(readl(&cpucfg->cpu[cpu].status) & BIT(2));
+}
+
+static void __secure sunxi_cpu_invalidate_cache(int cpu)
+{
+ struct sunxi_cpucfg_reg *cpucfg =
+ (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+ clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
+}
+
+static void __secure sunxi_cpu_power_off(u32 cpuid)
+{
u32 cpu = cpuid & 0x3;
/* Wait for the core to enter WFI */
- while (1) {
- if (readl(&cpucfg->cpu[cpu].status) & BIT(2))
- break;
+ while (!sunxi_cpu_poll_wfi(cpu))
__mdelay(1);
- }
/* Assert reset on target CPU */
- writel(0, &cpucfg->cpu[cpu].rst);
+ sunxi_cpu_set_reset(cpu, true);
/* Lock CPU (Disable external debug access) */
- clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ sunxi_cpu_set_locking(cpu, true);
/* Power down CPU */
sunxi_cpu_set_power(cpuid, false);
- /* Unlock CPU (Disable external debug access) */
- setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ /* Unlock CPU (Reenable external debug access) */
+ sunxi_cpu_set_locking(cpu, false);
}
static u32 __secure cp15_read_scr(void)
@@ -229,33 +259,31 @@ out:
int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc,
u32 context_id)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
u32 cpu = (mpidr & 0x3);
/* store target PC and context id */
psci_save(cpu, pc, context_id);
/* Set secondary core power on PC */
- sunxi_set_entry_address(&psci_cpu_entry);
+ sunxi_cpu_set_entry(cpu, &psci_cpu_entry);
/* Assert reset on target CPU */
- writel(0, &cpucfg->cpu[cpu].rst);
+ sunxi_cpu_set_reset(cpu, true);
/* Invalidate L1 cache */
- clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
+ sunxi_cpu_invalidate_cache(cpu);
/* Lock CPU (Disable external debug access) */
- clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ sunxi_cpu_set_locking(cpu, true);
/* 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);
+ sunxi_cpu_set_reset(cpu, false);
- /* Unlock CPU (Disable external debug access) */
- setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ /* Unlock CPU (Reenable external debug access) */
+ sunxi_cpu_set_locking(cpu, false);
return ARM_PSCI_RET_SUCCESS;
}
--
2.41.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v3 3/4] sunxi: psci: stop modeling register layout with C structs
2023-09-30 18:34 [PATCH v3 0/4] Allwinner R528/T113s PSCI Sam Edwards
2023-09-30 18:34 ` [PATCH v3 1/4] sunxi: psci: clean away preprocessor macros Sam Edwards
2023-09-30 18:34 ` [PATCH v3 2/4] sunxi: psci: refactor register access to separate functions Sam Edwards
@ 2023-09-30 18:34 ` Sam Edwards
2023-09-30 18:34 ` [PATCH v3 4/4] sunxi: psci: implement PSCI on R528 Sam Edwards
3 siblings, 0 replies; 5+ messages in thread
From: Sam Edwards @ 2023-09-30 18:34 UTC (permalink / raw)
To: u-boot, Andre Przywara, Jagan Teki
Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maksim Kiselev,
Sam Edwards
Since the sunxi support nowadays generally prefers #defined register
offsets instead of modeling register layouts using C structs, now is a
good time to do this for PSCI as well. This patch moves away from using
the structs `sunxi_cpucfg_reg` and `sunxi_prcm_reg` in psci.c.
The former struct and its associated header file existed only to support
PSCI code, so also delete them altogether.
Signed-off-by: Sam Edwards <CFSworks@gmail.com>
---
arch/arm/cpu/armv7/sunxi/psci.c | 57 ++++++++------------
arch/arm/include/asm/arch-sunxi/cpucfg.h | 67 ------------------------
2 files changed, 23 insertions(+), 101 deletions(-)
delete mode 100644 arch/arm/include/asm/arch-sunxi/cpucfg.h
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
index 27ca9c39e1..207aa6bc4b 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -11,8 +11,6 @@
#include <asm/cache.h>
#include <asm/arch/cpu.h>
-#include <asm/arch/cpucfg.h>
-#include <asm/arch/prcm.h>
#include <asm/armv7.h>
#include <asm/gic.h>
#include <asm/io.h>
@@ -27,6 +25,17 @@
#define GICD_BASE (SUNXI_GIC400_BASE + GIC_DIST_OFFSET)
#define GICC_BASE (SUNXI_GIC400_BASE + GIC_CPU_OFFSET_A15)
+/*
+ * Offsets into the CPUCFG block applicable to most SUNXIs.
+ */
+#define SUNXI_CPU_RST(cpu) (0x40 + (cpu) * 0x40 + 0x0)
+#define SUNXI_CPU_STATUS(cpu) (0x40 + (cpu) * 0x40 + 0x8)
+#define SUNXI_GEN_CTRL (0x184)
+#define SUNXI_PRIV0 (0x1a4)
+#define SUN7I_CPU1_PWR_CLAMP (0x1b0)
+#define SUN7I_CPU1_PWROFF (0x1b4)
+#define SUNXI_DBG_CTRL1 (0x1e4)
+
/*
* R40 is different from other single cluster SoCs.
*
@@ -99,10 +108,7 @@ static void __secure sunxi_cpu_set_entry(int __always_unused cpu, void *entry)
writel((u32)entry,
SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
} else {
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-
- writel((u32)entry, &cpucfg->priv0);
+ writel((u32)entry, SUNXI_CPUCFG_BASE + SUNXI_PRIV0);
}
}
@@ -110,26 +116,21 @@ static void __secure sunxi_cpu_set_power(int cpu, bool on)
{
u32 *clamp = NULL;
u32 *pwroff;
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
/* sun7i (A20) is different from other single cluster SoCs */
if (IS_ENABLED(CONFIG_MACH_SUN7I)) {
- clamp = &cpucfg->cpu1_pwr_clamp;
- pwroff = &cpucfg->cpu1_pwroff;
+ clamp = (void *)SUNXI_CPUCFG_BASE + SUN7I_CPU1_PWR_CLAMP;
+ pwroff = (void *)SUNXI_CPUCFG_BASE + SUN7I_CPU1_PWROFF;
cpu = 0;
} else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
- clamp = (void *)cpucfg + SUN8I_R40_PWR_CLAMP(cpu);
- pwroff = (void *)cpucfg + SUN8I_R40_PWROFF;
+ clamp = (void *)SUNXI_CPUCFG_BASE + SUN8I_R40_PWR_CLAMP(cpu);
+ pwroff = (void *)SUNXI_CPUCFG_BASE + SUN8I_R40_PWROFF;
} else {
- struct sunxi_prcm_reg *prcm =
- (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
-
if (IS_ENABLED(CONFIG_MACH_SUN6I) ||
IS_ENABLED(CONFIG_MACH_SUN8I_H3))
- clamp = &prcm->cpu_pwr_clamp[cpu];
+ clamp = (void *)SUNXI_PRCM_BASE + 0x140 + cpu * 0x4;
- pwroff = &prcm->cpu_pwroff;
+ pwroff = (void *)SUNXI_PRCM_BASE + 0x100;
}
if (on) {
@@ -151,37 +152,25 @@ static void __secure sunxi_cpu_set_power(int cpu, bool on)
static void __secure sunxi_cpu_set_reset(int cpu, bool reset)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-
- writel(reset ? 0b00 : 0b11, &cpucfg->cpu[cpu].rst);
+ writel(reset ? 0b00 : 0b11, SUNXI_CPUCFG_BASE + SUNXI_CPU_RST(cpu));
}
static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-
if (lock)
- clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUNXI_DBG_CTRL1, BIT(cpu));
else
- setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ setbits_le32(SUNXI_CPUCFG_BASE + SUNXI_DBG_CTRL1, BIT(cpu));
}
static bool __secure sunxi_cpu_poll_wfi(int cpu)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-
- return !!(readl(&cpucfg->cpu[cpu].status) & BIT(2));
+ return !!(readl(SUNXI_CPUCFG_BASE + SUNXI_CPU_STATUS(cpu)) & BIT(2));
}
static void __secure sunxi_cpu_invalidate_cache(int cpu)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
-
- clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUNXI_GEN_CTRL, BIT(cpu));
}
static void __secure sunxi_cpu_power_off(u32 cpuid)
diff --git a/arch/arm/include/asm/arch-sunxi/cpucfg.h b/arch/arm/include/asm/arch-sunxi/cpucfg.h
deleted file mode 100644
index 4aaebe0a97..0000000000
--- a/arch/arm/include/asm/arch-sunxi/cpucfg.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Sunxi A31 CPUCFG register definition.
- *
- * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com
- */
-
-#ifndef _SUNXI_CPUCFG_H
-#define _SUNXI_CPUCFG_H
-
-#include <linux/compiler.h>
-#include <linux/types.h>
-
-#ifndef __ASSEMBLY__
-
-struct __packed sunxi_cpucfg_cpu {
- u32 rst; /* base + 0x0 */
- u32 ctrl; /* base + 0x4 */
- u32 status; /* base + 0x8 */
- u8 res[0x34]; /* base + 0xc */
-};
-
-struct __packed sunxi_cpucfg_reg {
- u8 res0[0x40]; /* 0x000 */
- struct sunxi_cpucfg_cpu cpu[4]; /* 0x040 */
- u8 res1[0x44]; /* 0x140 */
- u32 gen_ctrl; /* 0x184 */
- u32 l2_status; /* 0x188 */
- u8 res2[0x4]; /* 0x18c */
- u32 event_in; /* 0x190 */
- u8 res3[0xc]; /* 0x194 */
- u32 super_standy_flag; /* 0x1a0 */
- u32 priv0; /* 0x1a4 */
- u32 priv1; /* 0x1a8 */
- u8 res4[0x4]; /* 0x1ac */
- u32 cpu1_pwr_clamp; /* 0x1b0 sun7i only */
- u32 cpu1_pwroff; /* 0x1b4 sun7i only */
- u8 res5[0x2c]; /* 0x1b8 */
- u32 dbg_ctrl1; /* 0x1e4 */
- u8 res6[0x18]; /* 0x1e8 */
- u32 idle_cnt0_low; /* 0x200 */
- u32 idle_cnt0_high; /* 0x204 */
- u32 idle_cnt0_ctrl; /* 0x208 */
- u8 res8[0x4]; /* 0x20c */
- u32 idle_cnt1_low; /* 0x210 */
- u32 idle_cnt1_high; /* 0x214 */
- u32 idle_cnt1_ctrl; /* 0x218 */
- u8 res9[0x4]; /* 0x21c */
- u32 idle_cnt2_low; /* 0x220 */
- u32 idle_cnt2_high; /* 0x224 */
- u32 idle_cnt2_ctrl; /* 0x228 */
- u8 res10[0x4]; /* 0x22c */
- u32 idle_cnt3_low; /* 0x230 */
- u32 idle_cnt3_high; /* 0x234 */
- u32 idle_cnt3_ctrl; /* 0x238 */
- u8 res11[0x4]; /* 0x23c */
- u32 idle_cnt4_low; /* 0x240 */
- u32 idle_cnt4_high; /* 0x244 */
- u32 idle_cnt4_ctrl; /* 0x248 */
- u8 res12[0x34]; /* 0x24c */
- u32 cnt64_ctrl; /* 0x280 */
- u32 cnt64_low; /* 0x284 */
- u32 cnt64_high; /* 0x288 */
-};
-
-#endif /* __ASSEMBLY__ */
-#endif /* _SUNXI_CPUCFG_H */
--
2.41.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v3 4/4] sunxi: psci: implement PSCI on R528
2023-09-30 18:34 [PATCH v3 0/4] Allwinner R528/T113s PSCI Sam Edwards
` (2 preceding siblings ...)
2023-09-30 18:34 ` [PATCH v3 3/4] sunxi: psci: stop modeling register layout with C structs Sam Edwards
@ 2023-09-30 18:34 ` Sam Edwards
3 siblings, 0 replies; 5+ messages in thread
From: Sam Edwards @ 2023-09-30 18:34 UTC (permalink / raw)
To: u-boot, Andre Przywara, Jagan Teki
Cc: Samuel Holland, Jernej Skrabec, Icenowy Zheng, Maksim Kiselev,
Sam Edwards, Kevin Amadiva
This patch adds the necessary code to make nonsec booting and PSCI
secondary core management functional on the R528/T113.
Signed-off-by: Sam Edwards <CFSworks@gmail.com>
Tested-by: Maksim Kiselev <bigunclemax@gmail.com>
Tested-by: Kevin Amadiva <kevin.amadiva@mec.at>
---
arch/arm/cpu/armv7/sunxi/psci.c | 47 ++++++++++++++++++++++++++++++++-
arch/arm/mach-sunxi/Kconfig | 4 +++
include/configs/sunxi-common.h | 8 ++++++
3 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
index 207aa6bc4b..b03a865483 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -47,6 +47,19 @@
#define SUN8I_R40_PWR_CLAMP(cpu) (0x120 + (cpu) * 0x4)
#define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0 (0xbc)
+/*
+ * R528 is also different, as it has both cores powered up (but held in reset
+ * state) after the SoC is reset. Like the R40, it uses a "soft" entry point
+ * address register, but unlike the R40, it uses a newer "CPUX" block to manage
+ * CPU state, rather than the older CPUCFG system.
+ */
+#define SUN8I_R528_SOFT_ENTRY (0x1c8)
+#define SUN8I_R528_C0_RST_CTRL (0x0000)
+#define SUN8I_R528_C0_CTRL_REG0 (0x0010)
+#define SUN8I_R528_C0_CPU_STATUS (0x0080)
+
+#define SUN8I_R528_C0_STATUS_STANDBYWFI (16)
+
static void __secure cp15_write_cntp_tval(u32 tval)
{
asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval));
@@ -103,10 +116,12 @@ static void __secure clamp_set(u32 *clamp)
static void __secure sunxi_cpu_set_entry(int __always_unused cpu, void *entry)
{
- /* secondary core entry address is programmed differently on R40 */
if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
writel((u32)entry,
SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ writel((u32)entry,
+ SUNXI_R_CPUCFG_BASE + SUN8I_R528_SOFT_ENTRY);
} else {
writel((u32)entry, SUNXI_CPUCFG_BASE + SUNXI_PRIV0);
}
@@ -125,6 +140,9 @@ static void __secure sunxi_cpu_set_power(int cpu, bool on)
} else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
clamp = (void *)SUNXI_CPUCFG_BASE + SUN8I_R40_PWR_CLAMP(cpu);
pwroff = (void *)SUNXI_CPUCFG_BASE + SUN8I_R40_PWROFF;
+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ /* R528 leaves both cores powered up, manages them via reset */
+ return;
} else {
if (IS_ENABLED(CONFIG_MACH_SUN6I) ||
IS_ENABLED(CONFIG_MACH_SUN8I_H3))
@@ -152,11 +170,27 @@ static void __secure sunxi_cpu_set_power(int cpu, bool on)
static void __secure sunxi_cpu_set_reset(int cpu, bool reset)
{
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ if (reset)
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_RST_CTRL,
+ BIT(cpu));
+ else
+ setbits_le32(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_RST_CTRL,
+ BIT(cpu));
+
+ return;
+ }
+
writel(reset ? 0b00 : 0b11, SUNXI_CPUCFG_BASE + SUNXI_CPU_RST(cpu));
}
static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
{
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ /* Not required on R528 */
+ return;
+ }
+
if (lock)
clrbits_le32(SUNXI_CPUCFG_BASE + SUNXI_DBG_CTRL1, BIT(cpu));
else
@@ -165,11 +199,22 @@ static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
static bool __secure sunxi_cpu_poll_wfi(int cpu)
{
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ return !!(readl(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_CPU_STATUS) &
+ BIT(SUN8I_R528_C0_STATUS_STANDBYWFI + cpu));
+ }
+
return !!(readl(SUNXI_CPUCFG_BASE + SUNXI_CPU_STATUS(cpu)) & BIT(2));
}
static void __secure sunxi_cpu_invalidate_cache(int cpu)
{
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_CTRL_REG0,
+ BIT(cpu));
+ return;
+ }
+
clrbits_le32(SUNXI_CPUCFG_BASE + SUNXI_GEN_CTRL, BIT(cpu));
}
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index e891e291f1..23b5b27b97 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -355,6 +355,10 @@ config MACH_SUN8I_R40
config MACH_SUN8I_R528
bool "sun8i (Allwinner R528)"
select CPU_V7A
+ select CPU_V7_HAS_NONSEC
+ select CPU_V7_HAS_VIRT
+ select ARCH_SUPPORT_PSCI
+ select SPL_ARMV7_SET_CORTEX_SMPEN
select SUNXI_GEN_NCAT2
select SUNXI_NEW_PINCTRL
select MMC_SUNXI_HAS_NEW_MODE
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index b8ca77d031..67eb0d25db 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -33,6 +33,14 @@
/* CPU */
+/*
+ * Newer ARM SoCs have moved the GIC, but have not updated their ARM cores to
+ * reflect the correct address in CBAR/PERIPHBASE.
+ */
+#if defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
+#define CFG_ARM_GIC_BASE_ADDRESS 0x03020000
+#endif
+
/*
* The DRAM Base differs between some models. We cannot use macros for the
* CONFIG_FOO defines which contain the DRAM base address since they end
--
2.41.0
^ permalink raw reply related [flat|nested] 5+ messages in thread