[U-Boot] [PATCH 0/4] sunxi: PSCI support for H3

Hi everyone,
This series enables PSCI support for the H3. Like other Allwinner SoCs, the implementation only supports PSCI 0.1, specifically only secondary CPU boot/hotplug.
Patch 1 supports the SMTA (previously called TZPC) TrustZone hardware on H3. This controls non-secure access to some important hardware blocks.
Patch 2 supports the security switch in H3's CCU. This is H3 only. No other SoCs have this feature.
Patch 3 supports H3 using sun6i PSCI implementation. H3 uses the same power sequence as sun6i, including the power clamps. This is shown in Allwinner's SDK, and confirmed / tested by Siarhei.
Patch 4 enables PSCI support for the H3 in Kconfig.
I've only tested booting HYP/SMP on my Orange Pi PC. Hotplugging was not tested, but should work.
Regards ChenYu
Chen-Yu Tsai (4): sunxi: Support Secure Memory Touch Arbiter (SMTA) in sun8i H3 sunxi: Support H3 CCU security switches sunxi: Support PSCI ops on Allwinner H3 sunxi: Enable booting non-secure and virtualization for H3
arch/arm/cpu/armv7/sunxi/Makefile | 1 + arch/arm/cpu/armv7/sunxi/clock.c | 5 +++++ arch/arm/cpu/armv7/sunxi/clock_sun6i.c | 13 +++++++++++++ arch/arm/cpu/armv7/sunxi/psci_sun6i.S | 4 ++-- arch/arm/cpu/armv7/sunxi/tzpc.c | 11 ++++++++++- arch/arm/include/asm/arch-sunxi/clock.h | 1 + arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 7 +++++++ arch/arm/include/asm/arch-sunxi/tzpc.h | 13 ++++++++++++- board/sunxi/Kconfig | 3 +++ 9 files changed, 54 insertions(+), 4 deletions(-)

Secure Memory Touch Arbiter is the same thing as the TrustZone Protection Controller found on A31/A31s.
Access to many peripherals on the H3 can be controlled by the SMTA, and the settings default to secure access only.
This patch supports the new settings, and sets them to allow non-secure access.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- arch/arm/cpu/armv7/sunxi/Makefile | 1 + arch/arm/cpu/armv7/sunxi/tzpc.c | 11 ++++++++++- arch/arm/include/asm/arch-sunxi/tzpc.h | 13 ++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index dfb0a3e..7a6a3cc 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_SUN8I) += clock_sun6i.o endif obj-$(CONFIG_MACH_SUN9I) += clock_sun9i.o obj-$(CONFIG_MACH_SUN6I) += tzpc.o +obj-$(CONFIG_MACH_SUN8I) += tzpc.o
obj-$(CONFIG_AXP152_POWER) += pmic_bus.o obj-$(CONFIG_AXP209_POWER) += pmic_bus.o diff --git a/arch/arm/cpu/armv7/sunxi/tzpc.c b/arch/arm/cpu/armv7/sunxi/tzpc.c index 5c9c69b..6c8a0fd 100644 --- a/arch/arm/cpu/armv7/sunxi/tzpc.c +++ b/arch/arm/cpu/armv7/sunxi/tzpc.c @@ -13,6 +13,15 @@ void tzpc_init(void) { struct sunxi_tzpc *tzpc = (struct sunxi_tzpc *)SUNXI_TZPC_BASE;
+#ifdef CONFIG_MACH_SUN6I /* Enable non-secure access to the RTC */ - writel(SUNXI_TZPC_DECPORT0_RTC, &tzpc->decport0_set); + writel(SUN6I_TZPC_DECPORT0_RTC, &tzpc->decport0_set); +#endif + +#ifdef CONFIG_MACH_SUN8I_H3 + /* Enable non-secure access to all peripherals */ + writel(SUN8I_H3_TZPC_DECPORT0_ALL, &tzpc->decport0_set); + writel(SUN8I_H3_TZPC_DECPORT1_ALL, &tzpc->decport1_set); + writel(SUN8I_H3_TZPC_DECPORT2_ALL, &tzpc->decport2_set); +#endif } diff --git a/arch/arm/include/asm/arch-sunxi/tzpc.h b/arch/arm/include/asm/arch-sunxi/tzpc.h index ba4d43b..95c55cd 100644 --- a/arch/arm/include/asm/arch-sunxi/tzpc.h +++ b/arch/arm/include/asm/arch-sunxi/tzpc.h @@ -13,10 +13,21 @@ struct sunxi_tzpc { u32 decport0_status; /* 0x04 Status of decode protection port 0 */ u32 decport0_set; /* 0x08 Set decode protection port 0 */ u32 decport0_clear; /* 0x0c Clear decode protection port 0 */ + /* For A80 and later SoCs */ + u32 decport1_status; /* 0x10 Status of decode protection port 1 */ + u32 decport1_set; /* 0x14 Set decode protection port 1 */ + u32 decport1_clear; /* 0x18 Clear decode protection port 1 */ + u32 decport2_status; /* 0x1c Status of decode protection port 2 */ + u32 decport2_set; /* 0x20 Set decode protection port 2 */ + u32 decport2_clear; /* 0x24 Clear decode protection port 2 */ }; #endif
-#define SUNXI_TZPC_DECPORT0_RTC (1 << 1) +#define SUN6I_TZPC_DECPORT0_RTC (1 << 1) + +#define SUN8I_H3_TZPC_DECPORT0_ALL 0xbe +#define SUN8I_H3_TZPC_DECPORT1_ALL 0xff +#define SUN8I_H3_TZPC_DECPORT2_ALL 0x7f
void tzpc_init(void);

Hi,
On 01/06/2016 08:13 AM, Chen-Yu Tsai wrote:
Secure Memory Touch Arbiter is the same thing as the TrustZone Protection Controller found on A31/A31s.
Access to many peripherals on the H3 can be controlled by the SMTA, and the settings default to secure access only.
This patch supports the new settings, and sets them to allow non-secure access.
Except that you've forgotten to update arch/arm/cpu/armv7/sunxi/board.c to actually call tzpc_init on the H3, I've added this chunk to fix this:
@@ -127,8 +127,8 @@ void s_init(void) "orr r0, r0, #1 << 6\n" "mcr p15, 0, r0, c1, c0, 1\n"); #endif -#if defined CONFIG_MACH_SUN6I - /* Enable non-secure access to the RTC */ +#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I_H3 + /* Enable non-secure access to some peripherals */ tzpc_init(); #endif
Regards,
Hans
Signed-off-by: Chen-Yu Tsai wens@csie.org
arch/arm/cpu/armv7/sunxi/Makefile | 1 + arch/arm/cpu/armv7/sunxi/tzpc.c | 11 ++++++++++- arch/arm/include/asm/arch-sunxi/tzpc.h | 13 ++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index dfb0a3e..7a6a3cc 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MACH_SUN8I) += clock_sun6i.o endif obj-$(CONFIG_MACH_SUN9I) += clock_sun9i.o obj-$(CONFIG_MACH_SUN6I) += tzpc.o +obj-$(CONFIG_MACH_SUN8I) += tzpc.o
obj-$(CONFIG_AXP152_POWER) += pmic_bus.o obj-$(CONFIG_AXP209_POWER) += pmic_bus.o diff --git a/arch/arm/cpu/armv7/sunxi/tzpc.c b/arch/arm/cpu/armv7/sunxi/tzpc.c index 5c9c69b..6c8a0fd 100644 --- a/arch/arm/cpu/armv7/sunxi/tzpc.c +++ b/arch/arm/cpu/armv7/sunxi/tzpc.c @@ -13,6 +13,15 @@ void tzpc_init(void) { struct sunxi_tzpc *tzpc = (struct sunxi_tzpc *)SUNXI_TZPC_BASE;
+#ifdef CONFIG_MACH_SUN6I /* Enable non-secure access to the RTC */
- writel(SUNXI_TZPC_DECPORT0_RTC, &tzpc->decport0_set);
- writel(SUN6I_TZPC_DECPORT0_RTC, &tzpc->decport0_set);
+#endif
+#ifdef CONFIG_MACH_SUN8I_H3
- /* Enable non-secure access to all peripherals */
- writel(SUN8I_H3_TZPC_DECPORT0_ALL, &tzpc->decport0_set);
- writel(SUN8I_H3_TZPC_DECPORT1_ALL, &tzpc->decport1_set);
- writel(SUN8I_H3_TZPC_DECPORT2_ALL, &tzpc->decport2_set);
+#endif } diff --git a/arch/arm/include/asm/arch-sunxi/tzpc.h b/arch/arm/include/asm/arch-sunxi/tzpc.h index ba4d43b..95c55cd 100644 --- a/arch/arm/include/asm/arch-sunxi/tzpc.h +++ b/arch/arm/include/asm/arch-sunxi/tzpc.h @@ -13,10 +13,21 @@ struct sunxi_tzpc { u32 decport0_status; /* 0x04 Status of decode protection port 0 */ u32 decport0_set; /* 0x08 Set decode protection port 0 */ u32 decport0_clear; /* 0x0c Clear decode protection port 0 */
- /* For A80 and later SoCs */
- u32 decport1_status; /* 0x10 Status of decode protection port 1 */
- u32 decport1_set; /* 0x14 Set decode protection port 1 */
- u32 decport1_clear; /* 0x18 Clear decode protection port 1 */
- u32 decport2_status; /* 0x1c Status of decode protection port 2 */
- u32 decport2_set; /* 0x20 Set decode protection port 2 */
- u32 decport2_clear; /* 0x24 Clear decode protection port 2 */ }; #endif
-#define SUNXI_TZPC_DECPORT0_RTC (1 << 1) +#define SUN6I_TZPC_DECPORT0_RTC (1 << 1)
+#define SUN8I_H3_TZPC_DECPORT0_ALL 0xbe +#define SUN8I_H3_TZPC_DECPORT1_ALL 0xff +#define SUN8I_H3_TZPC_DECPORT2_ALL 0x7f
void tzpc_init(void);

H3's CCU includes some switches which disable non-secure access to some of the more critical clock controls, such as MBUS, PLLs, and main platform busses.
Configure them to enable non-secure access.
For now the only SoC that has this feature is the H3. For other platforms just use a default (weak) empty function so things do not break.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- arch/arm/cpu/armv7/sunxi/clock.c | 5 +++++ arch/arm/cpu/armv7/sunxi/clock_sun6i.c | 13 +++++++++++++ arch/arm/include/asm/arch-sunxi/clock.h | 1 + arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 7 +++++++ 4 files changed, 26 insertions(+)
diff --git a/arch/arm/cpu/armv7/sunxi/clock.c b/arch/arm/cpu/armv7/sunxi/clock.c index 47fb70f..5cc5d25 100644 --- a/arch/arm/cpu/armv7/sunxi/clock.c +++ b/arch/arm/cpu/armv7/sunxi/clock.c @@ -14,12 +14,17 @@ #include <asm/arch/gpio.h> #include <asm/arch/sys_proto.h>
+__weak void clock_init_sec(void) +{ +} + int clock_init(void) { #ifdef CONFIG_SPL_BUILD clock_init_safe(); #endif clock_init_uart(); + clock_init_sec();
return 0; } diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c index 4501884..d0085e8 100644 --- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c +++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c @@ -45,6 +45,19 @@ void clock_init_safe(void) } #endif
+void clock_init_sec(void) +{ + struct sunxi_ccm_reg * const ccm = + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + +#ifdef CONFIG_MACH_SUN8I_H3 + setbits_le32(&ccm->ccu_sec_switch, + CCM_SEC_SWITCH_MBUS_NONSEC | + CCM_SEC_SWITCH_BUS_NONSEC | + CCM_SEC_SWITCH_PLL_NONSEC); +#endif +} + void clock_init_uart(void) { #if CONFIG_CONS_INDEX < 5 diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h index 8ca58ae..6c0573f 100644 --- a/arch/arm/include/asm/arch-sunxi/clock.h +++ b/arch/arm/include/asm/arch-sunxi/clock.h @@ -30,6 +30,7 @@ int clock_init(void); int clock_twi_onoff(int port, int state); void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz); void clock_init_safe(void); +void clock_init_sec(void); void clock_init_uart(void); #endif
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h index 5c76275..554d858 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h @@ -137,6 +137,8 @@ struct sunxi_ccm_reg { u32 apb1_reset_cfg; /* 0x2d0 APB1 Reset config */ u32 reserved24; u32 apb2_reset_cfg; /* 0x2d8 APB2 Reset config */ + u32 reserved25[5]; + u32 ccu_sec_switch; /* 0x2f0 CCU Security Switch, H3 only */ };
/* apb2 bit field */ @@ -375,6 +377,11 @@ struct sunxi_ccm_reg { #define CCM_DE_CTRL_PLL10 (5 << 24) #define CCM_DE_CTRL_GATE (1 << 31)
+/* CCU security switch, H3 only */ +#define CCM_SEC_SWITCH_MBUS_NONSEC (1 << 2) +#define CCM_SEC_SWITCH_BUS_NONSEC (1 << 1) +#define CCM_SEC_SWITCH_PLL_NONSEC (1 << 0) + #ifndef __ASSEMBLY__ void clock_set_pll1(unsigned int hz); void clock_set_pll3(unsigned int hz);

H3 has the same power sequencing procedure as the A31/A31s, which includes the power clamps.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- arch/arm/cpu/armv7/sunxi/psci_sun6i.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/armv7/sunxi/psci_sun6i.S b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S index 4ff46e4..90b5bfd 100644 --- a/arch/arm/cpu/armv7/sunxi/psci_sun6i.S +++ b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S @@ -106,7 +106,7 @@ psci_fiq_enter: str r10, [r8, #0x100] timer_wait r10, ONE_MS
-#ifdef CONFIG_MACH_SUN6I +#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I_H3) @ Activate power clamp lsl r12, r9, #2 @ x4 add r12, r12, r8 @@ -170,7 +170,7 @@ psci_cpu_on: movw r0, #(SUNXI_PRCM_BASE & 0xffff) movt r0, #(SUNXI_PRCM_BASE >> 16)
-#ifdef CONFIG_MACH_SUN6I +#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I_H3) @ Release power clamp lsl r5, r1, #2 @ 1 register per CPU add r5, r5, r0 @ PRCM

Now that we support PSCI and various security switches, we can let U-boot boot Linux into non-secure and HYP mode.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- board/sunxi/Kconfig | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index 9d67847..28e6bb4 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -71,8 +71,11 @@ config MACH_SUN8I_A33 config MACH_SUN8I_H3 bool "sun8i (Allwinner H3)" select CPU_V7 + select CPU_V7_HAS_NONSEC + select CPU_V7_HAS_VIRT select SUNXI_GEN_SUN6I select SUPPORT_SPL + select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
config MACH_SUN8I_A83T bool "sun8i (Allwinner A83T)"

Hi Chen-Yu,
On 06/01/16 08:13, Chen-Yu Tsai wrote:
Hi everyone,
This series enables PSCI support for the H3. Like other Allwinner SoCs, the implementation only supports PSCI 0.1, specifically only secondary CPU boot/hotplug.
Thanks, the patches look good to me. I've also tested them on the Orange Pi Plus, works as expected.
Jens
Patch 1 supports the SMTA (previously called TZPC) TrustZone hardware on H3. This controls non-secure access to some important hardware blocks.
Patch 2 supports the security switch in H3's CCU. This is H3 only. No other SoCs have this feature.
Patch 3 supports H3 using sun6i PSCI implementation. H3 uses the same power sequence as sun6i, including the power clamps. This is shown in Allwinner's SDK, and confirmed / tested by Siarhei.
Patch 4 enables PSCI support for the H3 in Kconfig.
I've only tested booting HYP/SMP on my Orange Pi PC. Hotplugging was not tested, but should work.
Regards ChenYu
Chen-Yu Tsai (4): sunxi: Support Secure Memory Touch Arbiter (SMTA) in sun8i H3 sunxi: Support H3 CCU security switches sunxi: Support PSCI ops on Allwinner H3 sunxi: Enable booting non-secure and virtualization for H3
arch/arm/cpu/armv7/sunxi/Makefile | 1 + arch/arm/cpu/armv7/sunxi/clock.c | 5 +++++ arch/arm/cpu/armv7/sunxi/clock_sun6i.c | 13 +++++++++++++ arch/arm/cpu/armv7/sunxi/psci_sun6i.S | 4 ++-- arch/arm/cpu/armv7/sunxi/tzpc.c | 11 ++++++++++- arch/arm/include/asm/arch-sunxi/clock.h | 1 + arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 7 +++++++ arch/arm/include/asm/arch-sunxi/tzpc.h | 13 ++++++++++++- board/sunxi/Kconfig | 3 +++ 9 files changed, 54 insertions(+), 4 deletions(-)

Hi,
On 01/06/2016 08:13 AM, Chen-Yu Tsai wrote:
Hi everyone,
This series enables PSCI support for the H3. Like other Allwinner SoCs, the implementation only supports PSCI 0.1, specifically only secondary CPU boot/hotplug.
Patch 1 supports the SMTA (previously called TZPC) TrustZone hardware on H3. This controls non-secure access to some important hardware blocks.
Patch 2 supports the security switch in H3's CCU. This is H3 only. No other SoCs have this feature.
Patch 3 supports H3 using sun6i PSCI implementation. H3 uses the same power sequence as sun6i, including the power clamps. This is shown in Allwinner's SDK, and confirmed / tested by Siarhei.
Patch 4 enables PSCI support for the H3 in Kconfig.
I've only tested booting HYP/SMP on my Orange Pi PC. Hotplugging was not tested, but should work.
Many thanks for this patch-set, I've applied this to my tree, and it will be part of the pull-req I plan to send out this weekend.
Regards,
Hans
participants (3)
-
Chen-Yu Tsai
-
Hans de Goede
-
Jens Kuske