From 4912cf04b202a9d0bdc4082ecb9247943584450d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 18 Jan 2011 17:00:00 -0800 Subject: [PATCH] omap1: Fix sched_clock implementation when both MPU timer and 32K timer are used Earlier patches select HAVE_SCHED_CLOCK for omaps. To have working sched_clock also for MPU timer, we need to implement it in a way where the right one gets selected during the runtime. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/time.c | 48 +++++++++++++++++++++++- arch/arm/plat-omap/counter_32k.c | 14 ++++++- arch/arm/plat-omap/include/plat/common.h | 1 + 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index b03f34d55d88..f83fc335c613 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c @@ -219,6 +219,24 @@ static struct clocksource clocksource_mpu = { static DEFINE_CLOCK_DATA(cd); +static inline unsigned long long notrace _omap_mpu_sched_clock(void) +{ + u32 cyc = mpu_read(&clocksource_mpu); + return cyc_to_sched_clock(&cd, cyc, (u32)~0); +} + +#ifndef CONFIG_OMAP_32K_TIMER +unsigned long long notrace sched_clock(void) +{ + return _omap_mpu_sched_clock(); +} +#else +static unsigned long long notrace omap_mpu_sched_clock(void) +{ + return _omap_mpu_sched_clock(); +} +#endif + static void notrace mpu_update_sched_clock(void) { u32 cyc = mpu_read(&clocksource_mpu); @@ -262,6 +280,30 @@ static inline void omap_mpu_timer_init(void) } #endif /* CONFIG_OMAP_MPU_TIMER */ +#if defined(CONFIG_OMAP_MPU_TIMER) && defined(CONFIG_OMAP_32K_TIMER) +static unsigned long long (*preferred_sched_clock)(void); + +unsigned long long notrace sched_clock(void) +{ + if (!preferred_sched_clock) + return 0; + + return preferred_sched_clock(); +} + +static inline void preferred_sched_clock_init(bool use_32k_sched_clock) +{ + if (use_32k_sched_clock) + preferred_sched_clock = omap_32k_sched_clock; + else + preferred_sched_clock = omap_mpu_sched_clock; +} +#else +static inline void preferred_sched_clock_init(bool use_32k_sched_clcok) +{ +} +#endif + static inline int omap_32k_timer_usable(void) { int res = false; @@ -283,8 +325,12 @@ static inline int omap_32k_timer_usable(void) */ static void __init omap_timer_init(void) { - if (!omap_32k_timer_usable()) + if (omap_32k_timer_usable()) { + preferred_sched_clock_init(1); + } else { omap_mpu_timer_init(); + preferred_sched_clock_init(0); + } } struct sys_timer omap_timer = { diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index 5d7b08b5a13a..862dda95d61d 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c @@ -120,12 +120,24 @@ static DEFINE_CLOCK_DATA(cd); #define SC_MULT 4000000000u #define SC_SHIFT 17 -unsigned long long notrace sched_clock(void) +static inline unsigned long long notrace _omap_32k_sched_clock(void) { u32 cyc = clocksource_32k.read(&clocksource_32k); return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); } +#ifndef CONFIG_OMAP_MPU_TIMER +unsigned long long notrace sched_clock(void) +{ + return _omap_32k_sched_clock(); +} +#else +unsigned long long notrace omap_32k_sched_clock(void) +{ + return _omap_32k_sched_clock(); +} +#endif + static void notrace omap_update_sched_clock(void) { u32 cyc = clocksource_32k.read(&clocksource_32k); diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index ef683e01701b..29b2afb4288f 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h @@ -37,6 +37,7 @@ extern void omap_map_common_io(void); extern struct sys_timer omap_timer; extern bool omap_32k_timer_init(void); extern int __init omap_init_clocksource_32k(void); +extern unsigned long long notrace omap_32k_sched_clock(void); extern void omap_reserve(void);