From: Magnus Damm Date: Wed, 31 Jul 2013 07:07:49 +0000 (+0900) Subject: ARM: shmobile: Add shared SCU CPU Hotplug code X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=e7b1c96384181d690950530f5a64167965226744;p=linux-beck.git ARM: shmobile: Add shared SCU CPU Hotplug code 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 Signed-off-by: Simon Horman --- diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 42761f4fb171..04209d5c0338 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 8f478e4d4964..7a0c066df686 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 #include #include #include +#include #include #include #include @@ -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