diff options
-rw-r--r-- | arch/arm/Kconfig | 5 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-realview/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-realview/core.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-realview/localtimer.c | 39 | ||||
-rw-r--r-- | arch/arm/mach-realview/platsmp.c | 6 | ||||
-rw-r--r-- | include/asm-arm/smp.h | 13 |
7 files changed, 69 insertions, 17 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index b82828e768ad..a0aeecc33c73 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -33,6 +33,11 @@ config GENERIC_CLOCKEVENTS | |||
33 | bool | 33 | bool |
34 | default n | 34 | default n |
35 | 35 | ||
36 | config GENERIC_CLOCKEVENTS_BROADCAST | ||
37 | bool | ||
38 | depends on GENERIC_CLOCKEVENTS | ||
39 | default y if SMP && !LOCAL_TIMERS | ||
40 | |||
36 | config MMU | 41 | config MMU |
37 | bool | 42 | bool |
38 | default y | 43 | default y |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index aef6f9ab900e..e9dfbab46cb6 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -290,6 +290,11 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
290 | local_irq_enable(); | 290 | local_irq_enable(); |
291 | local_fiq_enable(); | 291 | local_fiq_enable(); |
292 | 292 | ||
293 | /* | ||
294 | * Setup local timer for this CPU. | ||
295 | */ | ||
296 | local_timer_setup(cpu); | ||
297 | |||
293 | calibrate_delay(); | 298 | calibrate_delay(); |
294 | 299 | ||
295 | smp_store_cpu_info(cpu); | 300 | smp_store_cpu_info(cpu); |
@@ -300,11 +305,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
300 | cpu_set(cpu, cpu_online_map); | 305 | cpu_set(cpu, cpu_online_map); |
301 | 306 | ||
302 | /* | 307 | /* |
303 | * Setup local timer for this CPU. | ||
304 | */ | ||
305 | local_timer_setup(cpu); | ||
306 | |||
307 | /* | ||
308 | * OK, it's off to the idle thread for us | 308 | * OK, it's off to the idle thread for us |
309 | */ | 309 | */ |
310 | cpu_idle(); | 310 | cpu_idle(); |
diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index 36e76ba937fc..ca1e390c3c28 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile | |||
@@ -4,6 +4,5 @@ | |||
4 | 4 | ||
5 | obj-y := core.o clock.o | 5 | obj-y := core.o clock.o |
6 | obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o | 6 | obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o |
7 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o | 7 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o |
8 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 8 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
9 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o | ||
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 6c68deed84dc..8cabfec31da2 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c | |||
@@ -596,12 +596,20 @@ static void __init realview_clocksource_init(void) | |||
596 | } | 596 | } |
597 | 597 | ||
598 | /* | 598 | /* |
599 | * Set up timer interrupt, and return the current time in seconds. | 599 | * Set up the clock source and clock events devices |
600 | */ | 600 | */ |
601 | static void __init realview_timer_init(void) | 601 | static void __init realview_timer_init(void) |
602 | { | 602 | { |
603 | u32 val; | 603 | u32 val; |
604 | 604 | ||
605 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | ||
606 | /* | ||
607 | * The dummy clock device has to be registered before the main device | ||
608 | * so that the latter will broadcast the clock events | ||
609 | */ | ||
610 | local_timer_setup(smp_processor_id()); | ||
611 | #endif | ||
612 | |||
605 | /* | 613 | /* |
606 | * set clock frequency: | 614 | * set clock frequency: |
607 | * REALVIEW_REFCLK is 32KHz | 615 | * REALVIEW_REFCLK is 32KHz |
diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c index c7bdf04ab094..529eb6979e61 100644 --- a/arch/arm/mach-realview/localtimer.c +++ b/arch/arm/mach-realview/localtimer.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/smp.h> | 15 | #include <linux/smp.h> |
16 | #include <linux/jiffies.h> | 16 | #include <linux/jiffies.h> |
17 | #include <linux/percpu.h> | ||
18 | #include <linux/clockchips.h> | ||
17 | 19 | ||
18 | #include <asm/mach/time.h> | 20 | #include <asm/mach/time.h> |
19 | #include <asm/hardware/arm_twd.h> | 21 | #include <asm/hardware/arm_twd.h> |
@@ -25,6 +27,20 @@ | |||
25 | #define TWD_BASE(cpu) (__io_address(REALVIEW_TWD_BASE) + \ | 27 | #define TWD_BASE(cpu) (__io_address(REALVIEW_TWD_BASE) + \ |
26 | ((cpu) * REALVIEW_TWD_SIZE)) | 28 | ((cpu) * REALVIEW_TWD_SIZE)) |
27 | 29 | ||
30 | static DEFINE_PER_CPU(struct clock_event_device, local_clockevent); | ||
31 | |||
32 | /* | ||
33 | * Used on SMP for either the local timer or IPI_TIMER | ||
34 | */ | ||
35 | void local_timer_interrupt(void) | ||
36 | { | ||
37 | struct clock_event_device *clk = &__get_cpu_var(local_clockevent); | ||
38 | |||
39 | clk->event_handler(clk); | ||
40 | } | ||
41 | |||
42 | #ifdef CONFIG_LOCAL_TIMERS | ||
43 | |||
28 | static unsigned long mpcore_timer_rate; | 44 | static unsigned long mpcore_timer_rate; |
29 | 45 | ||
30 | /* | 46 | /* |
@@ -127,3 +143,26 @@ void __cpuexit local_timer_stop(unsigned int cpu) | |||
127 | { | 143 | { |
128 | __raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL); | 144 | __raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL); |
129 | } | 145 | } |
146 | |||
147 | #else /* CONFIG_LOCAL_TIMERS */ | ||
148 | |||
149 | static void dummy_timer_set_mode(enum clock_event_mode mode, | ||
150 | struct clock_event_device *clk) | ||
151 | { | ||
152 | } | ||
153 | |||
154 | void __cpuinit local_timer_setup(unsigned int cpu) | ||
155 | { | ||
156 | struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); | ||
157 | |||
158 | clk->name = "dummy_timer"; | ||
159 | clk->features = CLOCK_EVT_FEAT_DUMMY; | ||
160 | clk->rating = 200; | ||
161 | clk->set_mode = dummy_timer_set_mode; | ||
162 | clk->broadcast = smp_timer_broadcast; | ||
163 | clk->cpumask = cpumask_of_cpu(cpu); | ||
164 | |||
165 | clockevents_register_device(clk); | ||
166 | } | ||
167 | |||
168 | #endif /* !CONFIG_LOCAL_TIMERS */ | ||
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index fce3596f9950..bb5eaa48520d 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c | |||
@@ -187,10 +187,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
187 | if (max_cpus > ncores) | 187 | if (max_cpus > ncores) |
188 | max_cpus = ncores; | 188 | max_cpus = ncores; |
189 | 189 | ||
190 | #ifdef CONFIG_LOCAL_TIMERS | ||
190 | /* | 191 | /* |
191 | * Enable the local timer for primary CPU | 192 | * Enable the local timer for primary CPU. If the device is |
193 | * dummy (!CONFIG_LOCAL_TIMERS), it was already registers in | ||
194 | * realview_timer_init | ||
192 | */ | 195 | */ |
193 | local_timer_setup(cpu); | 196 | local_timer_setup(cpu); |
197 | #endif | ||
194 | 198 | ||
195 | /* | 199 | /* |
196 | * Initialise the present map, which describes the set of CPUs | 200 | * Initialise the present map, which describes the set of CPUs |
diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h index 1f7c51a1886d..af99636db400 100644 --- a/include/asm-arm/smp.h +++ b/include/asm-arm/smp.h | |||
@@ -107,10 +107,6 @@ extern void platform_cpu_enable(unsigned int cpu); | |||
107 | extern void local_timer_interrupt(void); | 107 | extern void local_timer_interrupt(void); |
108 | 108 | ||
109 | #ifdef CONFIG_LOCAL_TIMERS | 109 | #ifdef CONFIG_LOCAL_TIMERS |
110 | /* | ||
111 | * Setup a local timer interrupt for a CPU. | ||
112 | */ | ||
113 | extern void local_timer_setup(unsigned int cpu); | ||
114 | 110 | ||
115 | /* | 111 | /* |
116 | * Stop a local timer interrupt. | 112 | * Stop a local timer interrupt. |
@@ -124,10 +120,6 @@ extern int local_timer_ack(void); | |||
124 | 120 | ||
125 | #else | 121 | #else |
126 | 122 | ||
127 | static inline void local_timer_setup(unsigned int cpu) | ||
128 | { | ||
129 | } | ||
130 | |||
131 | static inline void local_timer_stop(unsigned int cpu) | 123 | static inline void local_timer_stop(unsigned int cpu) |
132 | { | 124 | { |
133 | } | 125 | } |
@@ -135,6 +127,11 @@ static inline void local_timer_stop(unsigned int cpu) | |||
135 | #endif | 127 | #endif |
136 | 128 | ||
137 | /* | 129 | /* |
130 | * Setup a local timer interrupt for a CPU. | ||
131 | */ | ||
132 | extern void local_timer_setup(unsigned int cpu); | ||
133 | |||
134 | /* | ||
138 | * show local interrupt info | 135 | * show local interrupt info |
139 | */ | 136 | */ |
140 | extern void show_local_irqs(struct seq_file *); | 137 | extern void show_local_irqs(struct seq_file *); |