]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/arm/mach-omap1/time.c
ARM: OMAP: Remove MPU-timer based sched_clock()
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap1 / time.c
index 64fefff5d99f61ac5348526df6e304f926d1ae08..c189a2d634e50cbe71dd45a7a7e28e8621e0058a 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/clocksource.h>
+#include <linux/clockchips.h>
 
 #include <asm/system.h>
 #include <asm/hardware.h>
@@ -102,15 +103,40 @@ static inline unsigned long omap_mpu_timer_read(int nr)
        return timer->read_tim;
 }
 
-static inline void omap_mpu_timer_start(int nr, unsigned long load_val)
+static inline void omap_mpu_set_autoreset(int nr)
 {
        volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
 
+       timer->cntl = timer->cntl | MPU_TIMER_AR;
+}
+
+static inline void omap_mpu_remove_autoreset(int nr)
+{
+       volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
+
+       timer->cntl = timer->cntl & ~MPU_TIMER_AR;
+}
+
+static inline void omap_mpu_timer_start(int nr, unsigned long load_val,
+                                       int autoreset)
+{
+       volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
+       unsigned int timerflags = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_ST);
+
+       if (autoreset) timerflags |= MPU_TIMER_AR;
+
        timer->cntl = MPU_TIMER_CLOCK_ENABLE;
        udelay(1);
        timer->load_tim = load_val;
         udelay(1);
-       timer->cntl = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_AR | MPU_TIMER_ST);
+       timer->cntl = timerflags;
+}
+
+static inline void omap_mpu_timer_stop(int nr)
+{
+       volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
+
+       timer->cntl &= ~MPU_TIMER_ST;
 }
 
 /*
@@ -118,19 +144,51 @@ static inline void omap_mpu_timer_start(int nr, unsigned long load_val)
  * MPU timer 1 ... count down to zero, interrupt, reload
  * ---------------------------------------------------------------------------
  */
+static int omap_mpu_set_next_event(unsigned long cycles,
+                                  struct clock_event_device *evt)
+{
+       omap_mpu_timer_start(0, cycles, 0);
+       return 0;
+}
+
+static void omap_mpu_set_mode(enum clock_event_mode mode,
+                             struct clock_event_device *evt)
+{
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               omap_mpu_set_autoreset(0);
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+               omap_mpu_timer_stop(0);
+               omap_mpu_remove_autoreset(0);
+               break;
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+       case CLOCK_EVT_MODE_RESUME:
+               break;
+       }
+}
+
+static struct clock_event_device clockevent_mpu_timer1 = {
+       .name           = "mpu_timer1",
+       .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+       .shift          = 32,
+       .set_next_event = omap_mpu_set_next_event,
+       .set_mode       = omap_mpu_set_mode,
+};
+
 static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id)
 {
-       write_seqlock(&xtime_lock);
-       /* NOTE:  no lost-tick detection/handling! */
-       timer_tick();
-       write_sequnlock(&xtime_lock);
+       struct clock_event_device *evt = &clockevent_mpu_timer1;
+
+       evt->event_handler(evt);
 
        return IRQ_HANDLED;
 }
 
 static struct irqaction omap_mpu_timer1_irq = {
        .name           = "mpu_timer1",
-       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = omap_mpu_timer1_interrupt,
 };
 
@@ -139,9 +197,20 @@ static __init void omap_init_mpu_timer(unsigned long rate)
        set_cyc2ns_scale(rate / 1000);
 
        setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
-       omap_mpu_timer_start(0, (rate / HZ) - 1);
+       omap_mpu_timer_start(0, (rate / HZ) - 1, 1);
+
+       clockevent_mpu_timer1.mult = div_sc(rate, NSEC_PER_SEC,
+                                           clockevent_mpu_timer1.shift);
+       clockevent_mpu_timer1.max_delta_ns =
+               clockevent_delta2ns(-1, &clockevent_mpu_timer1);
+       clockevent_mpu_timer1.min_delta_ns =
+               clockevent_delta2ns(1, &clockevent_mpu_timer1);
+
+       clockevent_mpu_timer1.cpumask = cpumask_of_cpu(0);
+       clockevents_register_device(&clockevent_mpu_timer1);
 }
 
+
 /*
  * ---------------------------------------------------------------------------
  * MPU timer 2 ... free running 32-bit clock source and scheduler clock
@@ -173,7 +242,7 @@ static struct clocksource clocksource_mpu = {
        .read           = mpu_read,
        .mask           = CLOCKSOURCE_MASK(32),
        .shift          = 24,
-       .is_continuous  = 1,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static void __init omap_init_clocksource(unsigned long rate)
@@ -185,28 +254,12 @@ static void __init omap_init_clocksource(unsigned long rate)
                = clocksource_khz2mult(rate/1000, clocksource_mpu.shift);
 
        setup_irq(INT_TIMER2, &omap_mpu_timer2_irq);
-       omap_mpu_timer_start(1, ~0);
+       omap_mpu_timer_start(1, ~0, 1);
 
        if (clocksource_register(&clocksource_mpu))
                printk(err, clocksource_mpu.name);
 }
 
-
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
-       unsigned long ticks = 0 - omap_mpu_timer_read(1);
-       unsigned long long ticks64;
-
-       ticks64 = omap_mpu_timer2_overflows;
-       ticks64 <<= 32;
-       ticks64 |= ticks;
-
-       return cycles_2_ns(ticks64);
-}
-
 /*
  * ---------------------------------------------------------------------------
  * Timer initialization
@@ -214,7 +267,7 @@ unsigned long long sched_clock(void)
  */
 static void __init omap_timer_init(void)
 {
-       struct clk      *ck_ref = clk_get(NULL, "ck_ref");
+       struct clk      *ck_ref = clk_get(NULL, "ck_ref");
        unsigned long   rate;
 
        BUG_ON(IS_ERR(ck_ref));