diff options
Diffstat (limited to 'arch/arm/mach-pxa/time.c')
| -rw-r--r-- | arch/arm/mach-pxa/time.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 98d27e646b09..ec4286c7931c 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c | |||
| @@ -16,10 +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> |
| 26 | #include <asm/mach-types.h> | ||
| 27 | |||
| 28 | /* | ||
| 29 | * This is PXA's sched_clock implementation. This has a resolution | ||
| 30 | * of at least 308 ns and a maximum value of 208 days. | ||
| 31 | * | ||
| 32 | * The return value is guaranteed to be monotonic in that range as | ||
| 33 | * long as there is always less than 582 seconds between successive | ||
| 34 | * calls to sched_clock() which should always be the case in practice. | ||
| 35 | */ | ||
| 36 | |||
| 37 | #define OSCR2NS_SCALE_FACTOR 10 | ||
| 38 | |||
| 39 | static unsigned long oscr2ns_scale; | ||
| 40 | |||
| 41 | static void __init set_oscr2ns_scale(unsigned long oscr_rate) | ||
| 42 | { | ||
| 43 | unsigned long long v = 1000000000ULL << OSCR2NS_SCALE_FACTOR; | ||
| 44 | do_div(v, oscr_rate); | ||
| 45 | oscr2ns_scale = v; | ||
| 46 | /* | ||
| 47 | * We want an even value to automatically clear the top bit | ||
| 48 | * returned by cnt32_to_63() without an additional run time | ||
| 49 | * instruction. So if the LSB is 1 then round it up. | ||
| 50 | */ | ||
| 51 | if (oscr2ns_scale & 1) | ||
| 52 | oscr2ns_scale++; | ||
| 53 | } | ||
| 54 | |||
| 55 | unsigned long long sched_clock(void) | ||
| 56 | { | ||
| 57 | unsigned long long v = cnt32_to_63(OSCR); | ||
| 58 | return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR; | ||
| 59 | } | ||
| 60 | |||
| 23 | 61 | ||
| 24 | static irqreturn_t | 62 | static irqreturn_t |
| 25 | pxa_ost0_interrupt(int irq, void *dev_id) | 63 | pxa_ost0_interrupt(int irq, void *dev_id) |
| @@ -149,18 +187,29 @@ static struct irqaction pxa_ost0_irq = { | |||
| 149 | 187 | ||
| 150 | static void __init pxa_timer_init(void) | 188 | static void __init pxa_timer_init(void) |
| 151 | { | 189 | { |
| 190 | unsigned long clock_tick_rate; | ||
| 191 | |||
| 152 | OIER = 0; | 192 | OIER = 0; |
| 153 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; | 193 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; |
| 154 | 194 | ||
| 195 | if (cpu_is_pxa21x() || cpu_is_pxa25x()) | ||
| 196 | clock_tick_rate = 3686400; | ||
| 197 | else if (machine_is_mainstone()) | ||
| 198 | clock_tick_rate = 3249600; | ||
| 199 | else | ||
| 200 | clock_tick_rate = 3250000; | ||
| 201 | |||
| 202 | set_oscr2ns_scale(clock_tick_rate); | ||
| 203 | |||
| 155 | ckevt_pxa_osmr0.mult = | 204 | ckevt_pxa_osmr0.mult = |
| 156 | div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); | 205 | div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); |
| 157 | ckevt_pxa_osmr0.max_delta_ns = | 206 | ckevt_pxa_osmr0.max_delta_ns = |
| 158 | clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); | 207 | clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); |
| 159 | ckevt_pxa_osmr0.min_delta_ns = | 208 | ckevt_pxa_osmr0.min_delta_ns = |
| 160 | clockevent_delta2ns(MIN_OSCR_DELTA, &ckevt_pxa_osmr0) + 1; | 209 | clockevent_delta2ns(MIN_OSCR_DELTA, &ckevt_pxa_osmr0) + 1; |
| 161 | 210 | ||
| 162 | cksrc_pxa_oscr0.mult = | 211 | cksrc_pxa_oscr0.mult = |
| 163 | clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_pxa_oscr0.shift); | 212 | clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift); |
| 164 | 213 | ||
| 165 | setup_irq(IRQ_OST0, &pxa_ost0_irq); | 214 | setup_irq(IRQ_OST0, &pxa_ost0_irq); |
| 166 | 215 | ||
