rk_timer: v1.2, update sched clock support, only use 32bits
author黄涛 <huangtao@rock-chips.com>
Fri, 25 Jan 2013 07:17:00 +0000 (15:17 +0800)
committer黄涛 <huangtao@rock-chips.com>
Fri, 25 Jan 2013 07:17:24 +0000 (15:17 +0800)
arch/arm/Kconfig
arch/arm/plat-rk/rk_timer.c

index fde5a928ee034c5d3ca747be025646ece5beaed3..07be42f84d3e63677d7356e553d5d61a302a9187 100644 (file)
@@ -862,7 +862,6 @@ config ARCH_OMAP
 config ARCH_RK29
        bool "Rockchip RK29xx"
        select PLAT_RK
-       select HAVE_SCHED_CLOCK
        select CPU_V7
        select ARM_GIC
        select PL330
@@ -875,7 +874,6 @@ config ARCH_RK29
 config ARCH_RK2928
        bool "Rockchip RK2928"
        select PLAT_RK
-       select HAVE_SCHED_CLOCK
        select CPU_V7
        select ARM_GIC
        select RK_PL330_DMA
@@ -888,7 +886,6 @@ config ARCH_RK2928
 config ARCH_RK30
        bool "Rockchip RK30xx/RK3108/RK3168"
        select PLAT_RK
-       select HAVE_SCHED_CLOCK
        select CPU_V7
        select ARM_GIC
        select RK_PL330_DMA
@@ -1090,6 +1087,7 @@ config PLAT_PXA
 config PLAT_RK
        bool
        select CLKDEV_LOOKUP
+       select HAVE_SCHED_CLOCK
        select ARCH_HAS_CPUFREQ
        select GENERIC_CLOCKEVENTS
        select ARCH_REQUIRE_GPIOLIB
index 72788fa073fbc5c8acad45cd08702d4b8b747e3d..aad8777c866dba49a7944e2ba83b38d94bd7e95c 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/platform_device.h>
 
 #include <asm/localtimer.h>
+#include <asm/sched_clock.h>
 
 #define TIMER_NAME "rk_timer"
 
@@ -51,23 +52,9 @@ static inline void rk_timer_enable(void __iomem *base, u32 flags)
        dsb();
 }
 
-static inline u64 rk_timer_read_current_value(void __iomem *base)
+static inline u32 rk_timer_read_current_value(void __iomem *base)
 {
-       /*
-        * 1. Read the upper 32-bit timer counter register
-        * 2. Read the lower 32-bit timer counter register
-        * 3. Read the upper 32-bit timer counter register again. If the value is different to the 32-bit
-        * upper value read previously, go back to step 2. Otherwise the 64-bit timer counter value
-        * is correct.
-        */
-       u32 upper, lower;
-
-       do {
-               upper = readl_relaxed(base + TIMER_CURRENT_VALUE1);
-               lower = readl_relaxed(base + TIMER_CURRENT_VALUE0);
-       } while (upper != readl_relaxed(base + TIMER_CURRENT_VALUE1));
-
-       return ((u64) upper << 32) + lower;
+       return readl_relaxed(base + TIMER_CURRENT_VALUE0);
 }
 
 struct rk_timer {
@@ -181,11 +168,19 @@ static cycle_t rk_timer_read(struct clocksource *cs)
        return ~rk_timer_read_current_value(timer.cs_base);
 }
 
+/*
+ * Constants generated by clocksource_hz2mult(24000000, 26).
+ * This gives a resolution of about 41ns and a wrap period of about 178s.
+ */
+#define MULT   2796202667u
+#define SHIFT  26
+#define MASK   (u32)~0
+
 static struct clocksource rk_timer_clocksource = {
        .name           = TIMER_NAME,
        .rating         = 200,
        .read           = rk_timer_read,
-       .mask           = CLOCKSOURCE_MASK(64),
+       .mask           = CLOCKSOURCE_MASK(32),
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -208,6 +203,30 @@ static void __init rk_timer_init_clocksource(void)
                printk(err, cs->name);
 }
 
+static DEFINE_CLOCK_DATA(cd);
+
+unsigned long long notrace sched_clock(void)
+{
+       cycle_t cyc;
+
+       if (!timer.cs_base)
+               return 0;
+
+       cyc = ~rk_timer_read_current_value(timer.cs_base);
+       return cyc_to_fixed_sched_clock(&cd, cyc, MASK, MULT, SHIFT);
+}
+
+static void notrace rk_timer_update_sched_clock(void)
+{
+       u32 cyc = ~rk_timer_read_current_value(timer.cs_base);
+       update_sched_clock(&cd, cyc, MASK);
+}
+
+static void __init rk_timer_init_sched_clock(void)
+{
+       init_fixed_sched_clock(&cd, rk_timer_update_sched_clock, 32, 24000000, MULT, SHIFT);
+}
+
 #ifndef CONFIG_LOCAL_TIMERS
 static struct clock_event_device rk_timer_clockevent;
 #endif
@@ -253,8 +272,9 @@ static int __init rk_timer_probe(struct platform_device *pdev)
        rk_timer_clockevent.rating = 200;
        rk_timer_init_clockevent(&rk_timer_clockevent, 0);
 #endif
+       rk_timer_init_sched_clock();
 
-       printk("rk_timer: version 1.1\n");
+       printk("rk_timer: version 1.2\n");
        return 0;
 }
 
@@ -296,18 +316,3 @@ int local_timer_ack(void)
        return 0;
 }
 #endif
-
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long notrace sched_clock(void)
-{
-       const struct clocksource *cs = &rk_timer_clocksource;
-       cycle_t cyc;
-
-       if (!timer.cs_base)
-               return 0;
-
-       cyc = ~rk_timer_read_current_value(timer.cs_base);
-       return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
-}