diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b82828e768ad4570595a99d0f85e3f77c2e55582..a0aeecc33c739434113ee1cc25813d02063fdbba 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -33,6 +33,11 @@ config GENERIC_CLOCKEVENTS
 	bool
 	default n
 
+config GENERIC_CLOCKEVENTS_BROADCAST
+	bool
+	depends on GENERIC_CLOCKEVENTS
+	default y if SMP && !LOCAL_TIMERS
+
 config MMU
 	bool
 	default y
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index aef6f9ab900ebebe3bd73ee4cbb045b4b601767f..e9dfbab46cb65ef0a6e85d8aa90a9cc0cc0f1522 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -290,6 +290,11 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
 	local_irq_enable();
 	local_fiq_enable();
 
+	/*
+	 * Setup local timer for this CPU.
+	 */
+	local_timer_setup(cpu);
+
 	calibrate_delay();
 
 	smp_store_cpu_info(cpu);
@@ -299,11 +304,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
 	 */
 	cpu_set(cpu, cpu_online_map);
 
-	/*
-	 * Setup local timer for this CPU.
-	 */
-	local_timer_setup(cpu);
-
 	/*
 	 * OK, it's off to the idle thread for us
 	 */
diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile
index 36e76ba937fc031286eeb4fa7acf46b13e37cd64..ca1e390c3c28795f3873bc8249e3eb3c74a8f078 100644
--- a/arch/arm/mach-realview/Makefile
+++ b/arch/arm/mach-realview/Makefile
@@ -4,6 +4,5 @@
 
 obj-y					:= core.o clock.o
 obj-$(CONFIG_MACH_REALVIEW_EB)		+= realview_eb.o
-obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
+obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o localtimer.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
-obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 6c68deed84dc1e5eae9d6670c7e5a707a6652b6c..8cabfec31da2769fdac4d17d336095afa55117ba 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)
 }
 
 /*
- * Set up timer interrupt, and return the current time in seconds.
+ * Set up the clock source and clock events devices
  */
 static void __init realview_timer_init(void)
 {
 	u32 val;
 
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+	/*
+	 * The dummy clock device has to be registered before the main device
+	 * so that the latter will broadcast the clock events
+	 */
+	local_timer_setup(smp_processor_id());
+#endif
+
 	/* 
 	 * set clock frequency: 
 	 *	REALVIEW_REFCLK is 32KHz
diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c
index c7bdf04ab094d1f82f2afbb52c204154cf0dfef4..529eb6979e614cab73b9cf61b2d6cc968cc69ea9 100644
--- a/arch/arm/mach-realview/localtimer.c
+++ b/arch/arm/mach-realview/localtimer.c
@@ -14,6 +14,8 @@
 #include <linux/device.h>
 #include <linux/smp.h>
 #include <linux/jiffies.h>
+#include <linux/percpu.h>
+#include <linux/clockchips.h>
 
 #include <asm/mach/time.h>
 #include <asm/hardware/arm_twd.h>
@@ -25,6 +27,20 @@
 #define TWD_BASE(cpu)	(__io_address(REALVIEW_TWD_BASE) + \
 			 ((cpu) * REALVIEW_TWD_SIZE))
 
+static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
+
+/*
+ * Used on SMP for either the local timer or IPI_TIMER
+ */
+void local_timer_interrupt(void)
+{
+	struct clock_event_device *clk = &__get_cpu_var(local_clockevent);
+
+	clk->event_handler(clk);
+}
+
+#ifdef CONFIG_LOCAL_TIMERS
+
 static unsigned long mpcore_timer_rate;
 
 /*
@@ -127,3 +143,26 @@ void __cpuexit local_timer_stop(unsigned int cpu)
 {
 	__raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL);
 }
+
+#else	/* CONFIG_LOCAL_TIMERS */
+
+static void dummy_timer_set_mode(enum clock_event_mode mode,
+				 struct clock_event_device *clk)
+{
+}
+
+void __cpuinit local_timer_setup(unsigned int cpu)
+{
+	struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
+
+	clk->name		= "dummy_timer";
+	clk->features		= CLOCK_EVT_FEAT_DUMMY;
+	clk->rating		= 200;
+	clk->set_mode		= dummy_timer_set_mode;
+	clk->broadcast		= smp_timer_broadcast;
+	clk->cpumask		= cpumask_of_cpu(cpu);
+
+	clockevents_register_device(clk);
+}
+
+#endif	/* !CONFIG_LOCAL_TIMERS */
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index fce3596f9950a6aea5d8489d9d674a99759ad7b0..bb5eaa48520d2d595a7529678e69ed1aff34c0ca 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)
 	if (max_cpus > ncores)
 		max_cpus = ncores;
 
+#ifdef CONFIG_LOCAL_TIMERS
 	/*
-	 * Enable the local timer for primary CPU
+	 * Enable the local timer for primary CPU. If the device is
+	 * dummy (!CONFIG_LOCAL_TIMERS), it was already registers in
+	 * realview_timer_init
 	 */
 	local_timer_setup(cpu);
+#endif
 
 	/*
 	 * 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 1f7c51a1886d524e738613479ee2622d8df61be7..af99636db400e7e8cfbe81956faa1d84f11ebdf2 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);
 extern void local_timer_interrupt(void);
 
 #ifdef CONFIG_LOCAL_TIMERS
-/*
- * Setup a local timer interrupt for a CPU.
- */
-extern void local_timer_setup(unsigned int cpu);
 
 /*
  * Stop a local timer interrupt.
@@ -124,16 +120,17 @@ extern int local_timer_ack(void);
 
 #else
 
-static inline void local_timer_setup(unsigned int cpu)
-{
-}
-
 static inline void local_timer_stop(unsigned int cpu)
 {
 }
 
 #endif
 
+/*
+ * Setup a local timer interrupt for a CPU.
+ */
+extern void local_timer_setup(unsigned int cpu);
+
 /*
  * show local interrupt info
  */