diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-01-10 13:16:37 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-01-10 13:16:37 +0900 |
commit | ea75b9c127e67683a11f7c9c8e052172f28d9266 (patch) | |
tree | 707d616bc44bb7ad251cc92985a586a8e34c3426 | |
parent | 916b1f8c81ea563611288d1a9b082df3f723e4fe (diff) | |
parent | 1229835ccb6d7ea2b36230121205be95c88eca88 (diff) |
Merge branch 'rmobile/core' into rmobile/marzen
-rw-r--r-- | arch/arm/mach-shmobile/headsmp.S | 2 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/hotplug.c | 32 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/common.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/platsmp.c | 5 |
4 files changed, 38 insertions, 2 deletions
diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S index 26079d933d9..6ac015c8920 100644 --- a/arch/arm/mach-shmobile/headsmp.S +++ b/arch/arm/mach-shmobile/headsmp.S @@ -14,7 +14,7 @@ #include <linux/init.h> #include <asm/memory.h> - __INIT + __CPUINIT /* * Reset vector for secondary CPUs. diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c index 238a0d97d2d..828d22f3af5 100644 --- a/arch/arm/mach-shmobile/hotplug.c +++ b/arch/arm/mach-shmobile/hotplug.c @@ -12,14 +12,43 @@ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/smp.h> +#include <linux/cpumask.h> +#include <linux/delay.h> +#include <mach/common.h> +#include <asm/cacheflush.h> + +static cpumask_t dead_cpus; int platform_cpu_kill(unsigned int cpu) { - return 1; + 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 (cpumask_test_cpu(cpu, &dead_cpus)) + return shmobile_platform_cpu_kill(cpu); + + mdelay(1); + } + + return 0; } void platform_cpu_die(unsigned int cpu) { + /* hardware shutdown code running on the CPU that is being offlined */ + flush_cache_all(); + dsb(); + + /* notify platform_cpu_kill() that hardware shutdown is finished */ + cpumask_set_cpu(cpu, &dead_cpus); + + /* wait for SoC code in platform_cpu_kill() to shut off CPU core + * power. CPU bring up starts from the reset vector. + */ while (1) { /* * here's the WFI @@ -33,6 +62,7 @@ void platform_cpu_die(unsigned int cpu) int platform_cpu_disable(unsigned int cpu) { + cpumask_clear_cpu(cpu, &dead_cpus); /* * we don't allow CPU 0 to be shutdown (it is still too special * e.g. clock tick interrupts) diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 65e954b0877..304ac311533 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -4,6 +4,7 @@ extern struct sys_timer shmobile_timer; extern void shmobile_setup_console(void); extern void shmobile_secondary_vector(void); +extern int shmobile_platform_cpu_kill(unsigned int cpu); struct clk; extern int clk_init(void); extern void shmobile_handle_irq_intc(struct pt_regs *); diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index c49a833bf9b..3f3325d4206 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -37,6 +37,11 @@ static void __init shmobile_smp_prepare_cpus(void) sh73a0_smp_prepare_cpus(); } +int shmobile_platform_cpu_kill(unsigned int cpu) +{ + return 1; +} + void __cpuinit platform_secondary_init(unsigned int cpu) { trace_hardirqs_off(); |