diff mbox series

[3/3] sunxi: psci: implement PSCI on R528

Message ID 20230812003055.74527-4-CFSworks@gmail.com
State Superseded
Delegated to: Andre Przywara
Headers show
Series Allwinner R528/T113s PSCI | expand

Commit Message

Sam Edwards Aug. 12, 2023, 12:30 a.m. UTC
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>
---
 arch/arm/cpu/armv7/sunxi/psci.c | 47 ++++++++++++++++++++++++++++++++-
 arch/arm/mach-sunxi/Kconfig     |  2 ++
 include/configs/sunxi-common.h  |  8 ++++++
 3 files changed, 56 insertions(+), 1 deletion(-)

Comments

Andre Przywara Aug. 14, 2023, 2:16 p.m. UTC | #1
On Fri, 11 Aug 2023 18:30:55 -0600
Sam Edwards <cfsworks@gmail.com> wrote:

Hi Sam,

> This patch adds the necessary code to make nonsec booting and PSCI
> secondary core management functional on the R528/T113.

Unfortunately this patch breaks the build on older 32-bit SoCs, as
SUNXI_CPUX_BASE is not defined there. That's a typical problem of the
"C-if" approach, but typically there is a clean, albeit not trivial,
solution:

It seems like SUNXI_CPUX_BASE and SUNXI_CPUCFG_BASE are mutually
exclusive, and I actually carry a "#define SUNXI_CPUCFG_BASE 0" hack in my
patches already.
So I wonder if we should unify those two into SUNXI_CPUCFG_BASE, with the
following rework:
 
> Signed-off-by: Sam Edwards <CFSworks@gmail.com>
> Tested-by: Maksim Kiselev <bigunclemax@gmail.com>
> ---
>  arch/arm/cpu/armv7/sunxi/psci.c | 47 ++++++++++++++++++++++++++++++++-
>  arch/arm/mach-sunxi/Kconfig     |  2 ++
>  include/configs/sunxi-common.h  |  8 ++++++
>  3 files changed, 56 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
> index 94120e7526..f3c1c459c2 100644
> --- a/arch/arm/cpu/armv7/sunxi/psci.c
> +++ b/arch/arm/cpu/armv7/sunxi/psci.c
> @@ -38,6 +38,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));
> @@ -116,10 +129,13 @@ static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
>  
>  static void __secure sunxi_cpu_set_entry(int __always_unused cpu, void *entry)
>  {
> -	/* secondary core entry address is programmed differently on R40 */
> +	/* secondary core entry address is programmed differently on R40/528 */
>  	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 {
>  		struct sunxi_cpucfg_reg *cpucfg =
>  			(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
> @@ -139,6 +155,8 @@ static void __secure sunxi_cpu_set_power(int cpu, bool on)
>  	} else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
>  		sunxi_power_switch(NULL, (void *)cpucfg + SUN8I_R40_PWROFF,
>  				   on, cpu);
> +	} else if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
> +		/* R528 leaves both cores powered up, manages them via reset */
>  	} else {
>  #if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2)
>  		struct sunxi_prcm_reg *prcm =
> @@ -159,6 +177,17 @@ static void __secure sunxi_cpu_set_reset(int cpu, bool reset)
>  	struct sunxi_cpucfg_reg *cpucfg =
>  		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;

Can you check what it would take to get rid of this struct altogether, and
replace accesses with "SUNXI_CPUCFG_BASE + REG_OFFSET", similiar to what
you do for the R528?
I was never a friend of ab-using C structs to model hardware register
layouts, so it seems like a good excuse to get rid of that here ;-)

Then we can define SUNXI_CPUCFG_BASE everywhere, and don't need SUNXI_CPUX_BASE.

Or do I miss something here?

Cheers,
Andre

P.S.: You can test-build for all SoCs with buildman:
$ tools/buildman/buildman -j 4 sunxi
(you might need some setup in ~/.buildman to announce your cross-compilers)
Or you just build one board per SoC, for instance "Bananapi_defconfig" for
the A20.

>  
> +	if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
> +		if (reset) {
> +			clrbits_le32(SUNXI_CPUX_BASE + SUN8I_R528_C0_RST_CTRL,
> +				     BIT(cpu));
> +		} else {
> +			setbits_le32(SUNXI_CPUX_BASE + SUN8I_R528_C0_RST_CTRL,
> +				     BIT(cpu));
> +		}
> +		return;
> +	}
> +
>  	writel(reset ? 0b00 : 0b11, &cpucfg->cpu[cpu].rst);
>  }
>  
> @@ -167,6 +196,11 @@ static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
>  	struct sunxi_cpucfg_reg *cpucfg =
>  		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
>  
> +	if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
> +		/* Not required on R528 */
> +		return;
> +	}
> +
>  	if (lock)
>  		clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
>  	else
> @@ -178,6 +212,11 @@ static bool __secure sunxi_cpu_poll_wfi(int cpu)
>  	struct sunxi_cpucfg_reg *cpucfg =
>  		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
>  
> +	if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
> +		return !!(readl(SUNXI_CPUX_BASE + SUN8I_R528_C0_CPU_STATUS) &
> +			  BIT(SUN8I_R528_C0_STATUS_STANDBYWFI + cpu));
> +	}
> +
>  	return !!(readl(&cpucfg->cpu[cpu].status) & BIT(2));
>  }
>  
> @@ -186,6 +225,12 @@ static void __secure sunxi_cpu_invalidate_cache(int cpu)
>  	struct sunxi_cpucfg_reg *cpucfg =
>  		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
>  
> +	if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
> +		clrbits_le32(SUNXI_CPUX_BASE + SUN8I_R528_C0_CTRL_REG0,
> +			     BIT(cpu));
> +		return;
> +	}
> +
>  	clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
>  }
>  
> diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
> index 0a3454a51a..d46fd8c0bc 100644
> --- a/arch/arm/mach-sunxi/Kconfig
> +++ b/arch/arm/mach-sunxi/Kconfig
> @@ -355,6 +355,8 @@ config MACH_SUN8I_R40
>  config MACH_SUN8I_R528
>  	bool "sun8i (Allwinner R528)"
>  	select CPU_V7A
> +	select CPU_V7_HAS_NONSEC
> +	select ARCH_SUPPORT_PSCI
>  	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
Sam Edwards Aug. 15, 2023, 7:17 p.m. UTC | #2
On 8/14/23 08:16, Andre Przywara wrote:
> Hi Sam,
> 
>> This patch adds the necessary code to make nonsec booting and PSCI
>> secondary core management functional on the R528/T113.
> 
> Unfortunately this patch breaks the build on older 32-bit SoCs, as
> SUNXI_CPUX_BASE is not defined there. That's a typical problem of the
> "C-if" approach, but typically there is a clean, albeit not trivial,
> solution:
> 
> It seems like SUNXI_CPUX_BASE and SUNXI_CPUCFG_BASE are mutually
> exclusive, and I actually carry a "#define SUNXI_CPUCFG_BASE 0" hack in my
> patches already.
> So I wonder if we should unify those two into SUNXI_CPUCFG_BASE, with the
> following rework:

The SUNXI_CPUX_BASE -> SUNXI_CPUCFG_BASE rename worked excellently. 
We're having the same problem with SUNXI_R_CPUCFG_BASE as well, though. 
How do you want to handle that?

Thanks,
Sam
Andre Przywara Aug. 15, 2023, 10:59 p.m. UTC | #3
On Tue, 15 Aug 2023 13:17:33 -0600
Sam Edwards <cfsworks@gmail.com> wrote:

Hi Sam,

> On 8/14/23 08:16, Andre Przywara wrote:
> > Hi Sam,
> >   
> >> This patch adds the necessary code to make nonsec booting and PSCI
> >> secondary core management functional on the R528/T113.  
> > 
> > Unfortunately this patch breaks the build on older 32-bit SoCs, as
> > SUNXI_CPUX_BASE is not defined there. That's a typical problem of the
> > "C-if" approach, but typically there is a clean, albeit not trivial,
> > solution:
> > 
> > It seems like SUNXI_CPUX_BASE and SUNXI_CPUCFG_BASE are mutually
> > exclusive, and I actually carry a "#define SUNXI_CPUCFG_BASE 0" hack in my
> > patches already.
> > So I wonder if we should unify those two into SUNXI_CPUCFG_BASE, with the
> > following rework:  
> 
> The SUNXI_CPUX_BASE -> SUNXI_CPUCFG_BASE rename worked excellently. 
> We're having the same problem with SUNXI_R_CPUCFG_BASE as well, though. 
> How do you want to handle that?

So that's a bit more nasty indeed. I don't even know if R_CPUCFG really
makes sense here, as the _R_ term typically refers to the management
processor, which the D1/R528 don't have. Or at least the always-on power
domain, but then again this hardly relates to the secondary entry
point. I think the name was just used because the address matches the
one used in the H6. Anyway, I got the impression that Allwinner just
uses registers wherever they find them, and that they don't care too
much about logical grouping or compatibility.

So taking a step back, I wonder if we should actually just define a
CONFIG_SUNXI_CPU_SOFT_ENTRY (or so) *Kconfig* symbol, which holds that
address, and let the per-SoC definition be solved in Kconfig instead.
Because SUNXI_R_CPUCFG_BASE and also SUNXI_RTC_BASE seem to be just
used as the base address for that purpose, with some magic offset
added, across all of U-Boot (ARMv8 FEL and v7 PSCI).

So can you try to work on that base? I will take care of
armv8/fel_utils.S, which uses some post-increment assembly trick to
keep the code small, which wouldn't work anymore. But I have an idea
how to solve this.

Cheers,
Andre
Sam Edwards Aug. 16, 2023, 1:48 a.m. UTC | #4
On 8/15/23 15:59, Andre Przywara wrote:
> Hi Sam,

Hi Andre,

> So that's a bit more nasty indeed. I don't even know if R_CPUCFG really
> makes sense here, as the _R_ term typically refers to the management
> processor, which the D1/R528 don't have. Or at least the always-on power
> domain, but then again this hardly relates to the secondary entry
> point. I think the name was just used because the address matches the
> one used in the H6.

Oh, no. That was my doing (and my reasoning) by suggesting that for 
inclusion in your series. Yours is good reasoning to be rid of it.

> So taking a step back, I wonder if we should actually just define a
> CONFIG_SUNXI_CPU_SOFT_ENTRY (or so) *Kconfig* symbol, which holds that
> address, and let the per-SoC definition be solved in Kconfig instead.
> Because SUNXI_R_CPUCFG_BASE and also SUNXI_RTC_BASE seem to be just
> used as the base address for that purpose, with some magic offset
> added, across all of U-Boot (ARMv8 FEL and v7 PSCI).

Mmh, since this is a block of soft registers for managing several 
functions of both cores, I think I'd rather point to the base of the 
block and still use an offset to get to the specific soft register. 
Allwinner may keep this layout for a 4-core chip in the near future or 
U-Boot may want to add code that sets the CPU0 hotplug flag, for example.

I'm not unwilling to do the Kconfig route, but just out of curiosity, 
what would your fallback plan be?

> So can you try to work on that base? I will take care of
> armv8/fel_utils.S, which uses some post-increment assembly trick to
> keep the code small, which wouldn't work anymore. But I have an idea
> how to solve this.

Before that, I think now might be a good time for me to send in the v2 
that I have so far; I doubt the final patch of my v2 series will pass 
review, but I'd like to keep us synced up (and clear away any patches in 
that series that do pass review off from my mental desktop).

> Cheers,
> Andre

Likewise,
Sam
Andre Przywara Aug. 18, 2023, 2:27 p.m. UTC | #5
On Tue, 15 Aug 2023 18:48:49 -0700
Sam Edwards <cfsworks@gmail.com> wrote:

Hi Sam,

> On 8/15/23 15:59, Andre Przywara wrote:
> > Hi Sam,  
> 
> Hi Andre,
> 
> > So that's a bit more nasty indeed. I don't even know if R_CPUCFG really
> > makes sense here, as the _R_ term typically refers to the management
> > processor, which the D1/R528 don't have. Or at least the always-on power
> > domain, but then again this hardly relates to the secondary entry
> > point. I think the name was just used because the address matches the
> > one used in the H6.  
> 
> Oh, no. That was my doing (and my reasoning) by suggesting that for 
> inclusion in your series. Yours is good reasoning to be rid of it.
> 
> > So taking a step back, I wonder if we should actually just define a
> > CONFIG_SUNXI_CPU_SOFT_ENTRY (or so) *Kconfig* symbol, which holds that
> > address, and let the per-SoC definition be solved in Kconfig instead.
> > Because SUNXI_R_CPUCFG_BASE and also SUNXI_RTC_BASE seem to be just
> > used as the base address for that purpose, with some magic offset
> > added, across all of U-Boot (ARMv8 FEL and v7 PSCI).  
> 
> Mmh, since this is a block of soft registers for managing several 
> functions of both cores, I think I'd rather point to the base of the 
> block and still use an offset to get to the specific soft register. 
> Allwinner may keep this layout for a 4-core chip in the near future or 
> U-Boot may want to add code that sets the CPU0 hotplug flag, for example.

That's a neat idea, but I gave up hoping that there is some real pattern,
especially about the memory map. In the past (up to A64/H5) that was
pretty stable, but changed wildly multiple times already afterwards.
So I don't know about the future, and we can always fix that should the
need arise.
What I do see though now is the following:
R40: SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0
R528: SUNXI_R_CPUCFG_BASE + SUN8I_R528_SOFT_ENTRY
rest: SUNXI_CPUCFG_BASE + SUNXI_PRIV0
so three totally different base addresses plus different offsets. That
comes close to random for me.
And that continues if you look into the ARMv8 fel_utils.S:
==================
#ifdef CONFIG_MACH_SUN50I_H616
        ldr     w2, =(SUNXI_R_CPUCFG_BASE + 0x1c0)
        str     w0, [x2], #0x4
#elif CONFIG_MACH_SUN50I_H6
        ldr     w2, =(SUNXI_RTC_BASE + 0x1b8)   // BOOT_CPU_HP_FLAG_REG
        str     w0, [x2], #0x4
#else
        ldr     w2, =(SUNXI_CPUCFG_BASE + 0x1a4) // offset for CPU hotplug base
	str     w0, [x2, #0x8]
==================
Again different entry points for each new SoC.
So instead of trying to derive some pattern from where there is none, I'd
rather do: config SUNXI_CPU_HOTPLUG_ADDRESS
	hex
	default 0x01c000bc if MACH_SUN8I_R40
	....
	default 0x01c25da4
and then use that symbol in both places (v7 PSCI + v8 FEL).
As mentioned, I can fix the pieces that break when naively doing so in the
FEL code. That has also the rewarding property of allowing to remove both
SUNXI_R_CPUCFG_BASE and SUNXI_RTC_BASE from the code base completely.

What do you think?

Cheers,
Andre


> I'm not unwilling to do the Kconfig route, but just out of curiosity, 
> what would your fallback plan be?
> 
> > So can you try to work on that base? I will take care of
> > armv8/fel_utils.S, which uses some post-increment assembly trick to
> > keep the code small, which wouldn't work anymore. But I have an idea
> > how to solve this.  
> 
> Before that, I think now might be a good time for me to send in the v2 
> that I have so far; I doubt the final patch of my v2 series will pass 
> review, but I'd like to keep us synced up (and clear away any patches in 
> that series that do pass review off from my mental desktop).
> 
> > Cheers,
> > Andre  
> 
> Likewise,
> Sam
Sam Edwards Aug. 18, 2023, 10:22 p.m. UTC | #6
On 8/18/23 07:27, Andre Przywara wrote:

Hi Andre,

> So instead of trying to derive some pattern from where there is none, I'd
> rather do: config SUNXI_CPU_HOTPLUG_ADDRESS
> 	hex
> 	default 0x01c000bc if MACH_SUN8I_R40

But the hotplug flag register is at 0x01c000b8 for R40?

> 	....
> 	default 0x01c25da4
> and then use that symbol in both places (v7 PSCI + v8 FEL).
> As mentioned, I can fix the pieces that break when naively doing so in the
> FEL code. That has also the rewarding property of allowing to remove both
> SUNXI_R_CPUCFG_BASE and SUNXI_RTC_BASE from the code base completely.

I might hold on to SUNXI_RTC_BASE for a bit, since the SPL may need it 
for the various reset-to-FEL mechanisms. I still want a nice way of 
getting mainline U-Boot to do this in the near term.

> What do you think?

I don't think this really solves your underlying grievance, since 
various sunxis need distinct offsets to jump from the hotplug address 
register to the secondary CPU soft entry point:

CONFIG_SUNXI_CPU_HOTPLUG_ADDRESS + 4 // for R40
CONFIG_SUNXI_CPU_HOTPLUG_ADDRESS + 8 // for R528

...at which point we're back to the "Kconfig symbol is really pointing 
to a sort of control block" idea.

We could take advantage of the fact that ARMv7 psci.c and ARMv8 
fel_utils.S are never both built and call it something horrible like 
"SUNXI_CPU_HOTPLUG_OR_SOFT_ENTRY_ADDR" but then it wouldn't be clear 
from a glance *which* it is. We could go with *two* (three, if we need 
R528's CPU0 entry for a reset-to-FEL mechanism) Kconfig symbols, but 
that's a lot for configuration symbols that are really only needed in 
pretty much one place each.

> 
> Cheers,
> Andre

Likewise,
Sam
diff mbox series

Patch

diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
index 94120e7526..f3c1c459c2 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -38,6 +38,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));
@@ -116,10 +129,13 @@  static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
 
 static void __secure sunxi_cpu_set_entry(int __always_unused cpu, void *entry)
 {
-	/* secondary core entry address is programmed differently on R40 */
+	/* secondary core entry address is programmed differently on R40/528 */
 	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 {
 		struct sunxi_cpucfg_reg *cpucfg =
 			(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
@@ -139,6 +155,8 @@  static void __secure sunxi_cpu_set_power(int cpu, bool on)
 	} else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
 		sunxi_power_switch(NULL, (void *)cpucfg + SUN8I_R40_PWROFF,
 				   on, cpu);
+	} else if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+		/* R528 leaves both cores powered up, manages them via reset */
 	} else {
 #if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2)
 		struct sunxi_prcm_reg *prcm =
@@ -159,6 +177,17 @@  static void __secure sunxi_cpu_set_reset(int cpu, bool reset)
 	struct sunxi_cpucfg_reg *cpucfg =
 		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
 
+	if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+		if (reset) {
+			clrbits_le32(SUNXI_CPUX_BASE + SUN8I_R528_C0_RST_CTRL,
+				     BIT(cpu));
+		} else {
+			setbits_le32(SUNXI_CPUX_BASE + SUN8I_R528_C0_RST_CTRL,
+				     BIT(cpu));
+		}
+		return;
+	}
+
 	writel(reset ? 0b00 : 0b11, &cpucfg->cpu[cpu].rst);
 }
 
@@ -167,6 +196,11 @@  static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
 	struct sunxi_cpucfg_reg *cpucfg =
 		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
 
+	if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+		/* Not required on R528 */
+		return;
+	}
+
 	if (lock)
 		clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
 	else
@@ -178,6 +212,11 @@  static bool __secure sunxi_cpu_poll_wfi(int cpu)
 	struct sunxi_cpucfg_reg *cpucfg =
 		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
 
+	if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+		return !!(readl(SUNXI_CPUX_BASE + SUN8I_R528_C0_CPU_STATUS) &
+			  BIT(SUN8I_R528_C0_STATUS_STANDBYWFI + cpu));
+	}
+
 	return !!(readl(&cpucfg->cpu[cpu].status) & BIT(2));
 }
 
@@ -186,6 +225,12 @@  static void __secure sunxi_cpu_invalidate_cache(int cpu)
 	struct sunxi_cpucfg_reg *cpucfg =
 		(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
 
+	if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+		clrbits_le32(SUNXI_CPUX_BASE + SUN8I_R528_C0_CTRL_REG0,
+			     BIT(cpu));
+		return;
+	}
+
 	clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
 }
 
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 0a3454a51a..d46fd8c0bc 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -355,6 +355,8 @@  config MACH_SUN8I_R40
 config MACH_SUN8I_R528
 	bool "sun8i (Allwinner R528)"
 	select CPU_V7A
+	select CPU_V7_HAS_NONSEC
+	select ARCH_SUPPORT_PSCI
 	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