From 684e94cbcb5add60356d124166e40feb2174f0f1 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 17 Nov 2010 16:20:15 -0800 Subject: ARM: tegra: timer: Separate clocksource and sched_clock tegra_clocksource_read should not use cnt32_to_63, wrapping is already handled in the clocksource code. Move the cnt32_to_63 into the sched_clock function, and replace the use of clocksource mult and shift with a multiplication by 1000 to convert us to ns. Acked-by: John Stultz Acked-by: Linus Walleij Tested-by: Olof Johansson Signed-off-by: Colin Cross Signed-off-by: Russell King --- arch/arm/mach-tegra/timer.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/arm/mach-tegra/timer.c') diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index 9057d6fd1d31..b49f2f5025f2 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c @@ -91,7 +91,7 @@ static void tegra_timer_set_mode(enum clock_event_mode mode, static cycle_t tegra_clocksource_read(struct clocksource *cs) { - return cnt32_to_63(timer_readl(TIMERUS_CNTR_1US)); + return timer_readl(TIMERUS_CNTR_1US); } static struct clock_event_device tegra_clockevent = { @@ -106,14 +106,13 @@ static struct clocksource tegra_clocksource = { .name = "timer_us", .rating = 300, .read = tegra_clocksource_read, - .mask = 0x7FFFFFFFFFFFFFFFULL, + .mask = CLOCKSOURCE_MASK(32), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; unsigned long long sched_clock(void) { - return clocksource_cyc2ns(tegra_clocksource.read(&tegra_clocksource), - tegra_clocksource.mult, tegra_clocksource.shift); + return cnt32_to_63(timer_readl(TIMERUS_CNTR_1US)) * 1000; } static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) -- cgit v1.2.3 From 5e06b6492e53ab2a4e467763a9ee9f70b032c301 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Dec 2010 19:19:25 +0000 Subject: ARM: ensure all sched_clock() implementations are notrace marked ftrace requires sched_clock() to be notrace. Ensure that all implementations are so marked. Also make sure that they include linux/sched.h Also ensure OMAP clocksource read functions are marked notrace as they're used for sched_clock() too. Tested-by: Santosh Shilimkar Tested-by: Will Deacon Tested-by: Mikael Pettersson Tested-by: Eric Miao Tested-by: Olof Johansson Signed-off-by: Russell King --- arch/arm/mach-ixp4xx/common.c | 2 +- arch/arm/mach-mmp/time.c | 2 +- arch/arm/mach-pxa/time.c | 2 +- arch/arm/mach-sa1100/generic.c | 2 +- arch/arm/mach-tegra/timer.c | 3 ++- arch/arm/mach-u300/timer.c | 1 + arch/arm/plat-iop/time.c | 3 ++- arch/arm/plat-nomadik/timer.c | 1 + arch/arm/plat-omap/counter_32k.c | 15 ++++++++------- arch/arm/plat-orion/time.c | 2 +- arch/arm/plat-versatile/sched-clock.c | 2 +- 11 files changed, 20 insertions(+), 15 deletions(-) (limited to 'arch/arm/mach-tegra/timer.c') diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 82fc003aae8b..e0b91d8ef644 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -424,7 +424,7 @@ static void __init ixp4xx_clocksource_init(void) /* * sched_clock() */ -unsigned long long sched_clock(void) +unsigned long long notrace sched_clock(void) { cycle_t cyc = ixp4xx_get_cycles(NULL); struct clocksource *cs = &clocksource_ixp4xx; diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 0c0ab0931735..a2ea33d04e63 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c @@ -75,7 +75,7 @@ static inline uint32_t timer_read(void) return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(0)); } -unsigned long long sched_clock(void) +unsigned long long notrace sched_clock(void) { unsigned long long v = cnt32_to_63(timer_read()); return (v * tcr2ns_scale) >> TCR2NS_SCALE_FACTOR; diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index caf92c0bfba5..b8d9dff00ad1 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -51,7 +51,7 @@ static void __init set_oscr2ns_scale(unsigned long oscr_rate) oscr2ns_scale++; } -unsigned long long sched_clock(void) +unsigned long long notrace sched_clock(void) { unsigned long long v = cnt32_to_63(OSCR); return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR; diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 3c1fcd696714..33b4969e9d51 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -119,7 +119,7 @@ unsigned int sa11x0_getspeed(unsigned int cpu) * * ( * 1E9 / 3686400 => * 78125 / 288) */ -unsigned long long sched_clock(void) +unsigned long long notrace sched_clock(void) { unsigned long long v = cnt32_to_63(OSCR); diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index b49f2f5025f2..c52bd84652e5 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -110,7 +111,7 @@ static struct clocksource tegra_clocksource = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -unsigned long long sched_clock(void) +unsigned long long notrace sched_clock(void) { return cnt32_to_63(timer_readl(TIMERUS_CNTR_1US)) * 1000; } diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index 377ff7ff9182..6c68fe797903 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c @@ -9,6 +9,7 @@ * Author: Linus Walleij */ #include +#include #include #include #include diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index 4332dc458ff9..d03a93295e60 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -52,7 +53,7 @@ static struct clocksource iop_clocksource = { /* * IOP sched_clock() implementation via its clocksource. */ -unsigned long long sched_clock(void) +unsigned long long notrace sched_clock(void) { cycle_t cyc = iop_clocksource_read(NULL); struct clocksource *cs = &iop_clocksource; diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index b0bd6dfea52b..c3b8a2246b99 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index 8f149f51cb46..aed301bfa2f9 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,7 @@ static u32 offset_32k __read_mostly; #ifdef CONFIG_ARCH_OMAP16XX -static cycle_t omap16xx_32k_read(struct clocksource *cs) +static cycle_t notrace omap16xx_32k_read(struct clocksource *cs) { return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k; } @@ -53,7 +54,7 @@ static cycle_t omap16xx_32k_read(struct clocksource *cs) #endif #ifdef CONFIG_ARCH_OMAP2420 -static cycle_t omap2420_32k_read(struct clocksource *cs) +static cycle_t notrace omap2420_32k_read(struct clocksource *cs) { return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k; } @@ -62,7 +63,7 @@ static cycle_t omap2420_32k_read(struct clocksource *cs) #endif #ifdef CONFIG_ARCH_OMAP2430 -static cycle_t omap2430_32k_read(struct clocksource *cs) +static cycle_t notrace omap2430_32k_read(struct clocksource *cs) { return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k; } @@ -71,7 +72,7 @@ static cycle_t omap2430_32k_read(struct clocksource *cs) #endif #ifdef CONFIG_ARCH_OMAP3 -static cycle_t omap34xx_32k_read(struct clocksource *cs) +static cycle_t notrace omap34xx_32k_read(struct clocksource *cs) { return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k; } @@ -80,7 +81,7 @@ static cycle_t omap34xx_32k_read(struct clocksource *cs) #endif #ifdef CONFIG_ARCH_OMAP4 -static cycle_t omap44xx_32k_read(struct clocksource *cs) +static cycle_t notrace omap44xx_32k_read(struct clocksource *cs) { return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k; } @@ -92,7 +93,7 @@ static cycle_t omap44xx_32k_read(struct clocksource *cs) * Kernel assumes that sched_clock can be called early but may not have * things ready yet. */ -static cycle_t omap_32k_read_dummy(struct clocksource *cs) +static cycle_t notrace omap_32k_read_dummy(struct clocksource *cs) { return 0; } @@ -109,7 +110,7 @@ static struct clocksource clocksource_32k = { * Returns current time from boot in nsecs. It's OK for this to wrap * around for now, as it's just a relative time stamp. */ -unsigned long long sched_clock(void) +unsigned long long notrace sched_clock(void) { return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k), clocksource_32k.mult, clocksource_32k.shift); diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 11e2583e85e4..123f96f4194f 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c @@ -55,7 +55,7 @@ static u32 ticks_per_jiffy; static unsigned long tclk2ns_scale; -unsigned long long sched_clock(void) +unsigned long long notrace sched_clock(void) { unsigned long long v = cnt32_to_63(0xffffffff - readl(TIMER0_VAL)); return (v * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR; diff --git a/arch/arm/plat-versatile/sched-clock.c b/arch/arm/plat-versatile/sched-clock.c index 9696ddc238c9..42efd14ed4b3 100644 --- a/arch/arm/plat-versatile/sched-clock.c +++ b/arch/arm/plat-versatile/sched-clock.c @@ -42,7 +42,7 @@ * long as there is always less than 89 seconds between successive * calls to this function. */ -unsigned long long sched_clock(void) +unsigned long long notrace sched_clock(void) { unsigned long long v = cnt32_to_63(readl(REFCOUNTER)); -- cgit v1.2.3 From e3f4c0ab916334e861fc49eeb2673a8c13e978e7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 15 Dec 2010 21:49:42 +0000 Subject: ARM: tegra: convert sched_clock() to use new infrastructure Convert tegra to use the new sched_clock() infrastructure for extending 32bit counters to full 64-bit nanoseconds. Tested-by: Olof Johansson Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/mach-tegra/timer.c | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-tegra/timer.c') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0e1a9667a869..ec7b0274d46a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -570,6 +570,7 @@ config ARCH_TEGRA select GENERIC_CLOCKEVENTS select GENERIC_GPIO select HAVE_CLK + select HAVE_SCHED_CLOCK select COMMON_CLKDEV select ARCH_HAS_BARRIERS if CACHE_L2X0 select ARCH_HAS_CPUFREQ diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index c52bd84652e5..7b8ad1f98f44 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c @@ -26,10 +26,10 @@ #include #include #include -#include #include #include +#include #include #include @@ -111,9 +111,25 @@ static struct clocksource tegra_clocksource = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static DEFINE_CLOCK_DATA(cd); + +/* + * Constants generated by clocks_calc_mult_shift(m, s, 1MHz, NSEC_PER_SEC, 60). + * This gives a resolution of about 1us and a wrap period of about 1h11min. + */ +#define SC_MULT 4194304000u +#define SC_SHIFT 22 + unsigned long long notrace sched_clock(void) { - return cnt32_to_63(timer_readl(TIMERUS_CNTR_1US)) * 1000; + u32 cyc = timer_readl(TIMERUS_CNTR_1US); + return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); +} + +static void notrace tegra_update_sched_clock(void) +{ + u32 cyc = timer_readl(TIMERUS_CNTR_1US); + update_sched_clock(&cd, cyc, (u32)~0); } static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) @@ -158,6 +174,9 @@ static void __init tegra_init_timer(void) WARN(1, "Unknown clock rate"); } + init_fixed_sched_clock(&cd, tegra_update_sched_clock, 32, + 1000000, SC_MULT, SC_SHIFT); + if (clocksource_register_hz(&tegra_clocksource, 1000000)) { printk(KERN_ERR "Failed to register clocksource\n"); BUG(); -- cgit v1.2.3