diff options
-rw-r--r-- | arch/arm/mach-berlin/platsmp.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/arch/arm/mach-berlin/platsmp.c b/arch/arm/mach-berlin/platsmp.c index 34a3753e7356..405cd37e4fba 100644 --- a/arch/arm/mach-berlin/platsmp.c +++ b/arch/arm/mach-berlin/platsmp.c | |||
@@ -14,10 +14,16 @@ | |||
14 | #include <linux/of_address.h> | 14 | #include <linux/of_address.h> |
15 | 15 | ||
16 | #include <asm/cacheflush.h> | 16 | #include <asm/cacheflush.h> |
17 | #include <asm/cp15.h> | ||
17 | #include <asm/smp_plat.h> | 18 | #include <asm/smp_plat.h> |
18 | #include <asm/smp_scu.h> | 19 | #include <asm/smp_scu.h> |
19 | 20 | ||
20 | #define CPU_RESET 0x00 | 21 | /* |
22 | * There are two reset registers, one with self-clearing (SC) | ||
23 | * reset and one with non-self-clearing reset (NON_SC). | ||
24 | */ | ||
25 | #define CPU_RESET_SC 0x00 | ||
26 | #define CPU_RESET_NON_SC 0x20 | ||
21 | 27 | ||
22 | #define RESET_VECT 0x00 | 28 | #define RESET_VECT 0x00 |
23 | #define SW_RESET_ADDR 0x94 | 29 | #define SW_RESET_ADDR 0x94 |
@@ -30,9 +36,11 @@ static inline void berlin_perform_reset_cpu(unsigned int cpu) | |||
30 | { | 36 | { |
31 | u32 val; | 37 | u32 val; |
32 | 38 | ||
33 | val = readl(cpu_ctrl + CPU_RESET); | 39 | val = readl(cpu_ctrl + CPU_RESET_NON_SC); |
40 | val &= ~BIT(cpu_logical_map(cpu)); | ||
41 | writel(val, cpu_ctrl + CPU_RESET_NON_SC); | ||
34 | val |= BIT(cpu_logical_map(cpu)); | 42 | val |= BIT(cpu_logical_map(cpu)); |
35 | writel(val, cpu_ctrl + CPU_RESET); | 43 | writel(val, cpu_ctrl + CPU_RESET_NON_SC); |
36 | } | 44 | } |
37 | 45 | ||
38 | static int berlin_boot_secondary(unsigned int cpu, struct task_struct *idle) | 46 | static int berlin_boot_secondary(unsigned int cpu, struct task_struct *idle) |
@@ -91,8 +99,32 @@ unmap_scu: | |||
91 | iounmap(scu_base); | 99 | iounmap(scu_base); |
92 | } | 100 | } |
93 | 101 | ||
102 | #ifdef CONFIG_HOTPLUG_CPU | ||
103 | static void berlin_cpu_die(unsigned int cpu) | ||
104 | { | ||
105 | v7_exit_coherency_flush(louis); | ||
106 | while (1) | ||
107 | cpu_do_idle(); | ||
108 | } | ||
109 | |||
110 | static int berlin_cpu_kill(unsigned int cpu) | ||
111 | { | ||
112 | u32 val; | ||
113 | |||
114 | val = readl(cpu_ctrl + CPU_RESET_NON_SC); | ||
115 | val &= ~BIT(cpu_logical_map(cpu)); | ||
116 | writel(val, cpu_ctrl + CPU_RESET_NON_SC); | ||
117 | |||
118 | return 1; | ||
119 | } | ||
120 | #endif | ||
121 | |||
94 | static struct smp_operations berlin_smp_ops __initdata = { | 122 | static struct smp_operations berlin_smp_ops __initdata = { |
95 | .smp_prepare_cpus = berlin_smp_prepare_cpus, | 123 | .smp_prepare_cpus = berlin_smp_prepare_cpus, |
96 | .smp_boot_secondary = berlin_boot_secondary, | 124 | .smp_boot_secondary = berlin_boot_secondary, |
125 | #ifdef CONFIG_HOTPLUG_CPU | ||
126 | .cpu_die = berlin_cpu_die, | ||
127 | .cpu_kill = berlin_cpu_kill, | ||
128 | #endif | ||
97 | }; | 129 | }; |
98 | CPU_METHOD_OF_DECLARE(berlin_smp, "marvell,berlin-smp", &berlin_smp_ops); | 130 | CPU_METHOD_OF_DECLARE(berlin_smp, "marvell,berlin-smp", &berlin_smp_ops); |