diff options
-rw-r--r-- | arch/arm/mach-shmobile/include/mach/common.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/platsmp-scu.c | 45 |
2 files changed, 47 insertions, 0 deletions
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); | |||
14 | extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus); | 14 | extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus); |
15 | extern int shmobile_smp_scu_boot_secondary(unsigned int cpu, | 15 | extern int shmobile_smp_scu_boot_secondary(unsigned int cpu, |
16 | struct task_struct *idle); | 16 | struct task_struct *idle); |
17 | extern void shmobile_smp_scu_cpu_die(unsigned int cpu); | ||
18 | extern int shmobile_smp_scu_cpu_kill(unsigned int cpu); | ||
17 | struct clk; | 19 | struct clk; |
18 | extern int shmobile_clk_init(void); | 20 | extern int shmobile_clk_init(void); |
19 | extern void shmobile_handle_irq_intc(struct pt_regs *); | 21 | 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 @@ | |||
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #include <linux/delay.h> | ||
10 | #include <linux/init.h> | 11 | #include <linux/init.h> |
11 | #include <linux/io.h> | 12 | #include <linux/io.h> |
12 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
14 | #include <asm/cacheflush.h> | ||
13 | #include <asm/smp_plat.h> | 15 | #include <asm/smp_plat.h> |
14 | #include <asm/smp_scu.h> | 16 | #include <asm/smp_scu.h> |
15 | #include <mach/common.h> | 17 | #include <mach/common.h> |
@@ -29,3 +31,46 @@ int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
29 | /* do nothing for now */ | 31 | /* do nothing for now */ |
30 | return 0; | 32 | return 0; |
31 | } | 33 | } |
34 | |||
35 | #ifdef CONFIG_HOTPLUG_CPU | ||
36 | void shmobile_smp_scu_cpu_die(unsigned int cpu) | ||
37 | { | ||
38 | dsb(); | ||
39 | flush_cache_all(); | ||
40 | |||
41 | /* disable cache coherency */ | ||
42 | scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF); | ||
43 | |||
44 | /* Endless loop until reset */ | ||
45 | while (1) | ||
46 | cpu_do_idle(); | ||
47 | } | ||
48 | |||
49 | static int shmobile_smp_scu_psr_core_disabled(int cpu) | ||
50 | { | ||
51 | unsigned long mask = SCU_PM_POWEROFF << (cpu * 8); | ||
52 | |||
53 | if ((__raw_readl(shmobile_scu_base + 8) & mask) == mask) | ||
54 | return 1; | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | int shmobile_smp_scu_cpu_kill(unsigned int cpu) | ||
60 | { | ||
61 | int k; | ||
62 | |||
63 | /* this function is running on another CPU than the offline target, | ||
64 | * here we need wait for shutdown code in platform_cpu_die() to | ||
65 | * finish before asking SoC-specific code to power off the CPU core. | ||
66 | */ | ||
67 | for (k = 0; k < 1000; k++) { | ||
68 | if (shmobile_smp_scu_psr_core_disabled(cpu)) | ||
69 | return 1; | ||
70 | |||
71 | mdelay(1); | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | #endif | ||