diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-pxa/generic.c | 62 | ||||
-rw-r--r-- | arch/arm/mach-pxa/time.c | 39 |
2 files changed, 39 insertions, 62 deletions
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 5510f6fdce55..9d6a2c00d762 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c | |||
@@ -25,10 +25,6 @@ | |||
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 | |||
32 | #include <asm/hardware.h> | 28 | #include <asm/hardware.h> |
33 | #include <asm/irq.h> | 29 | #include <asm/irq.h> |
34 | #include <asm/system.h> | 30 | #include <asm/system.h> |
@@ -47,64 +43,6 @@ | |||
47 | #include "generic.h" | 43 | #include "generic.h" |
48 | 44 | ||
49 | /* | 45 | /* |
50 | * This is the PXA2xx sched_clock implementation. This has a resolution | ||
51 | * of at least 308ns and a maximum value that depends on the value of | ||
52 | * CLOCK_TICK_RATE. | ||
53 | * | ||
54 | * The return value is guaranteed to be monotonic in that range as | ||
55 | * long as there is always less than 582 seconds between successive | ||
56 | * calls to this function. | ||
57 | */ | ||
58 | unsigned long long sched_clock(void) | ||
59 | { | ||
60 | unsigned long long v = cnt32_to_63(OSCR); | ||
61 | /* Note: top bit ov v needs cleared unless multiplier is even. */ | ||
62 | |||
63 | #if CLOCK_TICK_RATE == 3686400 | ||
64 | /* 1E9 / 3686400 => 78125 / 288, max value = 32025597s (370 days). */ | ||
65 | /* The <<1 is used to get rid of tick.hi top bit */ | ||
66 | v *= 78125<<1; | ||
67 | do_div(v, 288<<1); | ||
68 | #elif CLOCK_TICK_RATE == 3250000 | ||
69 | /* 1E9 / 3250000 => 4000 / 13, max value = 709490156s (8211 days) */ | ||
70 | v *= 4000; | ||
71 | do_div(v, 13); | ||
72 | #elif CLOCK_TICK_RATE == 3249600 | ||
73 | /* 1E9 / 3249600 => 625000 / 2031, max value = 4541295s (52 days) */ | ||
74 | v *= 625000; | ||
75 | do_div(v, 2031); | ||
76 | #else | ||
77 | #warning "consider fixing sched_clock for your value of CLOCK_TICK_RATE" | ||
78 | /* | ||
79 | * 96-bit math to perform tick * NSEC_PER_SEC / CLOCK_TICK_RATE for | ||
80 | * any value of CLOCK_TICK_RATE. Max value is in the 80 thousand | ||
81 | * years range and truncation to unsigned long long limits it to | ||
82 | * sched_clock's max range of ~584 years. This is nice but with | ||
83 | * higher computation cost. | ||
84 | */ | ||
85 | { | ||
86 | union { | ||
87 | unsigned long long val; | ||
88 | struct { unsigned long lo, hi; }; | ||
89 | } x; | ||
90 | unsigned long long y; | ||
91 | |||
92 | x.val = v; | ||
93 | x.hi &= 0x7fffffff; | ||
94 | y = (unsigned long long)x.lo * NSEC_PER_SEC; | ||
95 | x.lo = y; | ||
96 | y = (y >> 32) + (unsigned long long)x.hi * NSEC_PER_SEC; | ||
97 | x.hi = do_div(y, CLOCK_TICK_RATE); | ||
98 | do_div(x.val, CLOCK_TICK_RATE); | ||
99 | x.hi += y; | ||
100 | v = x.val; | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | return v; | ||
105 | } | ||
106 | |||
107 | /* | ||
108 | * Handy function to set GPIO alternate functions | 46 | * Handy function to set GPIO alternate functions |
109 | */ | 47 | */ |
110 | 48 | ||
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 98d27e646b09..7916311547ca 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c | |||
@@ -16,11 +16,48 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/clockchips.h> | 18 | #include <linux/clockchips.h> |
19 | #include <linux/sched.h> | ||
19 | 20 | ||
21 | #include <asm/div64.h> | ||
22 | #include <asm/cnt32_to_63.h> | ||
20 | #include <asm/mach/irq.h> | 23 | #include <asm/mach/irq.h> |
21 | #include <asm/mach/time.h> | 24 | #include <asm/mach/time.h> |
22 | #include <asm/arch/pxa-regs.h> | 25 | #include <asm/arch/pxa-regs.h> |
23 | 26 | ||
27 | /* | ||
28 | * This is PXA's sched_clock implementation. This has a resolution | ||
29 | * of at least 308 ns and a maximum value of 208 days. | ||
30 | * | ||
31 | * The return value is guaranteed to be monotonic in that range as | ||
32 | * long as there is always less than 582 seconds between successive | ||
33 | * calls to sched_clock() which should always be the case in practice. | ||
34 | */ | ||
35 | |||
36 | #define OSCR2NS_SCALE_FACTOR 10 | ||
37 | |||
38 | static unsigned long oscr2ns_scale; | ||
39 | |||
40 | static void __init set_oscr2ns_scale(unsigned long oscr_rate) | ||
41 | { | ||
42 | unsigned long long v = 1000000000ULL << OSCR2NS_SCALE_FACTOR; | ||
43 | do_div(v, oscr_rate); | ||
44 | oscr2ns_scale = v; | ||
45 | /* | ||
46 | * We want an even value to automatically clear the top bit | ||
47 | * returned by cnt32_to_63() without an additional run time | ||
48 | * instruction. So if the LSB is 1 then round it up. | ||
49 | */ | ||
50 | if (oscr2ns_scale & 1) | ||
51 | oscr2ns_scale++; | ||
52 | } | ||
53 | |||
54 | unsigned long long sched_clock(void) | ||
55 | { | ||
56 | unsigned long long v = cnt32_to_63(OSCR); | ||
57 | return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR; | ||
58 | } | ||
59 | |||
60 | |||
24 | static irqreturn_t | 61 | static irqreturn_t |
25 | pxa_ost0_interrupt(int irq, void *dev_id) | 62 | pxa_ost0_interrupt(int irq, void *dev_id) |
26 | { | 63 | { |
@@ -152,6 +189,8 @@ static void __init pxa_timer_init(void) | |||
152 | OIER = 0; | 189 | OIER = 0; |
153 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; | 190 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; |
154 | 191 | ||
192 | set_oscr2ns_scale(CLOCK_TICK_RATE); | ||
193 | |||
155 | ckevt_pxa_osmr0.mult = | 194 | ckevt_pxa_osmr0.mult = |
156 | div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); | 195 | div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); |
157 | ckevt_pxa_osmr0.max_delta_ns = | 196 | ckevt_pxa_osmr0.max_delta_ns = |