diff options
author | Chen-Yu Tsai <wens@csie.org> | 2017-03-01 11:03:15 +0800 |
---|---|---|
committer | Maxime Ripard <maxime.ripard@free-electrons.com> | 2017-04-20 13:30:01 +0200 |
commit | 0918648d823d6a5a9bd5fc37ddcaa9691e84ce88 (patch) | |
tree | b464404864195a2f3cfee19442ab257b3e032b83 /arch | |
parent | acef236454a97c65a9d95fc5845b38ce5602f506 (diff) |
sunxi: Add PSCI support for R40
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/psci.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c index 104dc909bc5..b3a34de1aaf 100644 --- a/arch/arm/cpu/armv7/sunxi/psci.c +++ b/arch/arm/cpu/armv7/sunxi/psci.c @@ -27,6 +27,17 @@ #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); |