diff options
author | Magnus Damm <damm@opensource.se> | 2011-12-28 02:53:16 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-01-08 20:37:29 -0500 |
commit | 1229835ccb6d7ea2b36230121205be95c88eca88 (patch) | |
tree | 7b8c0e49cc88b6a554552e8dd70ae52d1baefd76 /arch | |
parent | 8b306796995609c281f6d32b3cbaa814551ad5ac (diff) |
ARM: mach-shmobile: Flush caches in platform_cpu_die()
Add cache flushing code to the SH-Mobile specific CPU hotplug
implementation. While at it, add a cpu mask to make sure the
cache flushing code is finished in platform_cpu_die() before
letting the SoC-specific code in shmobile_platform_cpu_kill()
proceed with turning off power.
Without this code CPU hotplug offline fails when cache is
enabled on Cortex-A9 based SoCs.
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-shmobile/hotplug.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c index aee3a1088a5a..828d22f3af57 100644 --- a/arch/arm/mach-shmobile/hotplug.c +++ b/arch/arm/mach-shmobile/hotplug.c | |||
@@ -12,15 +12,43 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/smp.h> | 14 | #include <linux/smp.h> |
15 | #include <linux/cpumask.h> | ||
16 | #include <linux/delay.h> | ||
15 | #include <mach/common.h> | 17 | #include <mach/common.h> |
18 | #include <asm/cacheflush.h> | ||
19 | |||
20 | static cpumask_t dead_cpus; | ||
16 | 21 | ||
17 | int platform_cpu_kill(unsigned int cpu) | 22 | int platform_cpu_kill(unsigned int cpu) |
18 | { | 23 | { |
19 | return shmobile_platform_cpu_kill(cpu); | 24 | int k; |
25 | |||
26 | /* this function is running on another CPU than the offline target, | ||
27 | * here we need wait for shutdown code in platform_cpu_die() to | ||
28 | * finish before asking SoC-specific code to power off the CPU core. | ||
29 | */ | ||
30 | for (k = 0; k < 1000; k++) { | ||
31 | if (cpumask_test_cpu(cpu, &dead_cpus)) | ||
32 | return shmobile_platform_cpu_kill(cpu); | ||
33 | |||
34 | mdelay(1); | ||
35 | } | ||
36 | |||
37 | return 0; | ||
20 | } | 38 | } |
21 | 39 | ||
22 | void platform_cpu_die(unsigned int cpu) | 40 | void platform_cpu_die(unsigned int cpu) |
23 | { | 41 | { |
42 | /* hardware shutdown code running on the CPU that is being offlined */ | ||
43 | flush_cache_all(); | ||
44 | dsb(); | ||
45 | |||
46 | /* notify platform_cpu_kill() that hardware shutdown is finished */ | ||
47 | cpumask_set_cpu(cpu, &dead_cpus); | ||
48 | |||
49 | /* wait for SoC code in platform_cpu_kill() to shut off CPU core | ||
50 | * power. CPU bring up starts from the reset vector. | ||
51 | */ | ||
24 | while (1) { | 52 | while (1) { |
25 | /* | 53 | /* |
26 | * here's the WFI | 54 | * here's the WFI |
@@ -34,6 +62,7 @@ void platform_cpu_die(unsigned int cpu) | |||
34 | 62 | ||
35 | int platform_cpu_disable(unsigned int cpu) | 63 | int platform_cpu_disable(unsigned int cpu) |
36 | { | 64 | { |
65 | cpumask_clear_cpu(cpu, &dead_cpus); | ||
37 | /* | 66 | /* |
38 | * we don't allow CPU 0 to be shutdown (it is still too special | 67 | * we don't allow CPU 0 to be shutdown (it is still too special |
39 | * e.g. clock tick interrupts) | 68 | * e.g. clock tick interrupts) |