diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-03-29 23:38:01 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-04-20 23:23:25 -0400 |
commit | 3366e3585fbf0d40ce6f2382b544851cf4df1654 (patch) | |
tree | 2d0e01291d103d28bdb67afffb816fa1d7023fbb | |
parent | 4a6feab0ee5240c4bd5378d9f8a46b85718c68a7 (diff) |
sh: Move platform smp ops in to their own structure.
This cribs the MIPS plat_smp_ops approach for wrapping up the platform
ops. This will allow for mixing and matching different ops on the same
platform in the future.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | arch/sh/boards/board-urquell.c | 3 | ||||
-rw-r--r-- | arch/sh/boards/mach-sdk7786/setup.c | 3 | ||||
-rw-r--r-- | arch/sh/boards/mach-x3proto/setup.c | 7 | ||||
-rw-r--r-- | arch/sh/include/asm/smp-ops.h | 39 | ||||
-rw-r--r-- | arch/sh/include/asm/smp.h | 18 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/smp-shx3.c | 20 | ||||
-rw-r--r-- | arch/sh/kernel/localtimer.c | 2 | ||||
-rw-r--r-- | arch/sh/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/sh/kernel/smp.c | 24 |
9 files changed, 95 insertions, 23 deletions
diff --git a/arch/sh/boards/board-urquell.c b/arch/sh/boards/board-urquell.c index a9bd6e3ee10b..d81c609decc7 100644 --- a/arch/sh/boards/board-urquell.c +++ b/arch/sh/boards/board-urquell.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <cpu/sh7786.h> | 24 | #include <cpu/sh7786.h> |
25 | #include <asm/heartbeat.h> | 25 | #include <asm/heartbeat.h> |
26 | #include <asm/sizes.h> | 26 | #include <asm/sizes.h> |
27 | #include <asm/smp-ops.h> | ||
27 | 28 | ||
28 | /* | 29 | /* |
29 | * bit 1234 5678 | 30 | * bit 1234 5678 |
@@ -203,6 +204,8 @@ static void __init urquell_setup(char **cmdline_p) | |||
203 | printk(KERN_INFO "Renesas Technology Corp. Urquell support.\n"); | 204 | printk(KERN_INFO "Renesas Technology Corp. Urquell support.\n"); |
204 | 205 | ||
205 | pm_power_off = urquell_power_off; | 206 | pm_power_off = urquell_power_off; |
207 | |||
208 | register_smp_ops(&shx3_smp_ops); | ||
206 | } | 209 | } |
207 | 210 | ||
208 | /* | 211 | /* |
diff --git a/arch/sh/boards/mach-sdk7786/setup.c b/arch/sh/boards/mach-sdk7786/setup.c index 0c057a93fe29..2ec1ea5cf8ef 100644 --- a/arch/sh/boards/mach-sdk7786/setup.c +++ b/arch/sh/boards/mach-sdk7786/setup.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/heartbeat.h> | 21 | #include <asm/heartbeat.h> |
22 | #include <asm/sizes.h> | 22 | #include <asm/sizes.h> |
23 | #include <asm/reboot.h> | 23 | #include <asm/reboot.h> |
24 | #include <asm/smp-ops.h> | ||
24 | 25 | ||
25 | static struct resource heartbeat_resource = { | 26 | static struct resource heartbeat_resource = { |
26 | .start = 0x07fff8b0, | 27 | .start = 0x07fff8b0, |
@@ -189,6 +190,8 @@ static void __init sdk7786_setup(char **cmdline_p) | |||
189 | 190 | ||
190 | machine_ops.restart = sdk7786_restart; | 191 | machine_ops.restart = sdk7786_restart; |
191 | pm_power_off = sdk7786_power_off; | 192 | pm_power_off = sdk7786_power_off; |
193 | |||
194 | register_smp_ops(&shx3_smp_ops); | ||
192 | } | 195 | } |
193 | 196 | ||
194 | /* | 197 | /* |
diff --git a/arch/sh/boards/mach-x3proto/setup.c b/arch/sh/boards/mach-x3proto/setup.c index e284592fd42a..102bf56befb4 100644 --- a/arch/sh/boards/mach-x3proto/setup.c +++ b/arch/sh/boards/mach-x3proto/setup.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/usb/r8a66597.h> | 19 | #include <linux/usb/r8a66597.h> |
20 | #include <linux/usb/m66592.h> | 20 | #include <linux/usb/m66592.h> |
21 | #include <asm/ilsel.h> | 21 | #include <asm/ilsel.h> |
22 | #include <asm/smp-ops.h> | ||
22 | 23 | ||
23 | static struct resource heartbeat_resources[] = { | 24 | static struct resource heartbeat_resources[] = { |
24 | [0] = { | 25 | [0] = { |
@@ -152,7 +153,13 @@ static void __init x3proto_init_irq(void) | |||
152 | __raw_writel(__raw_readl(0xfe410000) | (1 << 21), 0xfe410000); | 153 | __raw_writel(__raw_readl(0xfe410000) | (1 << 21), 0xfe410000); |
153 | } | 154 | } |
154 | 155 | ||
156 | static void __init x3proto_setup(char **cmdline_p) | ||
157 | { | ||
158 | register_smp_ops(&shx3_smp_ops); | ||
159 | } | ||
160 | |||
155 | static struct sh_machine_vector mv_x3proto __initmv = { | 161 | static struct sh_machine_vector mv_x3proto __initmv = { |
156 | .mv_name = "x3proto", | 162 | .mv_name = "x3proto", |
163 | .mv_setup = x3proto_setup, | ||
157 | .mv_init_irq = x3proto_init_irq, | 164 | .mv_init_irq = x3proto_init_irq, |
158 | }; | 165 | }; |
diff --git a/arch/sh/include/asm/smp-ops.h b/arch/sh/include/asm/smp-ops.h new file mode 100644 index 000000000000..0581b2a4c8ce --- /dev/null +++ b/arch/sh/include/asm/smp-ops.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #ifndef __ASM_SH_SMP_OPS_H | ||
2 | #define __ASM_SH_SMP_OPS_H | ||
3 | |||
4 | struct plat_smp_ops { | ||
5 | void (*smp_setup)(void); | ||
6 | unsigned int (*smp_processor_id)(void); | ||
7 | void (*prepare_cpus)(unsigned int max_cpus); | ||
8 | void (*start_cpu)(unsigned int cpu, unsigned long entry_point); | ||
9 | void (*send_ipi)(unsigned int cpu, unsigned int message); | ||
10 | }; | ||
11 | |||
12 | extern struct plat_smp_ops shx3_smp_ops; | ||
13 | |||
14 | #ifdef CONFIG_SMP | ||
15 | |||
16 | static inline void plat_smp_setup(void) | ||
17 | { | ||
18 | extern struct plat_smp_ops *mp_ops; /* private */ | ||
19 | |||
20 | BUG_ON(!mp_ops); | ||
21 | mp_ops->smp_setup(); | ||
22 | } | ||
23 | |||
24 | extern void register_smp_ops(struct plat_smp_ops *ops); | ||
25 | |||
26 | #else | ||
27 | |||
28 | static inline void plat_smp_setup(void) | ||
29 | { | ||
30 | /* UP, nothing to do ... */ | ||
31 | } | ||
32 | |||
33 | static inline void register_smp_ops(struct plat_smp_ops *ops) | ||
34 | { | ||
35 | } | ||
36 | |||
37 | #endif /* CONFIG_SMP */ | ||
38 | |||
39 | #endif /* __ASM_SH_SMP_OPS_H */ | ||
diff --git a/arch/sh/include/asm/smp.h b/arch/sh/include/asm/smp.h index 53ef26ced75f..7f13d46ec8d7 100644 --- a/arch/sh/include/asm/smp.h +++ b/arch/sh/include/asm/smp.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/bitops.h> | 4 | #include <linux/bitops.h> |
5 | #include <linux/cpumask.h> | 5 | #include <linux/cpumask.h> |
6 | #include <asm/smp-ops.h> | ||
6 | 7 | ||
7 | #ifdef CONFIG_SMP | 8 | #ifdef CONFIG_SMP |
8 | 9 | ||
@@ -11,7 +12,6 @@ | |||
11 | #include <asm/current.h> | 12 | #include <asm/current.h> |
12 | 13 | ||
13 | #define raw_smp_processor_id() (current_thread_info()->cpu) | 14 | #define raw_smp_processor_id() (current_thread_info()->cpu) |
14 | #define hard_smp_processor_id() plat_smp_processor_id() | ||
15 | 15 | ||
16 | /* Map from cpu id to sequential logical cpu number. */ | 16 | /* Map from cpu id to sequential logical cpu number. */ |
17 | extern int __cpu_number_map[NR_CPUS]; | 17 | extern int __cpu_number_map[NR_CPUS]; |
@@ -36,15 +36,19 @@ void smp_timer_broadcast(const struct cpumask *mask); | |||
36 | void local_timer_interrupt(void); | 36 | void local_timer_interrupt(void); |
37 | void local_timer_setup(unsigned int cpu); | 37 | void local_timer_setup(unsigned int cpu); |
38 | 38 | ||
39 | void plat_smp_setup(void); | ||
40 | void plat_prepare_cpus(unsigned int max_cpus); | ||
41 | int plat_smp_processor_id(void); | ||
42 | void plat_start_cpu(unsigned int cpu, unsigned long entry_point); | ||
43 | void plat_send_ipi(unsigned int cpu, unsigned int message); | ||
44 | |||
45 | void arch_send_call_function_single_ipi(int cpu); | 39 | void arch_send_call_function_single_ipi(int cpu); |
46 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); | 40 | extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); |
47 | 41 | ||
42 | static inline int hard_smp_processor_id(void) | ||
43 | { | ||
44 | extern struct plat_smp_ops *mp_ops; /* private */ | ||
45 | |||
46 | if (!mp_ops) | ||
47 | return 0; /* boot CPU */ | ||
48 | |||
49 | return mp_ops->smp_processor_id(); | ||
50 | } | ||
51 | |||
48 | #else | 52 | #else |
49 | 53 | ||
50 | #define hard_smp_processor_id() (0) | 54 | #define hard_smp_processor_id() (0) |
diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index c98b4574c44e..5c5d50ccbfcd 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * SH-X3 SMP | 2 | * SH-X3 SMP |
3 | * | 3 | * |
4 | * Copyright (C) 2007 - 2008 Paul Mundt | 4 | * Copyright (C) 2007 - 2010 Paul Mundt |
5 | * Copyright (C) 2007 Magnus Damm | 5 | * Copyright (C) 2007 Magnus Damm |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -37,7 +37,7 @@ static irqreturn_t ipi_interrupt_handler(int irq, void *arg) | |||
37 | return IRQ_HANDLED; | 37 | return IRQ_HANDLED; |
38 | } | 38 | } |
39 | 39 | ||
40 | void __init plat_smp_setup(void) | 40 | static void shx3_smp_setup(void) |
41 | { | 41 | { |
42 | unsigned int cpu = 0; | 42 | unsigned int cpu = 0; |
43 | int i, num; | 43 | int i, num; |
@@ -63,7 +63,7 @@ void __init plat_smp_setup(void) | |||
63 | printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); | 63 | printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); |
64 | } | 64 | } |
65 | 65 | ||
66 | void __init plat_prepare_cpus(unsigned int max_cpus) | 66 | static void shx3_prepare_cpus(unsigned int max_cpus) |
67 | { | 67 | { |
68 | int i; | 68 | int i; |
69 | 69 | ||
@@ -76,7 +76,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus) | |||
76 | IRQF_DISABLED | IRQF_PERCPU, "IPI", (void *)(long)i); | 76 | IRQF_DISABLED | IRQF_PERCPU, "IPI", (void *)(long)i); |
77 | } | 77 | } |
78 | 78 | ||
79 | void plat_start_cpu(unsigned int cpu, unsigned long entry_point) | 79 | static void shx3_start_cpu(unsigned int cpu, unsigned long entry_point) |
80 | { | 80 | { |
81 | if (__in_29bit_mode()) | 81 | if (__in_29bit_mode()) |
82 | __raw_writel(entry_point, RESET_REG(cpu)); | 82 | __raw_writel(entry_point, RESET_REG(cpu)); |
@@ -93,12 +93,12 @@ void plat_start_cpu(unsigned int cpu, unsigned long entry_point) | |||
93 | __raw_writel(STBCR_RESET | STBCR_LTSLP, STBCR_REG(cpu)); | 93 | __raw_writel(STBCR_RESET | STBCR_LTSLP, STBCR_REG(cpu)); |
94 | } | 94 | } |
95 | 95 | ||
96 | int plat_smp_processor_id(void) | 96 | static unsigned int shx3_smp_processor_id(void) |
97 | { | 97 | { |
98 | return __raw_readl(0xff000048); /* CPIDR */ | 98 | return __raw_readl(0xff000048); /* CPIDR */ |
99 | } | 99 | } |
100 | 100 | ||
101 | void plat_send_ipi(unsigned int cpu, unsigned int message) | 101 | static void shx3_send_ipi(unsigned int cpu, unsigned int message) |
102 | { | 102 | { |
103 | unsigned long addr = 0xfe410070 + (cpu * 4); | 103 | unsigned long addr = 0xfe410070 + (cpu * 4); |
104 | 104 | ||
@@ -106,3 +106,11 @@ void plat_send_ipi(unsigned int cpu, unsigned int message) | |||
106 | 106 | ||
107 | __raw_writel(1 << (message << 2), addr); /* C0INTICI..CnINTICI */ | 107 | __raw_writel(1 << (message << 2), addr); /* C0INTICI..CnINTICI */ |
108 | } | 108 | } |
109 | |||
110 | struct plat_smp_ops shx3_smp_ops = { | ||
111 | .smp_setup = shx3_smp_setup, | ||
112 | .prepare_cpus = shx3_prepare_cpus, | ||
113 | .start_cpu = shx3_start_cpu, | ||
114 | .smp_processor_id = shx3_smp_processor_id, | ||
115 | .send_ipi = shx3_send_ipi, | ||
116 | }; | ||
diff --git a/arch/sh/kernel/localtimer.c b/arch/sh/kernel/localtimer.c index 0b04e7d4a9b9..865a2f1029b1 100644 --- a/arch/sh/kernel/localtimer.c +++ b/arch/sh/kernel/localtimer.c | |||
@@ -44,7 +44,7 @@ static void dummy_timer_set_mode(enum clock_event_mode mode, | |||
44 | { | 44 | { |
45 | } | 45 | } |
46 | 46 | ||
47 | void __cpuinit local_timer_setup(unsigned int cpu) | 47 | void local_timer_setup(unsigned int cpu) |
48 | { | 48 | { |
49 | struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); | 49 | struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); |
50 | 50 | ||
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 8870d6ba64bf..29155384d5a8 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -459,9 +459,7 @@ void __init setup_arch(char **cmdline_p) | |||
459 | if (likely(sh_mv.mv_setup)) | 459 | if (likely(sh_mv.mv_setup)) |
460 | sh_mv.mv_setup(cmdline_p); | 460 | sh_mv.mv_setup(cmdline_p); |
461 | 461 | ||
462 | #ifdef CONFIG_SMP | ||
463 | plat_smp_setup(); | 462 | plat_smp_setup(); |
464 | #endif | ||
465 | } | 463 | } |
466 | 464 | ||
467 | /* processor boot mode configuration */ | 465 | /* processor boot mode configuration */ |
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 002cc612deef..2f348fda0159 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SMP support for the SuperH processors. | 4 | * SMP support for the SuperH processors. |
5 | * | 5 | * |
6 | * Copyright (C) 2002 - 2008 Paul Mundt | 6 | * Copyright (C) 2002 - 2010 Paul Mundt |
7 | * Copyright (C) 2006 - 2007 Akio Idehara | 7 | * Copyright (C) 2006 - 2007 Akio Idehara |
8 | * | 8 | * |
9 | * This file is subject to the terms and conditions of the GNU General Public | 9 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -31,6 +31,16 @@ | |||
31 | int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ | 31 | int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ |
32 | int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ | 32 | int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ |
33 | 33 | ||
34 | struct plat_smp_ops *mp_ops = NULL; | ||
35 | |||
36 | void __cpuinit register_smp_ops(struct plat_smp_ops *ops) | ||
37 | { | ||
38 | if (mp_ops) | ||
39 | printk(KERN_WARNING "Overriding previously set SMP ops\n"); | ||
40 | |||
41 | mp_ops = ops; | ||
42 | } | ||
43 | |||
34 | static inline void __init smp_store_cpu_info(unsigned int cpu) | 44 | static inline void __init smp_store_cpu_info(unsigned int cpu) |
35 | { | 45 | { |
36 | struct sh_cpuinfo *c = cpu_data + cpu; | 46 | struct sh_cpuinfo *c = cpu_data + cpu; |
@@ -46,7 +56,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
46 | 56 | ||
47 | init_new_context(current, &init_mm); | 57 | init_new_context(current, &init_mm); |
48 | current_thread_info()->cpu = cpu; | 58 | current_thread_info()->cpu = cpu; |
49 | plat_prepare_cpus(max_cpus); | 59 | mp_ops->prepare_cpus(max_cpus); |
50 | 60 | ||
51 | #ifndef CONFIG_HOTPLUG_CPU | 61 | #ifndef CONFIG_HOTPLUG_CPU |
52 | init_cpu_present(&cpu_possible_map); | 62 | init_cpu_present(&cpu_possible_map); |
@@ -127,7 +137,7 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
127 | (unsigned long)&stack_start + sizeof(stack_start)); | 137 | (unsigned long)&stack_start + sizeof(stack_start)); |
128 | wmb(); | 138 | wmb(); |
129 | 139 | ||
130 | plat_start_cpu(cpu, (unsigned long)_stext); | 140 | mp_ops->start_cpu(cpu, (unsigned long)_stext); |
131 | 141 | ||
132 | timeout = jiffies + HZ; | 142 | timeout = jiffies + HZ; |
133 | while (time_before(jiffies, timeout)) { | 143 | while (time_before(jiffies, timeout)) { |
@@ -159,7 +169,7 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
159 | 169 | ||
160 | void smp_send_reschedule(int cpu) | 170 | void smp_send_reschedule(int cpu) |
161 | { | 171 | { |
162 | plat_send_ipi(cpu, SMP_MSG_RESCHEDULE); | 172 | mp_ops->send_ipi(cpu, SMP_MSG_RESCHEDULE); |
163 | } | 173 | } |
164 | 174 | ||
165 | void smp_send_stop(void) | 175 | void smp_send_stop(void) |
@@ -172,12 +182,12 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask) | |||
172 | int cpu; | 182 | int cpu; |
173 | 183 | ||
174 | for_each_cpu(cpu, mask) | 184 | for_each_cpu(cpu, mask) |
175 | plat_send_ipi(cpu, SMP_MSG_FUNCTION); | 185 | mp_ops->send_ipi(cpu, SMP_MSG_FUNCTION); |
176 | } | 186 | } |
177 | 187 | ||
178 | void arch_send_call_function_single_ipi(int cpu) | 188 | void arch_send_call_function_single_ipi(int cpu) |
179 | { | 189 | { |
180 | plat_send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE); | 190 | mp_ops->send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE); |
181 | } | 191 | } |
182 | 192 | ||
183 | void smp_timer_broadcast(const struct cpumask *mask) | 193 | void smp_timer_broadcast(const struct cpumask *mask) |
@@ -185,7 +195,7 @@ void smp_timer_broadcast(const struct cpumask *mask) | |||
185 | int cpu; | 195 | int cpu; |
186 | 196 | ||
187 | for_each_cpu(cpu, mask) | 197 | for_each_cpu(cpu, mask) |
188 | plat_send_ipi(cpu, SMP_MSG_TIMER); | 198 | mp_ops->send_ipi(cpu, SMP_MSG_TIMER); |
189 | } | 199 | } |
190 | 200 | ||
191 | static void ipi_timer(void) | 201 | static void ipi_timer(void) |