aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig5
-rw-r--r--arch/arm/kernel/smp.c10
-rw-r--r--arch/arm/mach-realview/Makefile3
-rw-r--r--arch/arm/mach-realview/core.c10
-rw-r--r--arch/arm/mach-realview/localtimer.c39
-rw-r--r--arch/arm/mach-realview/platsmp.c6
-rw-r--r--include/asm-arm/smp.h13
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
36config GENERIC_CLOCKEVENTS_BROADCAST
37 bool
38 depends on GENERIC_CLOCKEVENTS
39 default y if SMP && !LOCAL_TIMERS
40
36config MMU 41config 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
5obj-y := core.o clock.o 5obj-y := core.o clock.o
6obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o 6obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o
7obj-$(CONFIG_SMP) += platsmp.o headsmp.o 7obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o
8obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 8obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
9obj-$(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 */
601static void __init realview_timer_init(void) 601static 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
30static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
31
32/*
33 * Used on SMP for either the local timer or IPI_TIMER
34 */
35void 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
28static unsigned long mpcore_timer_rate; 44static 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
149static void dummy_timer_set_mode(enum clock_event_mode mode,
150 struct clock_event_device *clk)
151{
152}
153
154void __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);
107extern void local_timer_interrupt(void); 107extern 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 */
113extern 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
127static inline void local_timer_setup(unsigned int cpu)
128{
129}
130
131static inline void local_timer_stop(unsigned int cpu) 123static 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 */
132extern void local_timer_setup(unsigned int cpu);
133
134/*
138 * show local interrupt info 135 * show local interrupt info
139 */ 136 */
140extern void show_local_irqs(struct seq_file *); 137extern void show_local_irqs(struct seq_file *);