openrisc: add tick timer multi-core sync logic
[sfrench/cifs-2.6.git] / arch / openrisc / kernel / time.c
index 687c11d048d7c2493c7d302e3c0cd053f99ef360..6baecea270801ae56ab1ef39383442f846d1999a 100644 (file)
 
 #include <asm/cpuinfo.h>
 
-static int openrisc_timer_set_next_event(unsigned long delta,
-                                        struct clock_event_device *dev)
+/* Test the timer ticks to count, used in sync routine */
+inline void openrisc_timer_set(unsigned long count)
+{
+       mtspr(SPR_TTCR, count);
+}
+
+/* Set the timer to trigger in delta cycles */
+inline void openrisc_timer_set_next(unsigned long delta)
 {
        u32 c;
 
@@ -44,7 +50,12 @@ static int openrisc_timer_set_next_event(unsigned long delta,
         * Keep timer in continuous mode always.
         */
        mtspr(SPR_TTMR, SPR_TTMR_CR | SPR_TTMR_IE | c);
+}
 
+static int openrisc_timer_set_next_event(unsigned long delta,
+                                        struct clock_event_device *dev)
+{
+       openrisc_timer_set_next(delta);
        return 0;
 }
 
@@ -53,13 +64,32 @@ static int openrisc_timer_set_next_event(unsigned long delta,
  * timers) we cannot enable the PERIODIC feature.  The tick timer can run using
  * one-shot events, so no problem.
  */
+DEFINE_PER_CPU(struct clock_event_device, clockevent_openrisc_timer);
 
-static struct clock_event_device clockevent_openrisc_timer = {
-       .name = "openrisc_timer_clockevent",
-       .features = CLOCK_EVT_FEAT_ONESHOT,
-       .rating = 300,
-       .set_next_event = openrisc_timer_set_next_event,
-};
+void openrisc_clockevent_init(void)
+{
+       unsigned int cpu = smp_processor_id();
+       struct clock_event_device *evt =
+               &per_cpu(clockevent_openrisc_timer, cpu);
+       struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[cpu];
+
+       mtspr(SPR_TTMR, SPR_TTMR_CR);
+
+#ifdef CONFIG_SMP
+       evt->broadcast = tick_broadcast;
+#endif
+       evt->name = "openrisc_timer_clockevent",
+       evt->features = CLOCK_EVT_FEAT_ONESHOT,
+       evt->rating = 300,
+       evt->set_next_event = openrisc_timer_set_next_event,
+
+       evt->cpumask = cpumask_of(cpu);
+
+       /* We only have 28 bits */
+       clockevents_config_and_register(evt, cpuinfo->clock_frequency,
+                                       100, 0x0fffffff);
+
+}
 
 static inline void timer_ack(void)
 {
@@ -83,7 +113,9 @@ static inline void timer_ack(void)
 irqreturn_t __irq_entry timer_interrupt(struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
-       struct clock_event_device *evt = &clockevent_openrisc_timer;
+       unsigned int cpu = smp_processor_id();
+       struct clock_event_device *evt =
+               &per_cpu(clockevent_openrisc_timer, cpu);
 
        timer_ack();
 
@@ -99,24 +131,12 @@ irqreturn_t __irq_entry timer_interrupt(struct pt_regs *regs)
        return IRQ_HANDLED;
 }
 
-static __init void openrisc_clockevent_init(void)
-{
-       clockevent_openrisc_timer.cpumask = cpumask_of(0);
-
-       /* We only have 28 bits */
-       clockevents_config_and_register(&clockevent_openrisc_timer,
-                                       cpuinfo.clock_frequency,
-                                       100, 0x0fffffff);
-
-}
-
 /**
  * Clocksource: Based on OpenRISC timer/counter
  *
  * This sets up the OpenRISC Tick Timer as a clock source.  The tick timer
  * is 32 bits wide and runs at the CPU clock frequency.
  */
-
 static u64 openrisc_timer_read(struct clocksource *cs)
 {
        return (u64) mfspr(SPR_TTCR);
@@ -132,7 +152,9 @@ static struct clocksource openrisc_timer = {
 
 static int __init openrisc_timer_init(void)
 {
-       if (clocksource_register_hz(&openrisc_timer, cpuinfo.clock_frequency))
+       struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[smp_processor_id()];
+
+       if (clocksource_register_hz(&openrisc_timer, cpuinfo->clock_frequency))
                panic("failed to register clocksource");
 
        /* Enable the incrementer: 'continuous' mode with interrupt disabled */