]> err.no Git - linux-2.6/commitdiff
[ARM] 4592/1: ns9xxx: clocksource driver
authorUwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
Sun, 30 Sep 2007 19:35:48 +0000 (20:35 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 12 Oct 2007 22:43:37 +0000 (23:43 +0100)
Signed-off-by: Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/Kconfig
arch/arm/mach-ns9xxx/time.c

index 6acc59da332d7a32871eff9279e5db2aa954c244..a43a814bc7cfe1bae6a3483c9fd6f72d438c5396 100644 (file)
@@ -319,6 +319,7 @@ config ARCH_KS8695
 config ARCH_NS9XXX
        bool "NetSilicon NS9xxx"
        select GENERIC_GPIO
+       select GENERIC_TIME
        help
          Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
          System.
index 3327d302618d652099bfb2d90edd78d2963258aa..d293455017622aa6783a19ef0f3edd38d3cdb1f6 100644 (file)
@@ -11,6 +11,9 @@
 #include <linux/jiffies.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/stringify.h>
+#include <linux/clocksource.h>
+
 #include <asm/arch-ns9xxx/regs-sys.h>
 #include <asm/arch-ns9xxx/clock.h>
 #include <asm/arch-ns9xxx/irqs.h>
@@ -18,8 +21,7 @@
 #include "generic.h"
 
 #define TIMERCLOCKSELECT 64
-
-static u32 usecs_per_tick;
+#define TIMER_CLOCKSOURCE 1
 
 static irqreturn_t
 ns9xxx_timer_interrupt(int irq, void *dev_id)
@@ -45,39 +47,30 @@ ns9xxx_timer_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static unsigned long ns9xxx_timer_gettimeoffset(void)
-{
-       /* return the microseconds which have passed since the last interrupt
-        * was _serviced_.  That is, if an interrupt is pending or the counter
-        * reloads, return one period more. */
-
-       u32 counter1 = SYS_TR(0);
-       int pending = SYS_ISR & (1 << IRQ_TIMER0);
-       u32 counter2 = SYS_TR(0);
-       u32 elapsed;
-
-       if (pending || counter2 > counter1)
-               elapsed = 2 * SYS_TRC(0) - counter2;
-       else
-               elapsed = SYS_TRC(0) - counter1;
-
-       return (elapsed * usecs_per_tick) >> 16;
-
-}
-
 static struct irqaction ns9xxx_timer_irq = {
        .name = "NS9xxx Timer Tick",
        .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler = ns9xxx_timer_interrupt,
 };
 
+static cycle_t ns9xxx_clocksource_read(void)
+{
+       return SYS_TR(TIMER_CLOCKSOURCE);
+}
+
+static struct clocksource ns9xxx_clocksource = {
+       .name   = "ns9xxx-timer" __stringify(TIMER_CLOCKSOURCE),
+       .rating = 300,
+       .read   = ns9xxx_clocksource_read,
+       .mask   = CLOCKSOURCE_MASK(32),
+       .shift  = 20,
+       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
 static void __init ns9xxx_timer_init(void)
 {
        int tc;
 
-       usecs_per_tick =
-               SH_DIV(1000000 * TIMERCLOCKSELECT, ns9xxx_cpuclock(), 16);
-
        /* disable timer */
        if ((tc = SYS_TC(0)) & SYS_TCx_TEN)
                SYS_TC(0) = tc & ~SYS_TCx_TEN;
@@ -94,9 +87,32 @@ static void __init ns9xxx_timer_init(void)
        SYS_TC(0) = tc;
 
        setup_irq(IRQ_TIMER0, &ns9xxx_timer_irq);
+
+       tc = SYS_TC(TIMER_CLOCKSOURCE);
+       if (REGGET(tc, SYS_TCx, TEN)) {
+               REGSET(tc, SYS_TCx, TEN, DIS);
+               SYS_TC(TIMER_CLOCKSOURCE) = tc;
+       }
+
+       SYS_TRC(TIMER_CLOCKSOURCE) = 0;
+
+       REGSET(tc, SYS_TCx, TEN, EN);
+       REGSET(tc, SYS_TCx, TDBG, STOP);
+       REGSET(tc, SYS_TCx, TLCS, CPU);
+       REGSET(tc, SYS_TCx, TM, IEE);
+       REGSET(tc, SYS_TCx, INTS, DIS);
+       REGSET(tc, SYS_TCx, UDS, UP);
+       REGSET(tc, SYS_TCx, TSZ, 32);
+       REGSET(tc, SYS_TCx, REN, EN);
+
+       SYS_TC(TIMER_CLOCKSOURCE) = tc;
+
+       ns9xxx_clocksource.mult = clocksource_hz2mult(ns9xxx_cpuclock(),
+                       ns9xxx_clocksource.shift);
+
+       clocksource_register(&ns9xxx_clocksource);
 }
 
 struct sys_timer ns9xxx_timer = {
        .init = ns9xxx_timer_init,
-       .offset = ns9xxx_timer_gettimeoffset,
 };