diff options
author | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 18:40:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 18:40:39 -0500 |
commit | ea14fad0d416354a4e9bb1a04f32acba706f9548 (patch) | |
tree | 2c8acc5331f189aef1d40ddce3f40d6be9314e77 /arch/arm/mach-pxa/generic.c | |
parent | 6ee7e78e7c78d871409ad4df30551c9355be7d0e (diff) | |
parent | 6705cda24fad1cb0ac82ac4f312df8ec735b39b0 (diff) |
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (76 commits)
[ARM] 4002/1: S3C24XX: leave parent IRQs unmasked
[ARM] 4001/1: S3C24XX: shorten reboot time
[ARM] 3983/2: remove unused argument to __bug()
[ARM] 4000/1: Osiris: add third serial port in
[ARM] 3999/1: RX3715: suspend to RAM support
[ARM] 3998/1: VR1000: LED platform devices
[ARM] 3995/1: iop13xx: add iop13xx support
[ARM] 3968/1: iop13xx: add iop13xx_defconfig
[ARM] Update mach-types
[ARM] Allow gcc to optimise arm_add_memory a little more
[ARM] 3991/1: i.MX/MX1 high resolution time source
[ARM] 3990/1: i.MX/MX1 more precise PLL decode
[ARM] 3986/1: H1940: suspend to RAM support
[ARM] 3985/1: ixp4xx clocksource cleanup
[ARM] 3984/1: ixp4xx/nslu2: Fix disk LED numbering (take 2)
[ARM] 3994/1: ixp23xx: fix handling of pci master aborts
[ARM] 3981/1: sched_clock for PXA2xx
[ARM] 3980/1: extend the ARM Versatile sched_clock implementation from 32 to 63 bit
[ARM] 3979/1: extend the SA11x0 sched_clock implementation from 32 to 63 bit period
[ARM] 3978/1: macro to provide a 63-bit value from a 32-bit hardware counter
...
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 | ||