bool
        default n
 
+config GENERIC_CLOCKEVENTS_BROADCAST
+       bool
+       depends on GENERIC_CLOCKEVENTS
+       default y if SMP && !LOCAL_TIMERS
+
 config MMU
        bool
        default y
 
        local_irq_enable();
        local_fiq_enable();
 
+       /*
+        * Setup local timer for this CPU.
+        */
+       local_timer_setup(cpu);
+
        calibrate_delay();
 
        smp_store_cpu_info(cpu);
         */
        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
         */
 
 
 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
 
 }
 
 /*
- * 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
 
 #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>
 #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;
 
 /*
 {
        __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 */
 
        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
 
 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.
 
 #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
  */