From 8e1889c13d8990cbee586d43c3586100eed9a37d Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=BB=84=E6=B6=9B?= Date: Fri, 25 Jan 2013 15:17:00 +0800 Subject: [PATCH] rk_timer: v1.2, update sched clock support, only use 32bits --- arch/arm/Kconfig | 4 +-- arch/arm/plat-rk/rk_timer.c | 71 ++++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index fde5a928ee03..07be42f84d3e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -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 diff --git a/arch/arm/plat-rk/rk_timer.c b/arch/arm/plat-rk/rk_timer.c index 72788fa073fb..aad8777c866d 100644 --- a/arch/arm/plat-rk/rk_timer.c +++ b/arch/arm/plat-rk/rk_timer.c @@ -22,6 +22,7 @@ #include #include +#include #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); -} -- 2.34.1