diff options
author | Nicolas Pitre <nico@cam.org> | 2006-12-04 14:42:09 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-12-07 11:06:55 -0500 |
commit | 2dc20a51dc1e2da6eae1182cfe4c4835fca26017 (patch) | |
tree | 206a73320b1d41451884f0ca5d0796af9a34c50e /arch/arm/mach-pxa | |
parent | 752bee178ee107aa3dd87a9aeba970444034c6fb (diff) |
[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>
Diffstat (limited to 'arch/arm/mach-pxa')
-rw-r--r-- | arch/arm/mach-pxa/generic.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 45fb2c3bcf82..6ae605857ca9 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c | |||
@@ -25,6 +25,10 @@ | |||
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/string.h> | 26 | #include <linux/string.h> |
27 | 27 | ||
28 | #include <linux/sched.h> | ||
29 | #include <asm/cnt32_to_63.h> | ||
30 | #include <asm/div64.h> | ||
31 | |||
28 | #include <asm/hardware.h> | 32 | #include <asm/hardware.h> |
29 | #include <asm/irq.h> | 33 | #include <asm/irq.h> |
30 | #include <asm/system.h> | 34 | #include <asm/system.h> |
@@ -41,6 +45,62 @@ | |||
41 | #include "generic.h" | 45 | #include "generic.h" |
42 | 46 | ||
43 | /* | 47 | /* |
48 | * This is the PXA2xx sched_clock implementation. This has a resolution | ||
49 | * of at least 308ns and a maximum value that depends on the value of | ||
50 | * CLOCK_TICK_RATE. | ||
51 | * | ||
52 | * The return value is guaranteed to be monotonic in that range as | ||
53 | * long as there is always less than 582 seconds between successive | ||
54 | * calls to this function. | ||
55 | */ | ||
56 | unsigned long long sched_clock(void) | ||
57 | { | ||
58 | unsigned long long v = cnt32_to_63(OSCR); | ||
59 | /* Note: top bit ov v needs cleared unless multiplier is even. */ | ||
60 | |||
61 | #if CLOCK_TICK_RATE == 3686400 | ||
62 | /* 1E9 / 3686400 => 78125 / 288, max value = 32025597s (370 days). */ | ||
63 | /* The <<1 is used to get rid of tick.hi top bit */ | ||
64 | v *= 78125<<1; | ||
65 | do_div(v, 288<<1); | ||
66 | #elif CLOCK_TICK_RATE == 3250000 | ||
67 | /* 1E9 / 3250000 => 4000 / 13, max value = 709490156s (8211 days) */ | ||
68 | v *= 4000; | ||
69 | do_div(v, 13); | ||
70 | #elif CLOCK_TICK_RATE == 3249600 | ||
71 | /* 1E9 / 3249600 => 625000 / 2031, max value = 4541295s (52 days) */ | ||
72 | v *= 625000; | ||
73 | do_div(v, 2031); | ||
74 | #else | ||
75 | #warning "consider fixing sched_clock for your value of CLOCK_TICK_RATE" | ||
76 | /* | ||
77 | * 96-bit math to perform tick * NSEC_PER_SEC / CLOCK_TICK_RATE for | ||
78 | * any value of CLOCK_TICK_RATE. Max value is in the 80 thousand | ||
79 | * years range which is nice, but with higher computation cost. | ||
80 | */ | ||
81 | { | ||
82 | union { | ||
83 | unsigned long long val; | ||
84 | struct { unsigned long lo, hi; }; | ||
85 | } x; | ||
86 | unsigned long long y; | ||
87 | |||
88 | x.val = v; | ||
89 | x.hi &= 0x7fffffff; | ||
90 | y = (unsigned long long)x.lo * NSEC_PER_SEC; | ||
91 | x.lo = y; | ||
92 | y = (y >> 32) + (unsigned long long)x.hi * NSEC_PER_SEC; | ||
93 | x.hi = do_div(y, CLOCK_TICK_RATE); | ||
94 | do_div(x.val, CLOCK_TICK_RATE); | ||
95 | x.hi += y; | ||
96 | v = x.val; | ||
97 | } | ||
98 | #endif | ||
99 | |||
100 | return v; | ||
101 | } | ||
102 | |||
103 | /* | ||
44 | * Handy function to set GPIO alternate functions | 104 | * Handy function to set GPIO alternate functions |
45 | */ | 105 | */ |
46 | 106 | ||