diff options
Diffstat (limited to 'arch/arm/mach-pxa/generic.c')
| -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 | ||
