aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-pxa/time.c')
-rw-r--r--arch/arm/mach-pxa/time.c52
1 files changed, 27 insertions, 25 deletions
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 3ac268fa419b..ee2beb400414 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -18,6 +18,7 @@
18#include <linux/signal.h> 18#include <linux/signal.h>
19#include <linux/errno.h> 19#include <linux/errno.h>
20#include <linux/sched.h> 20#include <linux/sched.h>
21#include <linux/clocksource.h>
21 22
22#include <asm/system.h> 23#include <asm/system.h>
23#include <asm/hardware.h> 24#include <asm/hardware.h>
@@ -48,27 +49,6 @@ static int pxa_set_rtc(void)
48 return 0; 49 return 0;
49} 50}
50 51
51/* IRQs are disabled before entering here from do_gettimeofday() */
52static unsigned long pxa_gettimeoffset (void)
53{
54 long ticks_to_match, elapsed, usec;
55
56 /* Get ticks before next timer match */
57 ticks_to_match = OSMR0 - OSCR;
58
59 /* We need elapsed ticks since last match */
60 elapsed = LATCH - ticks_to_match;
61
62 /* don't get fooled by the workaround in pxa_timer_interrupt() */
63 if (elapsed <= 0)
64 return 0;
65
66 /* Now convert them to usec */
67 usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
68
69 return usec;
70}
71
72#ifdef CONFIG_NO_IDLE_HZ 52#ifdef CONFIG_NO_IDLE_HZ
73static unsigned long initial_match; 53static unsigned long initial_match;
74static int match_posponed; 54static int match_posponed;
@@ -121,9 +101,24 @@ static struct irqaction pxa_timer_irq = {
121 .handler = pxa_timer_interrupt, 101 .handler = pxa_timer_interrupt,
122}; 102};
123 103
104static cycle_t pxa_get_cycles(void)
105{
106 return OSCR;
107}
108
109static struct clocksource clocksource_pxa = {
110 .name = "pxa_timer",
111 .rating = 200,
112 .read = pxa_get_cycles,
113 .mask = CLOCKSOURCE_MASK(32),
114 .shift = 20,
115 .is_continuous = 1,
116};
117
124static void __init pxa_timer_init(void) 118static void __init pxa_timer_init(void)
125{ 119{
126 struct timespec tv; 120 struct timespec tv;
121 unsigned long flags;
127 122
128 set_rtc = pxa_set_rtc; 123 set_rtc = pxa_set_rtc;
129 124
@@ -132,12 +127,20 @@ static void __init pxa_timer_init(void)
132 do_settimeofday(&tv); 127 do_settimeofday(&tv);
133 128
134 OIER = 0; /* disable any timer interrupts */ 129 OIER = 0; /* disable any timer interrupts */
135 OSCR = LATCH*2; /* push OSCR out of the way */
136 OSMR0 = LATCH; /* set initial match */
137 OSSR = 0xf; /* clear status on all timers */ 130 OSSR = 0xf; /* clear status on all timers */
138 setup_irq(IRQ_OST0, &pxa_timer_irq); 131 setup_irq(IRQ_OST0, &pxa_timer_irq);
132 local_irq_save(flags);
139 OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */ 133 OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */
140 OSCR = 0; /* initialize free-running timer */ 134 OSMR0 = OSCR + LATCH; /* set initial match */
135 local_irq_restore(flags);
136
137 /*
138 * OSCR runs continuously on PXA and is not written to,
139 * so we can use it as clock source directly.
140 */
141 clocksource_pxa.mult =
142 clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_pxa.shift);
143 clocksource_register(&clocksource_pxa);
141} 144}
142 145
143#ifdef CONFIG_NO_IDLE_HZ 146#ifdef CONFIG_NO_IDLE_HZ
@@ -210,7 +213,6 @@ struct sys_timer pxa_timer = {
210 .init = pxa_timer_init, 213 .init = pxa_timer_init,
211 .suspend = pxa_timer_suspend, 214 .suspend = pxa_timer_suspend,
212 .resume = pxa_timer_resume, 215 .resume = pxa_timer_resume,
213 .offset = pxa_gettimeoffset,
214#ifdef CONFIG_NO_IDLE_HZ 216#ifdef CONFIG_NO_IDLE_HZ
215 .dyn_tick = &pxa_dyn_tick, 217 .dyn_tick = &pxa_dyn_tick,
216#endif 218#endif