sunxi: Add PSCI support for R40
authorChen-Yu Tsai <wens@csie.org>
Wed, 1 Mar 2017 03:03:15 +0000 (11:03 +0800)
committerMaxime Ripard <maxime.ripard@free-electrons.com>
Thu, 20 Apr 2017 11:30:01 +0000 (13:30 +0200)
The R40's CPU controls are a combination of sun6i and sun7i.

All controls are in the CPUCFG block, and it seems the R40 does not
have a PRCM block. The core reset, power gating and clamp controls
are grouped like sun6i.

Last, the R40 does not have a secure SRAM block.

This patch adds a PSCI implementation for CPU bring-up and hotplug
for the R40.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
arch/arm/cpu/armv7/sunxi/psci.c
board/sunxi/Kconfig

index 104dc90..b3a34de 100644 (file)
 #define        GICD_BASE       (SUNXI_GIC400_BASE + GIC_DIST_OFFSET)
 #define        GICC_BASE       (SUNXI_GIC400_BASE + GIC_CPU_OFFSET_A15)
 
+/*
+ * R40 is different from other single cluster SoCs.
+ *
+ * The power clamps are located in the unused space after the per-core
+ * reset controls for core 3. The secondary core entry address register
+ * is in the SRAM controller address range.
+ */
+#define SUN8I_R40_PWROFF                       (0x110)
+#define SUN8I_R40_PWR_CLAMP(cpu)               (0x120 + (cpu) * 0x4)
+#define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0                (0xbc)
+
 static void __secure cp15_write_cntp_tval(u32 tval)
 {
        asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval));
@@ -68,7 +79,8 @@ static void __secure __mdelay(u32 ms)
 static void __secure clamp_release(u32 __maybe_unused *clamp)
 {
 #if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
-       defined(CONFIG_MACH_SUN8I_H3)
+       defined(CONFIG_MACH_SUN8I_H3) || \
+       defined(CONFIG_MACH_SUN8I_R40)
        u32 tmp = 0x1ff;
        do {
                tmp >>= 1;
@@ -82,7 +94,8 @@ static void __secure clamp_release(u32 __maybe_unused *clamp)
 static void __secure clamp_set(u32 __maybe_unused *clamp)
 {
 #if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
-       defined(CONFIG_MACH_SUN8I_H3)
+       defined(CONFIG_MACH_SUN8I_H3) || \
+       defined(CONFIG_MACH_SUN8I_R40)
        writel(0xff, clamp);
 #endif
 }
@@ -115,7 +128,17 @@ static void __secure sunxi_cpu_set_power(int __always_unused cpu, bool on)
        sunxi_power_switch(&cpucfg->cpu1_pwr_clamp, &cpucfg->cpu1_pwroff,
                           on, 0);
 }
-#else /* ! CONFIG_MACH_SUN7I */
+#elif defined CONFIG_MACH_SUN8I_R40
+static void __secure sunxi_cpu_set_power(int cpu, bool on)
+{
+       struct sunxi_cpucfg_reg *cpucfg =
+               (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+
+       sunxi_power_switch((void *)cpucfg + SUN8I_R40_PWR_CLAMP(cpu),
+                          (void *)cpucfg + SUN8I_R40_PWROFF,
+                          on, 0);
+}
+#else /* ! CONFIG_MACH_SUN7I && ! CONFIG_MACH_SUN8I_R40 */
 static void __secure sunxi_cpu_set_power(int cpu, bool on)
 {
        struct sunxi_prcm_reg *prcm =
@@ -213,7 +236,13 @@ int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc)
        psci_save_target_pc(cpu, pc);
 
        /* Set secondary core power on PC */
+#ifdef CONFIG_MACH_SUN8I_R40
+       /* secondary core entry address is programmed differently */
+       writel((u32)&psci_cpu_entry,
+              SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
+#else
        writel((u32)&psci_cpu_entry, &cpucfg->priv0);
+#endif
 
        /* Assert reset on target CPU */
        writel(0, &cpucfg->cpu[cpu].rst);
index 0040e7e..c4fba84 100644 (file)
@@ -137,6 +137,9 @@ config MACH_SUN8I_H3
 config MACH_SUN8I_R40
        bool "sun8i (Allwinner R40)"
        select CPU_V7
+       select CPU_V7_HAS_NONSEC
+       select CPU_V7_HAS_VIRT
+       select ARCH_SUPPORT_PSCI
        select SUNXI_GEN_SUN6I
        select SUPPORT_SPL