[GIT PULL 5/9] ARM: shmobile: Add shared SCU CPU Hotplug code
From: Simon Horman <hidden>
Date: 2013-08-07 04:39:31
Also in:
linux-sh
Subsystem:
arm port, arm/risc-v/renesas architecture, the rest · Maintainers:
Russell King, Geert Uytterhoeven, Magnus Damm, Linus Torvalds
From: Magnus Damm <redacted> Add CPU Hotplug functions for SCU equipped mach-shmobile SoCs. The functions shmobile_smp_scu_cpu_die() together with shmobile_smp_scu_cpu_kill() perform basic shutdown and allows checking of shutdown status. These are written to work together with SMP boot code in headsmp-scu.S. Signed-off-by: Magnus Damm <redacted> Signed-off-by: Simon Horman <redacted> --- arch/arm/mach-shmobile/include/mach/common.h | 2 ++ arch/arm/mach-shmobile/platsmp-scu.c | 45 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+)
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 42761f4..04209d5 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h@@ -14,6 +14,8 @@ extern void shmobile_boot_scu(void); extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus); extern int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle); +extern void shmobile_smp_scu_cpu_die(unsigned int cpu); +extern int shmobile_smp_scu_cpu_kill(unsigned int cpu); struct clk; extern int shmobile_clk_init(void); extern void shmobile_handle_irq_intc(struct pt_regs *);
diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c
index 8f478e4..7a0c066 100644
--- a/arch/arm/mach-shmobile/platsmp-scu.c
+++ b/arch/arm/mach-shmobile/platsmp-scu.c@@ -7,9 +7,11 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include <linux/delay.h> #include <linux/init.h> #include <linux/io.h> #include <linux/smp.h> +#include <asm/cacheflush.h> #include <asm/smp_plat.h> #include <asm/smp_scu.h> #include <mach/common.h>
@@ -29,3 +31,46 @@ int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle) /* do nothing for now */ return 0; } + +#ifdef CONFIG_HOTPLUG_CPU +void shmobile_smp_scu_cpu_die(unsigned int cpu) +{ + dsb(); + flush_cache_all(); + + /* disable cache coherency */ + scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF); + + /* Endless loop until reset */ + while (1) + cpu_do_idle(); +} + +static int shmobile_smp_scu_psr_core_disabled(int cpu) +{ + unsigned long mask = SCU_PM_POWEROFF << (cpu * 8); + + if ((__raw_readl(shmobile_scu_base + 8) & mask) == mask) + return 1; + + return 0; +} + +int shmobile_smp_scu_cpu_kill(unsigned int cpu) +{ + int k; + + /* this function is running on another CPU than the offline target, + * here we need wait for shutdown code in platform_cpu_die() to + * finish before asking SoC-specific code to power off the CPU core. + */ + for (k = 0; k < 1000; k++) { + if (shmobile_smp_scu_psr_core_disabled(cpu)) + return 1; + + mdelay(1); + } + + return 0; +} +#endif
--
1.8.3.2