From 6c3a158316598bfb165b8c83b168fa413d5ae2d8 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 17 Aug 2007 16:55:22 +0100 Subject: [ARM] 4550/1: sched_clock on PXA should cope with run time clock rate selection The previous implementation was relying on compile time optimizations based on a constant clock rate. However, support for different PXA flavors in the same kernel binary requires that the clock be selected at run time, so here it is. Let's move this code to a more appropriate location while at it. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mach-pxa/time.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'arch/arm/mach-pxa/time.c') diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 98d27e646b0..7916311547c 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -16,11 +16,48 @@ #include #include #include +#include +#include +#include #include #include #include +/* + * This is PXA's sched_clock implementation. This has a resolution + * of at least 308 ns and a maximum value of 208 days. + * + * The return value is guaranteed to be monotonic in that range as + * long as there is always less than 582 seconds between successive + * calls to sched_clock() which should always be the case in practice. + */ + +#define OSCR2NS_SCALE_FACTOR 10 + +static unsigned long oscr2ns_scale; + +static void __init set_oscr2ns_scale(unsigned long oscr_rate) +{ + unsigned long long v = 1000000000ULL << OSCR2NS_SCALE_FACTOR; + do_div(v, oscr_rate); + oscr2ns_scale = v; + /* + * We want an even value to automatically clear the top bit + * returned by cnt32_to_63() without an additional run time + * instruction. So if the LSB is 1 then round it up. + */ + if (oscr2ns_scale & 1) + oscr2ns_scale++; +} + +unsigned long long sched_clock(void) +{ + unsigned long long v = cnt32_to_63(OSCR); + return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR; +} + + static irqreturn_t pxa_ost0_interrupt(int irq, void *dev_id) { @@ -152,6 +189,8 @@ static void __init pxa_timer_init(void) OIER = 0; OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; + set_oscr2ns_scale(CLOCK_TICK_RATE); + ckevt_pxa_osmr0.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); ckevt_pxa_osmr0.max_delta_ns = -- cgit v1.2.3 From 08197f6e3b262f4fb8b164c818d5e54b46c14711 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 1 Sep 2007 21:12:50 +0100 Subject: [ARM] pxa: make pxa timer initialisation select clock rate at runtime Rather than using the compile-time constant CLOCK_TICK_RATE, select the clock tick rate at run time. We organise the selection so that PXA3 automatically falls out with the right tick rate. Signed-off-by: Russell King --- arch/arm/mach-pxa/time.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-pxa/time.c') diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 7916311547c..ec4286c7931 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -23,6 +23,7 @@ #include #include #include +#include /* * This is PXA's sched_clock implementation. This has a resolution @@ -186,20 +187,29 @@ static struct irqaction pxa_ost0_irq = { static void __init pxa_timer_init(void) { + unsigned long clock_tick_rate; + OIER = 0; OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; - set_oscr2ns_scale(CLOCK_TICK_RATE); + if (cpu_is_pxa21x() || cpu_is_pxa25x()) + clock_tick_rate = 3686400; + else if (machine_is_mainstone()) + clock_tick_rate = 3249600; + else + clock_tick_rate = 3250000; + + set_oscr2ns_scale(clock_tick_rate); ckevt_pxa_osmr0.mult = - div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); + div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); ckevt_pxa_osmr0.max_delta_ns = clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); ckevt_pxa_osmr0.min_delta_ns = clockevent_delta2ns(MIN_OSCR_DELTA, &ckevt_pxa_osmr0) + 1; cksrc_pxa_oscr0.mult = - clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_pxa_oscr0.shift); + clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift); setup_irq(IRQ_OST0, &pxa_ost0_irq); -- cgit v1.2.3