diff options
Diffstat (limited to 'arch/arm/mach-pxa/time.c')
-rw-r--r-- | arch/arm/mach-pxa/time.c | 39 |
1 files changed, 39 insertions, 0 deletions
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 = |