[U-Boot] [PATCH 00/10] sunxi: Add basic PSCI support to enable SMP on the A80's first cluster

Hi everyone,
This series adds basic PSCI support for the A80 to enable SMP on the first cluster. This at least allows people to use more than one core. The term "basic" is used because the series does not add support for multi-cluster cache and power management.
The PSCI code is based on existing code for all the single cluster SoCs, and the kernel patches for MCPM SMP I did some time ago.
Unfortunately only SMP works at this time. The last patch does not actually work. While the system is indeed booted non-secure, tested by trying to write to secure SRAM and the results not sticking, reads from the GIC CPU interface shows that it's still returning the secure copy of registers, and since we use a secure monitor FIQ to do core power down, the FIQ gets passed to the kernel. The patch is included so people with in-depth ARM knowledge could probably help work out what is wrong.
Regards ChenYu
Chen-Yu Tsai (10): ARM: PSCI: Set ARMV7_PSCI_NR_CPUS default to 8 for sun9i/A80 sunxi: Add CCI-400 and CPUCFG registers base address for sun9i/A80 sunxi: Add base address of secure SRAM B for sun9i/A80 sunxi: Use secure SRAM B for secure RAM for sun9i/A80 sunxi: Add PRCM register definition for sun9i/A80 sunxi: Add CPUCFG register definitions for sun9i/A80 sunxi: Add support for TZPC on sun9i/A80 sunxi: Add basic PSCI implementation for A80 sunxi: Enable PSCI on sun9i/A80 sunxi: Add PSCI core power off support for A80's first cluster
arch/arm/cpu/armv7/Kconfig | 1 + arch/arm/cpu/armv7/sunxi/Makefile | 5 + arch/arm/cpu/armv7/sunxi/psci-mcpm.c | 322 +++++++++++++++++++++++++ arch/arm/cpu/armv7/sunxi/tzpc.c | 6 + arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 5 + arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h | 51 ++++ arch/arm/include/asm/arch-sunxi/prcm_sun9i.h | 55 +++++ arch/arm/include/asm/arch-sunxi/tzpc.h | 4 + arch/arm/mach-sunxi/board.c | 3 +- board/sunxi/Kconfig | 4 + include/configs/sun9i.h | 4 + 11 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/sunxi/psci-mcpm.c create mode 100644 arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun9i.h

The A80 is a big.LITTLE SoC with 4x Cortex-A7 in cluster 0 and 4x Cortex-A15 in cluster 1.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- arch/arm/cpu/armv7/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig index b9c4f4e79b9b..e37f1f328a34 100644 --- a/arch/arm/cpu/armv7/Kconfig +++ b/arch/arm/cpu/armv7/Kconfig @@ -44,6 +44,7 @@ config ARMV7_PSCI config ARMV7_PSCI_NR_CPUS int "Maximum supported CPUs for PSCI" depends on ARMV7_NONSEC + default 8 if MACH_SUN9I default 4 help The maximum number of CPUs supported in the PSCI firmware.

Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
The A80 is a big.LITTLE SoC with 4x Cortex-A7 in cluster 0 and 4x Cortex-A15 in cluster 1.
Signed-off-by: Chen-Yu Tsai wens@csie.org
LGTM:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Regards,
Hans
arch/arm/cpu/armv7/Kconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig index b9c4f4e79b9b..e37f1f328a34 100644 --- a/arch/arm/cpu/armv7/Kconfig +++ b/arch/arm/cpu/armv7/Kconfig @@ -44,6 +44,7 @@ config ARMV7_PSCI config ARMV7_PSCI_NR_CPUS int "Maximum supported CPUs for PSCI" depends on ARMV7_NONSEC
- default 8 if MACH_SUN9I default 4 help The maximum number of CPUs supported in the PSCI firmware.

The A80, having 2 clusters of 4 cores each, has an ARM CCI-400 hardware block for cache coherency.
Add the base address for CCI-400, and also add the base address for CPUCFG.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h index c775bcc515a0..88b48c644c06 100644 --- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h @@ -17,6 +17,9 @@ #define REGS_APB1_BASE 0x07000000 #define REGS_RCPUS_BASE 0x08000000
+#define SUNXI_CPUCFG_BASE 0x01700000 +#define SUNXI_CCI400_BASE 0x01790000 + #define SUNXI_SRAM_D_BASE 0x08100000
/* AHB0 Module */

Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
The A80, having 2 clusters of 4 cores each, has an ARM CCI-400 hardware block for cache coherency.
Add the base address for CCI-400, and also add the base address for CPUCFG.
Signed-off-by: Chen-Yu Tsai wens@csie.org
LGTM:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Regards,
Hans
arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h index c775bcc515a0..88b48c644c06 100644 --- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h @@ -17,6 +17,9 @@ #define REGS_APB1_BASE 0x07000000 #define REGS_RCPUS_BASE 0x08000000
+#define SUNXI_CPUCFG_BASE 0x01700000 +#define SUNXI_CCI400_BASE 0x01790000
#define SUNXI_SRAM_D_BASE 0x08100000
/* AHB0 Module */

The A80 has a 256 kiB secure SRAM. However the first 4 kiB are reserved for CPU0 hotplug flags.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h index 88b48c644c06..e9839eecaa92 100644 --- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h @@ -20,6 +20,7 @@ #define SUNXI_CPUCFG_BASE 0x01700000 #define SUNXI_CCI400_BASE 0x01790000
+#define SUNXI_SRAM_B_BASE 0x00020000 #define SUNXI_SRAM_D_BASE 0x08100000
/* AHB0 Module */

Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
The A80 has a 256 kiB secure SRAM. However the first 4 kiB are reserved for CPU0 hotplug flags.
Signed-off-by: Chen-Yu Tsai wens@csie.org
LGTM:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Regards,
Hans
arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h index 88b48c644c06..e9839eecaa92 100644 --- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h @@ -20,6 +20,7 @@ #define SUNXI_CPUCFG_BASE 0x01700000 #define SUNXI_CCI400_BASE 0x01790000
+#define SUNXI_SRAM_B_BASE 0x00020000 #define SUNXI_SRAM_D_BASE 0x08100000
/* AHB0 Module */

The A80 has a 256 kiB secure SRAM. However the first 4 kiB are reserved for CPU0 hotplug flags.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- include/configs/sun9i.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/configs/sun9i.h b/include/configs/sun9i.h index cd9e08d8b1b9..e751c5e05c14 100644 --- a/include/configs/sun9i.h +++ b/include/configs/sun9i.h @@ -13,6 +13,10 @@ * A80 specific configuration */
+/* First 4 kiB is reserved for CPU0 hotplug flags */ +#define CONFIG_ARMV7_SECURE_BASE (SUNXI_SRAM_B_BASE + 4 * 1024) +#define CONFIG_ARMV7_SECURE_MAX_SIZE (252 * 1024) /* 252 KB */ + /* * Include common sunxi configuration where most the settings are */

Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
The A80 has a 256 kiB secure SRAM. However the first 4 kiB are reserved for CPU0 hotplug flags.
Signed-off-by: Chen-Yu Tsai wens@csie.org
LGTM:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Regards,
Hans
include/configs/sun9i.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/configs/sun9i.h b/include/configs/sun9i.h index cd9e08d8b1b9..e751c5e05c14 100644 --- a/include/configs/sun9i.h +++ b/include/configs/sun9i.h @@ -13,6 +13,10 @@
- A80 specific configuration
*/
+/* First 4 kiB is reserved for CPU0 hotplug flags */ +#define CONFIG_ARMV7_SECURE_BASE (SUNXI_SRAM_B_BASE + 4 * 1024) +#define CONFIG_ARMV7_SECURE_MAX_SIZE (252 * 1024) /* 252 KB */
/*
- Include common sunxi configuration where most the settings are
*/

The A80 has a different PRCM register layout.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- arch/arm/include/asm/arch-sunxi/prcm_sun9i.h | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun9i.h
diff --git a/arch/arm/include/asm/arch-sunxi/prcm_sun9i.h b/arch/arm/include/asm/arch-sunxi/prcm_sun9i.h new file mode 100644 index 000000000000..f4732335fbcc --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/prcm_sun9i.h @@ -0,0 +1,55 @@ +/* + * Sunxi A80 Power Reset and Clock Module register definition + * + * (C) Copyright 2016 Chen-Yu Tsai wens@csie.org + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SUNXI_PRCM_SUN9I_H +#define _SUNXI_PRCM_SUN9I_H + +struct __packed sunxi_prcm_reg { + u32 cpus_rst; /* 0x000 */ + u32 cpu_rst[2]; /* 0x004 */ + u8 res0[0x4]; /* 0x00c */ + u32 cpus_cfg; /* 0x010 */ + u8 res1[0x8]; /* 0x014 */ + u32 apbs_ratio; /* 0x01c */ + u8 res2[0x8]; /* 0x020 */ + u32 apbs_gate; /* 0x028 */ + u8 res3[0x18]; /* 0x02c */ + u32 pll_ctrl1; /* 0x044 */ + u8 res4[0xc]; /* 0x048 */ + u32 clk_cir; /* 0x054 */ + u32 clk_i2s0; /* 0x058 */ + u32 clk_i2s1; /* 0x05c */ + u8 res5[0x50]; /* 0x060 */ + u32 apb0_reset; /* 0x0b0 */ + u8 res6[0x4c]; /* 0x0b4 */ + u32 cpu_pwroff[2]; /* 0x100 */ + u8 res7[0x8]; /* 0x108 */ + u32 vdd_sys_pwroff; /* 0x110 */ + u8 res8[0x4]; /* 0x114 */ + u32 gpu_pwroff; /* 0x118 */ + u8 res9[0x4]; /* 0x11c */ + u32 vdd_sys_rst; /* 0x120 */ + u8 res10[0x1c]; /* 0x124 */ + u32 cpu_pwr_clamp[2][4]; /* 0x140 */ + u32 super_standby_flag; /* 0x160 */ + u32 cpu_soft_entry; /* 0x164 */ + u32 super_standby_entry; /* 0x168 */ + u8 res11[0x34]; /* 0x16c */ + u32 nmi_irq_ctrl; /* 0x1a0 */ + u32 nmi_irq_en; /* 0x1a4 */ + u32 nmi_irq_status; /* 0x1a8 */ + u8 res12[0x14]; /* 0x1ac */ + u32 pll_audio_ctrl; /* 0x1c0 */ + u32 pll_audio_bias; /* 0x1c4 */ + u32 pll_audio_pat_cfg; /* 0x1c8 */ + u32 pll_audio_ctrl_sw; /* 0x1cc */ + u8 res13[0x20]; /* 0x1d0 */ + u32 osc24m_ctrl; /* 0x1f0 */ +}; + +#endif /* _SUNXI_PRCM_SUN9I_H */

Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
The A80 has a different PRCM register layout.
Signed-off-by: Chen-Yu Tsai wens@csie.org
LGTM:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Regards,
Hans
arch/arm/include/asm/arch-sunxi/prcm_sun9i.h | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun9i.h
diff --git a/arch/arm/include/asm/arch-sunxi/prcm_sun9i.h b/arch/arm/include/asm/arch-sunxi/prcm_sun9i.h new file mode 100644 index 000000000000..f4732335fbcc --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/prcm_sun9i.h @@ -0,0 +1,55 @@ +/*
- Sunxi A80 Power Reset and Clock Module register definition
- (C) Copyright 2016 Chen-Yu Tsai wens@csie.org
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _SUNXI_PRCM_SUN9I_H +#define _SUNXI_PRCM_SUN9I_H
+struct __packed sunxi_prcm_reg {
- u32 cpus_rst; /* 0x000 */
- u32 cpu_rst[2]; /* 0x004 */
- u8 res0[0x4]; /* 0x00c */
- u32 cpus_cfg; /* 0x010 */
- u8 res1[0x8]; /* 0x014 */
- u32 apbs_ratio; /* 0x01c */
- u8 res2[0x8]; /* 0x020 */
- u32 apbs_gate; /* 0x028 */
- u8 res3[0x18]; /* 0x02c */
- u32 pll_ctrl1; /* 0x044 */
- u8 res4[0xc]; /* 0x048 */
- u32 clk_cir; /* 0x054 */
- u32 clk_i2s0; /* 0x058 */
- u32 clk_i2s1; /* 0x05c */
- u8 res5[0x50]; /* 0x060 */
- u32 apb0_reset; /* 0x0b0 */
- u8 res6[0x4c]; /* 0x0b4 */
- u32 cpu_pwroff[2]; /* 0x100 */
- u8 res7[0x8]; /* 0x108 */
- u32 vdd_sys_pwroff; /* 0x110 */
- u8 res8[0x4]; /* 0x114 */
- u32 gpu_pwroff; /* 0x118 */
- u8 res9[0x4]; /* 0x11c */
- u32 vdd_sys_rst; /* 0x120 */
- u8 res10[0x1c]; /* 0x124 */
- u32 cpu_pwr_clamp[2][4]; /* 0x140 */
- u32 super_standby_flag; /* 0x160 */
- u32 cpu_soft_entry; /* 0x164 */
- u32 super_standby_entry; /* 0x168 */
- u8 res11[0x34]; /* 0x16c */
- u32 nmi_irq_ctrl; /* 0x1a0 */
- u32 nmi_irq_en; /* 0x1a4 */
- u32 nmi_irq_status; /* 0x1a8 */
- u8 res12[0x14]; /* 0x1ac */
- u32 pll_audio_ctrl; /* 0x1c0 */
- u32 pll_audio_bias; /* 0x1c4 */
- u32 pll_audio_pat_cfg; /* 0x1c8 */
- u32 pll_audio_ctrl_sw; /* 0x1cc */
- u8 res13[0x20]; /* 0x1d0 */
- u32 osc24m_ctrl; /* 0x1f0 */
+};
+#endif /* _SUNXI_PRCM_SUN9I_H */

The A80 has a different CPUCFG register layout, likely due to having 2 clusters.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h | 51 ++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h
diff --git a/arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h new file mode 100644 index 000000000000..0ee6a63e441b --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h @@ -0,0 +1,51 @@ +/* + * Sunxi A80 CPUCFG register definition. + * + * (C) Copyright 2016 Chen-Yu Tsai wens@csie.org + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SUNXI_CPUCFG_SUN9I_H +#define _SUNXI_CPUCFG_SUN9I_H + +#include <linux/compiler.h> +#include <linux/types.h> + +#define CPUCFG_CX_CTRL0_L1_RST_DISABLE(core) BIT(core) + +#define CPUCFG_CX_STATUS_STANDBYWFI(core) BIT(16 + core) + +#define CPUCFG_CX_RST_CORE(core) BIT(core) +#define CPUCFG_CX_RST_NEON(core) BIT(4 + core) /* A15 only */ +#define CPUCFG_CX_RST_L2 BIT(8) +#define CPUCFG_CX_RST_HRESET BIT(12) +#define CPUCFG_CX_RST_DBG(core) BIT(16 + core) +#define CPUCFG_CX_RST_ETM(core) BIT(20 + core) +#define CPUCFG_CX_RST_SOC_DBG BIT(24) + +#ifndef __ASSEMBLY__ + +struct __packed sunxi_cpucfg_cluster { + u32 ctrl0; /* base + 0x0 */ + u32 ctrl1; /* base + 0x4 */ + u32 adb400_pwrdnreqn; /* base + 0x8 */ + u8 res[0x4]; /* base + 0xc */ +}; + +struct __packed sunxi_cpucfg_reg { + struct sunxi_cpucfg_cluster cluster[2]; /* 0x00 */ + u8 res0[0x8]; /* 0x20 */ + u32 gen_ctrl0; /* 0x28 */ + u32 gen_ctrl1; /* 0x2c */ + u32 cluster_status[2]; /* 0x30 */ + u8 res1[0x4]; /* 0x38 */ + u32 irq_fiq_status; /* 0x3c */ + u32 irq_fiq_mask; /* 0x40 */ + u8 res2[0x3c]; /* 0x44 */ + u32 cluster_reset[2]; /* 0x80 */ + u32 gic_jtag_reset; /* 0x88 */ +}; + +#endif /* __ASSEMBLY__ */ +#endif /* _SUNXI_CPUCFG_SUN9I_H */

Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
The A80 has a different CPUCFG register layout, likely due to having 2 clusters.
Signed-off-by: Chen-Yu Tsai wens@csie.org
LGTM:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Regards,
Hans
arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h | 51 ++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h
diff --git a/arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h new file mode 100644 index 000000000000..0ee6a63e441b --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h @@ -0,0 +1,51 @@ +/*
- Sunxi A80 CPUCFG register definition.
- (C) Copyright 2016 Chen-Yu Tsai wens@csie.org
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _SUNXI_CPUCFG_SUN9I_H +#define _SUNXI_CPUCFG_SUN9I_H
+#include <linux/compiler.h> +#include <linux/types.h>
+#define CPUCFG_CX_CTRL0_L1_RST_DISABLE(core) BIT(core)
+#define CPUCFG_CX_STATUS_STANDBYWFI(core) BIT(16 + core)
+#define CPUCFG_CX_RST_CORE(core) BIT(core) +#define CPUCFG_CX_RST_NEON(core) BIT(4 + core) /* A15 only */ +#define CPUCFG_CX_RST_L2 BIT(8) +#define CPUCFG_CX_RST_HRESET BIT(12) +#define CPUCFG_CX_RST_DBG(core) BIT(16 + core) +#define CPUCFG_CX_RST_ETM(core) BIT(20 + core) +#define CPUCFG_CX_RST_SOC_DBG BIT(24)
+#ifndef __ASSEMBLY__
+struct __packed sunxi_cpucfg_cluster {
- u32 ctrl0; /* base + 0x0 */
- u32 ctrl1; /* base + 0x4 */
- u32 adb400_pwrdnreqn; /* base + 0x8 */
- u8 res[0x4]; /* base + 0xc */
+};
+struct __packed sunxi_cpucfg_reg {
- struct sunxi_cpucfg_cluster cluster[2]; /* 0x00 */
- u8 res0[0x8]; /* 0x20 */
- u32 gen_ctrl0; /* 0x28 */
- u32 gen_ctrl1; /* 0x2c */
- u32 cluster_status[2]; /* 0x30 */
- u8 res1[0x4]; /* 0x38 */
- u32 irq_fiq_status; /* 0x3c */
- u32 irq_fiq_mask; /* 0x40 */
- u8 res2[0x3c]; /* 0x44 */
- u32 cluster_reset[2]; /* 0x80 */
- u32 gic_jtag_reset; /* 0x88 */
+};
+#endif /* __ASSEMBLY__ */ +#endif /* _SUNXI_CPUCFG_SUN9I_H */

The A80 also has the TrustZone Protection Controller (TZPC), called the Secure Memory Touch Arbiter (SMTA).
Enable non-secure access to all the peripherals at boot time.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- arch/arm/cpu/armv7/sunxi/Makefile | 1 + arch/arm/cpu/armv7/sunxi/tzpc.c | 6 ++++++ arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 1 + arch/arm/include/asm/arch-sunxi/tzpc.h | 4 ++++ arch/arm/mach-sunxi/board.c | 3 ++- 5 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index b35b9df4a9d6..239c659ec032 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -11,6 +11,7 @@ obj-y += timer.o
obj-$(CONFIG_MACH_SUN6I) += tzpc.o obj-$(CONFIG_MACH_SUN8I_H3) += tzpc.o +obj-$(CONFIG_MACH_SUN9I) += tzpc.o
ifndef CONFIG_SPL_BUILD obj-$(CONFIG_ARMV7_PSCI) += psci.o diff --git a/arch/arm/cpu/armv7/sunxi/tzpc.c b/arch/arm/cpu/armv7/sunxi/tzpc.c index 6c8a0fd9a25b..2a2cf363b99c 100644 --- a/arch/arm/cpu/armv7/sunxi/tzpc.c +++ b/arch/arm/cpu/armv7/sunxi/tzpc.c @@ -24,4 +24,10 @@ void tzpc_init(void) writel(SUN8I_H3_TZPC_DECPORT1_ALL, &tzpc->decport1_set); writel(SUN8I_H3_TZPC_DECPORT2_ALL, &tzpc->decport2_set); #endif + +#ifdef CONFIG_MACH_SUN9I + writel(SUN9I_TZPC_DECPORT0_ALL, &tzpc->decport0_set); + writel(SUN9I_TZPC_DECPORT1_ALL, &tzpc->decport1_set); + writel(SUN9I_TZPC_DECPORT2_ALL, &tzpc->decport2_set); +#endif } diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h index e9839eecaa92..25114174f395 100644 --- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h @@ -90,6 +90,7 @@ #define SUNXI_TIMER_BASE (REGS_APB0_BASE + 0x0C00) #define SUNXI_PWM_BASE (REGS_APB0_BASE + 0x1400) #define SUNXI_LRADC_BASE (REGS_APB0_BASE + 0x1800) +#define SUNXI_TZPC_BASE (REGS_APB0_BASE + 0x3400)
/* APB1 Module */ #define SUNXI_UART0_BASE (REGS_APB1_BASE + 0x0000) diff --git a/arch/arm/include/asm/arch-sunxi/tzpc.h b/arch/arm/include/asm/arch-sunxi/tzpc.h index 95c55cd4d130..3425d00edd97 100644 --- a/arch/arm/include/asm/arch-sunxi/tzpc.h +++ b/arch/arm/include/asm/arch-sunxi/tzpc.h @@ -29,6 +29,10 @@ struct sunxi_tzpc { #define SUN8I_H3_TZPC_DECPORT1_ALL 0xff #define SUN8I_H3_TZPC_DECPORT2_ALL 0x7f
+#define SUN9I_TZPC_DECPORT0_ALL 0xfe +#define SUN9I_TZPC_DECPORT1_ALL 0x7f +#define SUN9I_TZPC_DECPORT2_ALL 0x00 + void tzpc_init(void);
#endif /* _SUNXI_TZPC_H */ diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 0f8ead980cdc..0053f562e00d 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -190,7 +190,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 || defined CONFIG_MACH_SUN8I_H3 +#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I_H3 || \ + defined CONFIG_MACH_SUN9I /* Enable non-secure access to some peripherals */ tzpc_init(); #endif

Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
The A80 also has the TrustZone Protection Controller (TZPC), called the Secure Memory Touch Arbiter (SMTA).
Enable non-secure access to all the peripherals at boot time.
Signed-off-by: Chen-Yu Tsai wens@csie.org
LGTM:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Regards,
Hans
arch/arm/cpu/armv7/sunxi/Makefile | 1 + arch/arm/cpu/armv7/sunxi/tzpc.c | 6 ++++++ arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 1 + arch/arm/include/asm/arch-sunxi/tzpc.h | 4 ++++ arch/arm/mach-sunxi/board.c | 3 ++- 5 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index b35b9df4a9d6..239c659ec032 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -11,6 +11,7 @@ obj-y += timer.o
obj-$(CONFIG_MACH_SUN6I) += tzpc.o obj-$(CONFIG_MACH_SUN8I_H3) += tzpc.o +obj-$(CONFIG_MACH_SUN9I) += tzpc.o
ifndef CONFIG_SPL_BUILD obj-$(CONFIG_ARMV7_PSCI) += psci.o diff --git a/arch/arm/cpu/armv7/sunxi/tzpc.c b/arch/arm/cpu/armv7/sunxi/tzpc.c index 6c8a0fd9a25b..2a2cf363b99c 100644 --- a/arch/arm/cpu/armv7/sunxi/tzpc.c +++ b/arch/arm/cpu/armv7/sunxi/tzpc.c @@ -24,4 +24,10 @@ void tzpc_init(void) writel(SUN8I_H3_TZPC_DECPORT1_ALL, &tzpc->decport1_set); writel(SUN8I_H3_TZPC_DECPORT2_ALL, &tzpc->decport2_set); #endif
+#ifdef CONFIG_MACH_SUN9I
- writel(SUN9I_TZPC_DECPORT0_ALL, &tzpc->decport0_set);
- writel(SUN9I_TZPC_DECPORT1_ALL, &tzpc->decport1_set);
- writel(SUN9I_TZPC_DECPORT2_ALL, &tzpc->decport2_set);
+#endif } diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h index e9839eecaa92..25114174f395 100644 --- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h @@ -90,6 +90,7 @@ #define SUNXI_TIMER_BASE (REGS_APB0_BASE + 0x0C00) #define SUNXI_PWM_BASE (REGS_APB0_BASE + 0x1400) #define SUNXI_LRADC_BASE (REGS_APB0_BASE + 0x1800) +#define SUNXI_TZPC_BASE (REGS_APB0_BASE + 0x3400)
/* APB1 Module */ #define SUNXI_UART0_BASE (REGS_APB1_BASE + 0x0000) diff --git a/arch/arm/include/asm/arch-sunxi/tzpc.h b/arch/arm/include/asm/arch-sunxi/tzpc.h index 95c55cd4d130..3425d00edd97 100644 --- a/arch/arm/include/asm/arch-sunxi/tzpc.h +++ b/arch/arm/include/asm/arch-sunxi/tzpc.h @@ -29,6 +29,10 @@ struct sunxi_tzpc { #define SUN8I_H3_TZPC_DECPORT1_ALL 0xff #define SUN8I_H3_TZPC_DECPORT2_ALL 0x7f
+#define SUN9I_TZPC_DECPORT0_ALL 0xfe +#define SUN9I_TZPC_DECPORT1_ALL 0x7f +#define SUN9I_TZPC_DECPORT2_ALL 0x00
void tzpc_init(void);
#endif /* _SUNXI_TZPC_H */ diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 0f8ead980cdc..0053f562e00d 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -190,7 +190,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 || defined CONFIG_MACH_SUN8I_H3 +#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I_H3 || \
- defined CONFIG_MACH_SUN9I /* Enable non-secure access to some peripherals */ tzpc_init();
#endif

The A80 is a big.LITTLE multi-cluster SoC, with a different layout for the PRCM and CPUCFG registers. As such it needs a different PSCI implementation.
This patch adds a basic version that allows bringing up the four cores in the first cluster. The structure is based on existing sunxi PSCI code.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- arch/arm/cpu/armv7/sunxi/Makefile | 4 + arch/arm/cpu/armv7/sunxi/psci-mcpm.c | 234 +++++++++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 arch/arm/cpu/armv7/sunxi/psci-mcpm.c
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index 239c659ec032..b18e5f1fa974 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -14,8 +14,12 @@ obj-$(CONFIG_MACH_SUN8I_H3) += tzpc.o obj-$(CONFIG_MACH_SUN9I) += tzpc.o
ifndef CONFIG_SPL_BUILD +ifdef CONFIG_MACH_SUN9I +obj-$(CONFIG_ARMV7_PSCI) += psci-mcpm.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-mcpm.c b/arch/arm/cpu/armv7/sunxi/psci-mcpm.c new file mode 100644 index 000000000000..3ede07cace2c --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/psci-mcpm.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2016 + * Author: Chen-Yu Tsai wens@csie.org + * + * Based on assembly code by Marc Zyngier marc.zyngier@arm.com, + * which was based on code by Carl van Schaik carl@ok-labs.com. + * + * SPDX-License-Identifier: GPL-2.0 + */ +#include <config.h> +#include <common.h> + +#include <asm/arch/cpu.h> +#include <asm/arch/cpucfg_sun9i.h> +#include <asm/arch/prcm_sun9i.h> +#include <asm/armv7.h> +#include <asm/io.h> +#include <asm/psci.h> +#include <asm/secure.h> + +#include <linux/bitops.h> + +/* + * NOTE dense CPU IDs (0~3 for first cluster of 4 cores, 4~7 for the + * second cluster) are used throughout the PSCI code. Any MPIDR style + * values must be converted. + */ + +/* + * Provide a dense CPU ID for 2-cluster systems. This must be coded in + * assembly as it gets called from psci_stack_setup, when the stack isn't + * available yet. + * + * Only r0 and r3 is usable. r8 - r12 are available if this function is + * only called from psci_stack_setup, which we cannot guarantee. + */ +u32 __secure __naked psci_get_cpu_id(void) +{ + asm volatile ( + "mrc p15, 0, r3, c0, c0, 5 @ Get MPIDR\n" + "lsr r0, r3, #6\n" + "and r3, r3, #3\n" + "and r0, r0, #4\n" + "orr r0, r0, r3\n" + "bx lr\n" + ); + + /* + * The last five lines are the compiler generated assembly code for + * + * return (reg & 0x3) | (((reg >> 8) & 0x1) << 2); + * + * We can't guarantee that all compilers correctly use only r0 and + * r3, so we use inline assembly here. + */ +} + +static void __secure cp15_write_cntp_tval(u32 tval) +{ + asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval)); +} + +static void __secure cp15_write_cntp_ctl(u32 val) +{ + asm volatile ("mcr p15, 0, %0, c14, c2, 1" : : "r" (val)); +} + +static u32 __secure cp15_read_cntp_ctl(void) +{ + u32 val; + + asm volatile ("mrc p15, 0, %0, c14, c2, 1" : "=r" (val)); + + return val; +} + +#define ONE_US (CONFIG_TIMER_CLK_FREQ / 1000000) + +/* Use a different name to avoid clashing with the non-secure function */ +static void __secure __udelay_sec(unsigned long us) +{ + u32 reg = ONE_US * us; + + cp15_write_cntp_tval(reg); + isb(); + cp15_write_cntp_ctl(3); + + do { + isb(); + reg = cp15_read_cntp_ctl(); + } while (!(reg & BIT(2))); + + cp15_write_cntp_ctl(0); + isb(); +} + +static void __secure clamp_release(u32 *clamp) +{ + writel(0xff, clamp); + __udelay_sec(10); + writel(0xfe, clamp); + __udelay_sec(10); + writel(0xf8, clamp); + __udelay_sec(10); + writel(0xf0, clamp); + __udelay_sec(10); + writel(0x00, clamp); +} + +static void __secure clamp_set(u32 *clamp) +{ + writel(0xff, clamp); +} + +static void __secure sunxi_core_power_switch(u32 *clamp, u32 *pwroff, + bool on, int cpu) +{ + if (on) { + /* Release power clamp */ + clamp_release(clamp); + + __udelay_sec(20); + + /* Clear power gating */ + clrbits_le32(pwroff, BIT(cpu)); + } else { + /* Set power gating */ + setbits_le32(pwroff, BIT(cpu)); + + __udelay_sec(20); + + /* Activate power clamp */ + clamp_set(clamp); + } +} + +static void __secure sunxi_cpu_set_power(int cpu, bool on) +{ + struct sunxi_prcm_reg *prcm = + (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE; + int cluster = (cpu >> 2) & 0x1; + int core = cpu & 0x3; + + sunxi_core_power_switch(&prcm->cpu_pwr_clamp[cluster][core], + &prcm->cpu_pwroff[cluster], on, core); +} + +static u32 __secure cp15_read_scr(void) +{ + u32 scr; + + asm volatile ("mrc p15, 0, %0, c1, c1, 0" : "=r" (scr)); + + return scr; +} + +static void __secure cp15_write_scr(u32 scr) +{ + asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (scr)); + isb(); +} + +int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc) +{ + struct sunxi_cpucfg_reg *cpucfg = + (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE; + struct sunxi_prcm_reg *prcm = + (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE; + u32 cluster = (mpidr >> 8) & 0x1; + u32 cpu = mpidr & 0x3; + u32 cpuid = cpu | (cluster << 2); + + /* TODO We don't support multi-cluster yet */ + if (cluster > 0) + return ARM_PSCI_RET_INVAL; + + /* store target PC */ + psci_save_target_pc(cpuid, pc); + + /* Set secondary core power on PC */ + writel((u32)&psci_cpu_entry, &prcm->cpu_soft_entry); + + /* Assert power-on reset on target CPU */ + clrbits_le32(&prcm->cpu_rst[cluster], BIT(cpu)); + + /* Cortex-A7: hold L1 cache reset disable signal low */ + if (cluster == 0) + clrbits_le32(&cpucfg->cluster[cluster].ctrl0, + CPUCFG_CX_CTRL0_L1_RST_DISABLE(cpu)); + + /* Lock CPU (Disable external debug access) */ + clrbits_le32(&cpucfg->cluster_reset[cluster], + CPUCFG_CX_RST_DBG(cpu)); + + /* Cortex-A7: Assert ETM reset */ + if (cluster == 0) + clrbits_le32(&cpucfg->cluster_reset[cluster], + CPUCFG_CX_RST_ETM(cpu)); + + /* + * Allwinner code also asserts resets for NEON on A15. According + * to ARM manuals, asserting power-on reset is sufficient. + */ + + /* Power up target CPU */ + sunxi_cpu_set_power(cpu, true); + + /* De-assert power-on reset on target CPU */ + setbits_le32(&prcm->cpu_rst[cluster], BIT(cpu)); + + /* De-assert core reset on target CPU */ + setbits_le32(&cpucfg->cluster_reset[cluster], + CPUCFG_CX_RST_CORE(cpu)); + + /* Cortex-A7: De-assert ETM reset */ + if (cluster == 0) + setbits_le32(&cpucfg->cluster_reset[cluster], + CPUCFG_CX_RST_ETM(cpu)); + + /* Unlock CPU (Disable external debug access) */ + setbits_le32(&cpucfg->cluster_reset[cluster], + CPUCFG_CX_RST_DBG(cpu)); + + return ARM_PSCI_RET_SUCCESS; +} + +void __secure psci_arch_init(void) +{ + u32 reg; + + reg = cp15_read_scr(); + reg &= ~BIT(0); /* Secure mode */ + cp15_write_scr(reg); +}

Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
The A80 is a big.LITTLE multi-cluster SoC, with a different layout for the PRCM and CPUCFG registers. As such it needs a different PSCI implementation.
This patch adds a basic version that allows bringing up the four cores in the first cluster. The structure is based on existing sunxi PSCI code.
Signed-off-by: Chen-Yu Tsai wens@csie.org
LGTM:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Regards,
Hans
arch/arm/cpu/armv7/sunxi/Makefile | 4 + arch/arm/cpu/armv7/sunxi/psci-mcpm.c | 234 +++++++++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 arch/arm/cpu/armv7/sunxi/psci-mcpm.c
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index 239c659ec032..b18e5f1fa974 100644 --- a/arch/arm/cpu/armv7/sunxi/Makefile +++ b/arch/arm/cpu/armv7/sunxi/Makefile @@ -14,8 +14,12 @@ obj-$(CONFIG_MACH_SUN8I_H3) += tzpc.o obj-$(CONFIG_MACH_SUN9I) += tzpc.o
ifndef CONFIG_SPL_BUILD +ifdef CONFIG_MACH_SUN9I +obj-$(CONFIG_ARMV7_PSCI) += psci-mcpm.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-mcpm.c b/arch/arm/cpu/armv7/sunxi/psci-mcpm.c new file mode 100644 index 000000000000..3ede07cace2c --- /dev/null +++ b/arch/arm/cpu/armv7/sunxi/psci-mcpm.c @@ -0,0 +1,234 @@ +/*
- Copyright (C) 2016
- Author: Chen-Yu Tsai wens@csie.org
- Based on assembly code by Marc Zyngier marc.zyngier@arm.com,
- which was based on code by Carl van Schaik carl@ok-labs.com.
- SPDX-License-Identifier: GPL-2.0
- */
+#include <config.h> +#include <common.h>
+#include <asm/arch/cpu.h> +#include <asm/arch/cpucfg_sun9i.h> +#include <asm/arch/prcm_sun9i.h> +#include <asm/armv7.h> +#include <asm/io.h> +#include <asm/psci.h> +#include <asm/secure.h>
+#include <linux/bitops.h>
+/*
- NOTE dense CPU IDs (0~3 for first cluster of 4 cores, 4~7 for the
- second cluster) are used throughout the PSCI code. Any MPIDR style
- values must be converted.
- */
+/*
- Provide a dense CPU ID for 2-cluster systems. This must be coded in
- assembly as it gets called from psci_stack_setup, when the stack isn't
- available yet.
- Only r0 and r3 is usable. r8 - r12 are available if this function is
- only called from psci_stack_setup, which we cannot guarantee.
- */
+u32 __secure __naked psci_get_cpu_id(void) +{
- asm volatile (
"mrc p15, 0, r3, c0, c0, 5 @ Get MPIDR\n"
"lsr r0, r3, #6\n"
"and r3, r3, #3\n"
"and r0, r0, #4\n"
"orr r0, r0, r3\n"
"bx lr\n"
- );
- /*
* The last five lines are the compiler generated assembly code for
*
* return (reg & 0x3) | (((reg >> 8) & 0x1) << 2);
*
* We can't guarantee that all compilers correctly use only r0 and
* r3, so we use inline assembly here.
*/
+}
+static void __secure cp15_write_cntp_tval(u32 tval) +{
- asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval));
+}
+static void __secure cp15_write_cntp_ctl(u32 val) +{
- asm volatile ("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
+}
+static u32 __secure cp15_read_cntp_ctl(void) +{
- u32 val;
- asm volatile ("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
- return val;
+}
+#define ONE_US (CONFIG_TIMER_CLK_FREQ / 1000000)
+/* Use a different name to avoid clashing with the non-secure function */ +static void __secure __udelay_sec(unsigned long us) +{
- u32 reg = ONE_US * us;
- cp15_write_cntp_tval(reg);
- isb();
- cp15_write_cntp_ctl(3);
- do {
isb();
reg = cp15_read_cntp_ctl();
- } while (!(reg & BIT(2)));
- cp15_write_cntp_ctl(0);
- isb();
+}
+static void __secure clamp_release(u32 *clamp) +{
- writel(0xff, clamp);
- __udelay_sec(10);
- writel(0xfe, clamp);
- __udelay_sec(10);
- writel(0xf8, clamp);
- __udelay_sec(10);
- writel(0xf0, clamp);
- __udelay_sec(10);
- writel(0x00, clamp);
+}
+static void __secure clamp_set(u32 *clamp) +{
- writel(0xff, clamp);
+}
+static void __secure sunxi_core_power_switch(u32 *clamp, u32 *pwroff,
bool on, int cpu)
+{
- if (on) {
/* Release power clamp */
clamp_release(clamp);
__udelay_sec(20);
/* Clear power gating */
clrbits_le32(pwroff, BIT(cpu));
- } else {
/* Set power gating */
setbits_le32(pwroff, BIT(cpu));
__udelay_sec(20);
/* Activate power clamp */
clamp_set(clamp);
- }
+}
+static void __secure sunxi_cpu_set_power(int cpu, bool on) +{
- struct sunxi_prcm_reg *prcm =
(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
- int cluster = (cpu >> 2) & 0x1;
- int core = cpu & 0x3;
- sunxi_core_power_switch(&prcm->cpu_pwr_clamp[cluster][core],
&prcm->cpu_pwroff[cluster], on, core);
+}
+static u32 __secure cp15_read_scr(void) +{
- u32 scr;
- asm volatile ("mrc p15, 0, %0, c1, c1, 0" : "=r" (scr));
- return scr;
+}
+static void __secure cp15_write_scr(u32 scr) +{
- asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (scr));
- isb();
+}
+int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc) +{
- struct sunxi_cpucfg_reg *cpucfg =
(struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
- struct sunxi_prcm_reg *prcm =
(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
- u32 cluster = (mpidr >> 8) & 0x1;
- u32 cpu = mpidr & 0x3;
- u32 cpuid = cpu | (cluster << 2);
- /* TODO We don't support multi-cluster yet */
- if (cluster > 0)
return ARM_PSCI_RET_INVAL;
- /* store target PC */
- psci_save_target_pc(cpuid, pc);
- /* Set secondary core power on PC */
- writel((u32)&psci_cpu_entry, &prcm->cpu_soft_entry);
- /* Assert power-on reset on target CPU */
- clrbits_le32(&prcm->cpu_rst[cluster], BIT(cpu));
- /* Cortex-A7: hold L1 cache reset disable signal low */
- if (cluster == 0)
clrbits_le32(&cpucfg->cluster[cluster].ctrl0,
CPUCFG_CX_CTRL0_L1_RST_DISABLE(cpu));
- /* Lock CPU (Disable external debug access) */
- clrbits_le32(&cpucfg->cluster_reset[cluster],
CPUCFG_CX_RST_DBG(cpu));
- /* Cortex-A7: Assert ETM reset */
- if (cluster == 0)
clrbits_le32(&cpucfg->cluster_reset[cluster],
CPUCFG_CX_RST_ETM(cpu));
- /*
* Allwinner code also asserts resets for NEON on A15. According
* to ARM manuals, asserting power-on reset is sufficient.
*/
- /* Power up target CPU */
- sunxi_cpu_set_power(cpu, true);
- /* De-assert power-on reset on target CPU */
- setbits_le32(&prcm->cpu_rst[cluster], BIT(cpu));
- /* De-assert core reset on target CPU */
- setbits_le32(&cpucfg->cluster_reset[cluster],
CPUCFG_CX_RST_CORE(cpu));
- /* Cortex-A7: De-assert ETM reset */
- if (cluster == 0)
setbits_le32(&cpucfg->cluster_reset[cluster],
CPUCFG_CX_RST_ETM(cpu));
- /* Unlock CPU (Disable external debug access) */
- setbits_le32(&cpucfg->cluster_reset[cluster],
CPUCFG_CX_RST_DBG(cpu));
- return ARM_PSCI_RET_SUCCESS;
+}
+void __secure psci_arch_init(void) +{
- u32 reg;
- reg = cp15_read_scr();
- reg &= ~BIT(0); /* Secure mode */
- cp15_write_scr(reg);
+}

Now that we have a basic version of PSCI firmware, enable non-secure boot and PSCI on the A80.
Signed-off-by: Chen-Yu Tsai wens@csie.org --- board/sunxi/Kconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index e1d4ab148f08..ae2fba1368cc 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -118,8 +118,12 @@ config MACH_SUN8I_H3 config MACH_SUN9I bool "sun9i (Allwinner A80)" select CPU_V7 + select CPU_V7_HAS_NONSEC + select CPU_V7_HAS_VIRT + select ARCH_SUPPORT_PSCI select SUNXI_GEN_SUN6I select SUPPORT_SPL + select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
config MACH_SUN50I bool "sun50i (Allwinner A64)"

Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
Now that we have a basic version of PSCI firmware, enable non-secure boot and PSCI on the A80.
Signed-off-by: Chen-Yu Tsai wens@csie.org
LGTM:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Regards,
Hans
board/sunxi/Kconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index e1d4ab148f08..ae2fba1368cc 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -118,8 +118,12 @@ config MACH_SUN8I_H3 config MACH_SUN9I bool "sun9i (Allwinner A80)" select CPU_V7
- select CPU_V7_HAS_NONSEC
- select CPU_V7_HAS_VIRT
- select ARCH_SUPPORT_PSCI select SUNXI_GEN_SUN6I select SUPPORT_SPL
- select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
config MACH_SUN50I bool "sun50i (Allwinner A64)"

I this this series is already merged as with latest changes on tree, but still shows 'New' in patchwork, Can someone confirm then I will update the same?
On Wed, Nov 9, 2016 at 3:51 PM, Chen-Yu Tsai wens@csie.org wrote:
Now that we have a basic version of PSCI firmware, enable non-secure boot and PSCI on the A80.
Signed-off-by: Chen-Yu Tsai wens@csie.org
board/sunxi/Kconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index e1d4ab148f08..ae2fba1368cc 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -118,8 +118,12 @@ config MACH_SUN8I_H3 config MACH_SUN9I bool "sun9i (Allwinner A80)" select CPU_V7
select CPU_V7_HAS_NONSEC
select CPU_V7_HAS_VIRT
select ARCH_SUPPORT_PSCI select SUNXI_GEN_SUN6I select SUPPORT_SPL
select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
config MACH_SUN50I bool "sun50i (Allwinner A64)" -- 2.10.2
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Hi,
On Mon, Apr 3, 2017 at 8:13 PM, Jagan Teki jagannadh.teki@gmail.com wrote:
I this this series is already merged as with latest changes on tree, but still shows 'New' in patchwork, Can someone confirm then I will update the same?
The series is on hold, as it breaks Linux. I've identified the culprit (non-secure world access to the GIC is actually secure) but the fix is really nasty and I haven't tested it reliably yet.
ChenYu
On Wed, Nov 9, 2016 at 3:51 PM, Chen-Yu Tsai wens@csie.org wrote:
Now that we have a basic version of PSCI firmware, enable non-secure boot and PSCI on the A80.
Signed-off-by: Chen-Yu Tsai wens@csie.org
board/sunxi/Kconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index e1d4ab148f08..ae2fba1368cc 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -118,8 +118,12 @@ config MACH_SUN8I_H3 config MACH_SUN9I bool "sun9i (Allwinner A80)" select CPU_V7
select CPU_V7_HAS_NONSEC
select CPU_V7_HAS_VIRT
select ARCH_SUPPORT_PSCI select SUNXI_GEN_SUN6I select SUPPORT_SPL
select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
config MACH_SUN50I bool "sun50i (Allwinner A64)" -- 2.10.2
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
-- Jagan Teki Free Software Engineer | www.openedev.com U-Boot, Linux | Upstream Maintainer Hyderabad, India.

This patch adds the ability to power off cores in the first cluster of the A80 SoC. Following the single cluster sunxi PSCI implementation, the core being powered down signals core0 via secure monitor FIQ that it should be shut down, and enters WFI.
Signed-off-by: Chen-Yu Tsai wens@csie.org ---
This does not actually work. While the system is indeed booted non-secure, tested by trying to write to secure SRAM and the results not sticking, reads from the GIC CPU interface shows that it's still returning the secure copy of registers, and since we use a secure monitor FIQ to do core power down, the FIQ gets passed to the kernel. The patch is included so people with in-depth ARM knowledge could probably help work out what is wrong.
Any thoughts on this is appreciated.
--- arch/arm/cpu/armv7/sunxi/psci-mcpm.c | 88 ++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+)
diff --git a/arch/arm/cpu/armv7/sunxi/psci-mcpm.c b/arch/arm/cpu/armv7/sunxi/psci-mcpm.c index 3ede07cace2c..1403aeed74f4 100644 --- a/arch/arm/cpu/armv7/sunxi/psci-mcpm.c +++ b/arch/arm/cpu/armv7/sunxi/psci-mcpm.c @@ -14,12 +14,19 @@ #include <asm/arch/cpucfg_sun9i.h> #include <asm/arch/prcm_sun9i.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>
#include <linux/bitops.h>
+#define __irq __attribute__ ((interrupt ("IRQ"))) + +#define GICD_BASE (SUNXI_GIC400_BASE + GIC_DIST_OFFSET) +#define GICC_BASE (SUNXI_GIC400_BASE + GIC_CPU_OFFSET_A15) + /* * NOTE dense CPU IDs (0~3 for first cluster of 4 cores, 4~7 for the * second cluster) are used throughout the PSCI code. Any MPIDR style @@ -145,6 +152,25 @@ static void __secure sunxi_cpu_set_power(int cpu, bool on) &prcm->cpu_pwroff[cluster], on, core); }
+void __secure sunxi_cpu_power_off(u32 cpuid) +{ + struct sunxi_cpucfg_reg *cpucfg = + (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE; + u32 cluster = (cpuid >> 2) & 0x1; + u32 core = cpuid & 0x3; + + /* Wait for the core to enter WFI */ + while (1) { + if (readl(&cpucfg->cluster_status[cluster]) & + CPUCFG_CX_STATUS_STANDBYWFI(core)) + break; + __udelay_sec(1000); + } + + /* Power down CPU */ + sunxi_cpu_set_power(cpuid, false); +} + static u32 __secure cp15_read_scr(void) { u32 scr; @@ -160,6 +186,42 @@ static void __secure cp15_write_scr(u32 scr) isb(); }
+/* + * Although this is an FIQ handler, the FIQ is processed in monitor mode, + * which means there's no FIQ banked registers. This is the same as IRQ + * mode, so use the IRQ attribute to ask the compiler to handler entry + * and return. + */ +void __secure __irq psci_fiq_enter(void) +{ + u32 scr, reg, cpu; + + /* Switch to secure mode */ + scr = cp15_read_scr(); + cp15_write_scr(scr & ~BIT(0)); + + /* Validate reason based on IAR and acknowledge */ + reg = readl(GICC_BASE + GICC_IAR); + + /* Skip spurious interrupts 1022 and 1023 */ + if (reg == 1023 || reg == 1022) + goto out; + + /* End of interrupt */ + writel(reg, GICC_BASE + GICC_EOIR); + dsb(); + + /* Get CPU number */ + cpu = (reg >> 10) & 0x7; + + /* Power off the CPU */ + sunxi_cpu_power_off(cpu); + +out: + /* Restore security level */ + cp15_write_scr(scr); +} + int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc) { struct sunxi_cpucfg_reg *cpucfg = @@ -224,11 +286,37 @@ int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc) return ARM_PSCI_RET_SUCCESS; }
+void __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(); + + /* Wait to be turned off */ + while (1) + wfi(); +} + void __secure psci_arch_init(void) { u32 reg;
+ /* SGI15 as Group-0 */ + clrbits_le32(GICD_BASE + GICD_IGROUPRn, BIT(15)); + + /* Set SGI15 priority to 0 */ + writeb(0, GICD_BASE + GICD_IPRIORITYRn + 15); + + /* Be cool with non-secure */ + writel(0xff, GICC_BASE + GICC_PMR); + + /* Switch FIQEn on */ + setbits_le32(GICC_BASE + GICC_CTLR, BIT(3)); + reg = cp15_read_scr(); + reg |= BIT(2); /* Enable FIQ in monitor mode */ reg &= ~BIT(0); /* Secure mode */ cp15_write_scr(reg); }

Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
Hi everyone,
This series adds basic PSCI support for the A80 to enable SMP on the first cluster. This at least allows people to use more than one core. The term "basic" is used because the series does not add support for multi-cluster cache and power management.
The PSCI code is based on existing code for all the single cluster SoCs, and the kernel patches for MCPM SMP I did some time ago.
Unfortunately only SMP works at this time. The last patch does not actually work. While the system is indeed booted non-secure, tested by trying to write to secure SRAM and the results not sticking, reads from the GIC CPU interface shows that it's still returning the secure copy of registers, and since we use a secure monitor FIQ to do core power down, the FIQ gets passed to the kernel. The patch is included so people with in-depth ARM knowledge could probably help work out what is wrong.
Cools stuff, when I find some time I will review and merge patches 1-9 to sunxi-next.
First a question though, do you see any chance that merging this might get in the way of enabling support for both clusters in the future?
Since the interface between u-boot and the kernel here is well defined (and outside our control) I guess in the worst case, we would need to revert some bits of this series from u-boot if they turn out to be non suitable, right?
Regards,
Hans
Regards ChenYu
Chen-Yu Tsai (10): ARM: PSCI: Set ARMV7_PSCI_NR_CPUS default to 8 for sun9i/A80 sunxi: Add CCI-400 and CPUCFG registers base address for sun9i/A80 sunxi: Add base address of secure SRAM B for sun9i/A80 sunxi: Use secure SRAM B for secure RAM for sun9i/A80 sunxi: Add PRCM register definition for sun9i/A80 sunxi: Add CPUCFG register definitions for sun9i/A80 sunxi: Add support for TZPC on sun9i/A80 sunxi: Add basic PSCI implementation for A80 sunxi: Enable PSCI on sun9i/A80 sunxi: Add PSCI core power off support for A80's first cluster
arch/arm/cpu/armv7/Kconfig | 1 + arch/arm/cpu/armv7/sunxi/Makefile | 5 + arch/arm/cpu/armv7/sunxi/psci-mcpm.c | 322 +++++++++++++++++++++++++ arch/arm/cpu/armv7/sunxi/tzpc.c | 6 + arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 5 + arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h | 51 ++++ arch/arm/include/asm/arch-sunxi/prcm_sun9i.h | 55 +++++ arch/arm/include/asm/arch-sunxi/tzpc.h | 4 + arch/arm/mach-sunxi/board.c | 3 +- board/sunxi/Kconfig | 4 + include/configs/sun9i.h | 4 + 11 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/sunxi/psci-mcpm.c create mode 100644 arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun9i.h

On Wed, Nov 9, 2016 at 6:38 PM, Hans de Goede hdegoede@redhat.com wrote:
Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
Hi everyone,
This series adds basic PSCI support for the A80 to enable SMP on the first cluster. This at least allows people to use more than one core. The term "basic" is used because the series does not add support for multi-cluster cache and power management.
The PSCI code is based on existing code for all the single cluster SoCs, and the kernel patches for MCPM SMP I did some time ago.
Unfortunately only SMP works at this time. The last patch does not actually work. While the system is indeed booted non-secure, tested by trying to write to secure SRAM and the results not sticking, reads from the GIC CPU interface shows that it's still returning the secure copy of registers, and since we use a secure monitor FIQ to do core power down, the FIQ gets passed to the kernel. The patch is included so people with in-depth ARM knowledge could probably help work out what is wrong.
Cools stuff, when I find some time I will review and merge patches 1-9 to sunxi-next.
First a question though, do you see any chance that merging this might get in the way of enabling support for both clusters in the future?
Since the interface between u-boot and the kernel here is well defined (and outside our control) I guess in the worst case, we would need to revert some bits of this series from u-boot if they turn out to be non suitable, right?
AFAIK with PSCI the firmware is responsible for doing all the setup before handing the core to the kernel. For now I just return -EINVAL for the latter 4 cores.
Once we have all the multi cluster support in, such as cluster powering, synchronization, and CCI-400, instead of returning -EINVAL, we can have it actually give back a working core.
And Linux can't access CCI-400 in non-secure mode anyway. This has to be setup by the firmware.
In short, just merging the power on bits for the first cluster here should not block any attempts to merge any future progress.
Regards ChenYu
Regards,
Hans
Regards ChenYu
Chen-Yu Tsai (10): ARM: PSCI: Set ARMV7_PSCI_NR_CPUS default to 8 for sun9i/A80 sunxi: Add CCI-400 and CPUCFG registers base address for sun9i/A80 sunxi: Add base address of secure SRAM B for sun9i/A80 sunxi: Use secure SRAM B for secure RAM for sun9i/A80 sunxi: Add PRCM register definition for sun9i/A80 sunxi: Add CPUCFG register definitions for sun9i/A80 sunxi: Add support for TZPC on sun9i/A80 sunxi: Add basic PSCI implementation for A80 sunxi: Enable PSCI on sun9i/A80 sunxi: Add PSCI core power off support for A80's first cluster
arch/arm/cpu/armv7/Kconfig | 1 + arch/arm/cpu/armv7/sunxi/Makefile | 5 + arch/arm/cpu/armv7/sunxi/psci-mcpm.c | 322 +++++++++++++++++++++++++ arch/arm/cpu/armv7/sunxi/tzpc.c | 6 + arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 5 + arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h | 51 ++++ arch/arm/include/asm/arch-sunxi/prcm_sun9i.h | 55 +++++ arch/arm/include/asm/arch-sunxi/tzpc.h | 4 + arch/arm/mach-sunxi/board.c | 3 +- board/sunxi/Kconfig | 4 + include/configs/sun9i.h | 4 + 11 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/sunxi/psci-mcpm.c create mode 100644 arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun9i.h

Hi,
On Wed, Nov 9, 2016 at 6:38 PM, Hans de Goede hdegoede@redhat.com wrote:
Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
Hi everyone,
This series adds basic PSCI support for the A80 to enable SMP on the first cluster. This at least allows people to use more than one core. The term "basic" is used because the series does not add support for multi-cluster cache and power management.
The PSCI code is based on existing code for all the single cluster SoCs, and the kernel patches for MCPM SMP I did some time ago.
Unfortunately only SMP works at this time. The last patch does not actually work. While the system is indeed booted non-secure, tested by trying to write to secure SRAM and the results not sticking, reads from the GIC CPU interface shows that it's still returning the secure copy of registers, and since we use a secure monitor FIQ to do core power down, the FIQ gets passed to the kernel. The patch is included so people with in-depth ARM knowledge could probably help work out what is wrong.
Cools stuff, when I find some time I will review and merge patches 1-9 to sunxi-next.
First a question though, do you see any chance that merging this might get in the way of enabling support for both clusters in the future?
Since the interface between u-boot and the kernel here is well defined (and outside our control) I guess in the worst case, we would need to revert some bits of this series from u-boot if they turn out to be non suitable, right?
So I started digging through why CPU power off is sending FIQs to the kernel. So it turns out that the GIC base address programmed in the CPU's CBAR is incorrect, so the GIC is not blocking secure interrupts, and when the interrupt returns the CPU seems to get switched to secure mode.
After hard-coding in the correct address, the system no longer boots. It hangs when it tries to bring up the second core. I'm not sure what's going on though. Need to add some more trace code.
I might have opened a can of worms...
ChenYu
Regards,
Hans
Regards ChenYu
Chen-Yu Tsai (10): ARM: PSCI: Set ARMV7_PSCI_NR_CPUS default to 8 for sun9i/A80 sunxi: Add CCI-400 and CPUCFG registers base address for sun9i/A80 sunxi: Add base address of secure SRAM B for sun9i/A80 sunxi: Use secure SRAM B for secure RAM for sun9i/A80 sunxi: Add PRCM register definition for sun9i/A80 sunxi: Add CPUCFG register definitions for sun9i/A80 sunxi: Add support for TZPC on sun9i/A80 sunxi: Add basic PSCI implementation for A80 sunxi: Enable PSCI on sun9i/A80 sunxi: Add PSCI core power off support for A80's first cluster
arch/arm/cpu/armv7/Kconfig | 1 + arch/arm/cpu/armv7/sunxi/Makefile | 5 + arch/arm/cpu/armv7/sunxi/psci-mcpm.c | 322 +++++++++++++++++++++++++ arch/arm/cpu/armv7/sunxi/tzpc.c | 6 + arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 5 + arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h | 51 ++++ arch/arm/include/asm/arch-sunxi/prcm_sun9i.h | 55 +++++ arch/arm/include/asm/arch-sunxi/tzpc.h | 4 + arch/arm/mach-sunxi/board.c | 3 +- board/sunxi/Kconfig | 4 + include/configs/sun9i.h | 4 + 11 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/sunxi/psci-mcpm.c create mode 100644 arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun9i.h

Hi everyone,
On Mon, Nov 14, 2016 at 7:21 PM, Chen-Yu Tsai wens@csie.org wrote:
Hi,
On Wed, Nov 9, 2016 at 6:38 PM, Hans de Goede hdegoede@redhat.com wrote:
Hi,
On 09-11-16 11:21, Chen-Yu Tsai wrote:
Hi everyone,
This series adds basic PSCI support for the A80 to enable SMP on the first cluster. This at least allows people to use more than one core. The term "basic" is used because the series does not add support for multi-cluster cache and power management.
The PSCI code is based on existing code for all the single cluster SoCs, and the kernel patches for MCPM SMP I did some time ago.
Unfortunately only SMP works at this time. The last patch does not actually work. While the system is indeed booted non-secure, tested by trying to write to secure SRAM and the results not sticking, reads from the GIC CPU interface shows that it's still returning the secure copy of registers, and since we use a secure monitor FIQ to do core power down, the FIQ gets passed to the kernel. The patch is included so people with in-depth ARM knowledge could probably help work out what is wrong.
Cools stuff, when I find some time I will review and merge patches 1-9 to sunxi-next.
First a question though, do you see any chance that merging this might get in the way of enabling support for both clusters in the future?
Since the interface between u-boot and the kernel here is well defined (and outside our control) I guess in the worst case, we would need to revert some bits of this series from u-boot if they turn out to be non suitable, right?
So I started digging through why CPU power off is sending FIQs to the kernel. So it turns out that the GIC base address programmed in the CPU's CBAR is incorrect, so the GIC is not blocking secure interrupts, and when the interrupt returns the CPU seems to get switched to secure mode.
After hard-coding in the correct address, the system no longer boots. It hangs when it tries to bring up the second core. I'm not sure what's going on though. Need to add some more trace code.
I might have opened a can of worms...
I got PSCI actually working today.
So the whole TrustZone implementation on the A80 is kind of broken, much like the A64. The TZPC doesn't actually do anything. All access to the GIC is "secure", regardless of the core's secure state. This means if we want separate groups of interrupts (secure and non-secure), which we do for the PSCI implementation for one core to tell another to shut it down, we have to use the aliased non-secure register fields, all the while making sure not to step on the secure interrupts the PSCI firmware needs.
This is doable, and it is actually what Allwinner's kernel does, but is really hackish. The released 3.4 kernel also has the same workarounds for A83T. So it's also possible the A83T has the same issues.
So, if there's still interest in getting a working PSCI environment for the A80/A83T, I'll look into doing a workaround patch for GIC-400. Otherwise I'm going to go back and revive my MCPM patches for in-kernel SMP support.
Regards ChenYu
ChenYu
Regards,
Hans
Regards ChenYu
Chen-Yu Tsai (10): ARM: PSCI: Set ARMV7_PSCI_NR_CPUS default to 8 for sun9i/A80 sunxi: Add CCI-400 and CPUCFG registers base address for sun9i/A80 sunxi: Add base address of secure SRAM B for sun9i/A80 sunxi: Use secure SRAM B for secure RAM for sun9i/A80 sunxi: Add PRCM register definition for sun9i/A80 sunxi: Add CPUCFG register definitions for sun9i/A80 sunxi: Add support for TZPC on sun9i/A80 sunxi: Add basic PSCI implementation for A80 sunxi: Enable PSCI on sun9i/A80 sunxi: Add PSCI core power off support for A80's first cluster
arch/arm/cpu/armv7/Kconfig | 1 + arch/arm/cpu/armv7/sunxi/Makefile | 5 + arch/arm/cpu/armv7/sunxi/psci-mcpm.c | 322 +++++++++++++++++++++++++ arch/arm/cpu/armv7/sunxi/tzpc.c | 6 + arch/arm/include/asm/arch-sunxi/cpu_sun9i.h | 5 + arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h | 51 ++++ arch/arm/include/asm/arch-sunxi/prcm_sun9i.h | 55 +++++ arch/arm/include/asm/arch-sunxi/tzpc.h | 4 + arch/arm/mach-sunxi/board.c | 3 +- board/sunxi/Kconfig | 4 + include/configs/sun9i.h | 4 + 11 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/sunxi/psci-mcpm.c create mode 100644 arch/arm/include/asm/arch-sunxi/cpucfg_sun9i.h create mode 100644 arch/arm/include/asm/arch-sunxi/prcm_sun9i.h

On Wed, Jan 25, 2017 at 06:40:38PM +0800, Chen-Yu Tsai wrote:
[hacking around the broken A80 TrustZone implementation]
This is doable, and it is actually what Allwinner's kernel does, but is really hackish. The released 3.4 kernel also has the same workarounds for A83T. So it's also possible the A83T has the same issues.
FWIW, the kernel that ships with my A80 based media player produces this: [ 0.000000] Linux version 3.4.39+ (lzq@sunchip-CS24-TY) (gcc version 4.6.3 20120201 (prerelease) (crosstool-NG linaro-1.13.1-2012.02-20120222 - Linaro GCC 2012.02) ) #1 SMP PREEMPT Sat Nov 14 03:33:12 UTC 2015 ... [ 0.262230] CPU4: failed to boot: -22 [ 0.302298] CPU5: failed to boot: -22 [ 0.342350] CPU6: failed to boot: -22 [ 0.382421] CPU7: failed to boot: -22
So I guess you are not alone in having trouble getting PSCI to work on the A80. However, when trying out your patches, I also once or twice got a failure booting CPU2 although CPU3 and CPU4 came up fine.
So, if there's still interest in getting a working PSCI environment for the A80/A83T, I'll look into doing a workaround patch for GIC-400. Otherwise I'm going to go back and revive my MCPM patches for in-kernel SMP support.
I vote for whatever works. I'll also happily test it. Is there a git tree I should keep an eye on?
participants (4)
-
Chen-Yu Tsai
-
Hans de Goede
-
Jagan Teki
-
Rask Ingemann Lambertsen