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
*/