[ARM] 3981/1: sched_clock for PXA2xx
Here's a 63-bit implementation of shed_clock() for PXA2xx. The actual period depends on the value of CLOCK_TICK_RATE and whether or not reduced scaling factors were provided for it. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
752bee178e
commit
2dc20a51dc
@ -25,6 +25,10 @@
|
||||
#include <linux/pm.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <asm/cnt32_to_63.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/system.h>
|
||||
@ -40,6 +44,62 @@
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
/*
|
||||
* This is the PXA2xx sched_clock implementation. This has a resolution
|
||||
* of at least 308ns and a maximum value that depends on the value of
|
||||
* CLOCK_TICK_RATE.
|
||||
*
|
||||
* 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 this function.
|
||||
*/
|
||||
unsigned long long sched_clock(void)
|
||||
{
|
||||
unsigned long long v = cnt32_to_63(OSCR);
|
||||
/* Note: top bit ov v needs cleared unless multiplier is even. */
|
||||
|
||||
#if CLOCK_TICK_RATE == 3686400
|
||||
/* 1E9 / 3686400 => 78125 / 288, max value = 32025597s (370 days). */
|
||||
/* The <<1 is used to get rid of tick.hi top bit */
|
||||
v *= 78125<<1;
|
||||
do_div(v, 288<<1);
|
||||
#elif CLOCK_TICK_RATE == 3250000
|
||||
/* 1E9 / 3250000 => 4000 / 13, max value = 709490156s (8211 days) */
|
||||
v *= 4000;
|
||||
do_div(v, 13);
|
||||
#elif CLOCK_TICK_RATE == 3249600
|
||||
/* 1E9 / 3249600 => 625000 / 2031, max value = 4541295s (52 days) */
|
||||
v *= 625000;
|
||||
do_div(v, 2031);
|
||||
#else
|
||||
#warning "consider fixing sched_clock for your value of CLOCK_TICK_RATE"
|
||||
/*
|
||||
* 96-bit math to perform tick * NSEC_PER_SEC / CLOCK_TICK_RATE for
|
||||
* any value of CLOCK_TICK_RATE. Max value is in the 80 thousand
|
||||
* years range which is nice, but with higher computation cost.
|
||||
*/
|
||||
{
|
||||
union {
|
||||
unsigned long long val;
|
||||
struct { unsigned long lo, hi; };
|
||||
} x;
|
||||
unsigned long long y;
|
||||
|
||||
x.val = v;
|
||||
x.hi &= 0x7fffffff;
|
||||
y = (unsigned long long)x.lo * NSEC_PER_SEC;
|
||||
x.lo = y;
|
||||
y = (y >> 32) + (unsigned long long)x.hi * NSEC_PER_SEC;
|
||||
x.hi = do_div(y, CLOCK_TICK_RATE);
|
||||
do_div(x.val, CLOCK_TICK_RATE);
|
||||
x.hi += y;
|
||||
v = x.val;
|
||||
}
|
||||
#endif
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handy function to set GPIO alternate functions
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user