diff options
author | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-02 03:52:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-02 03:52:05 -0400 |
commit | 66f3767376e2bbffb4c2c78ea171e1fdcb62201b (patch) | |
tree | 2006a0d4e087d34b4f8767574e36946c0254fbbc /arch/arm/mach-pxa/time.c | |
parent | 5d8c397f304e1363f8ff9749b08172eb59e6534a (diff) | |
parent | 86a8a83963a3f6beeca4900d26da93c7d2a9d92d (diff) |
Merge HEAD from master.kernel.org:/home/rmk/linux-2.6-arm
Diffstat (limited to 'arch/arm/mach-pxa/time.c')
-rw-r--r-- | arch/arm/mach-pxa/time.c | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 6e5202154f91..7dad3f1465e0 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c | |||
@@ -70,6 +70,11 @@ static unsigned long pxa_gettimeoffset (void) | |||
70 | return usec; | 70 | return usec; |
71 | } | 71 | } |
72 | 72 | ||
73 | #ifdef CONFIG_NO_IDLE_HZ | ||
74 | static unsigned long initial_match; | ||
75 | static int match_posponed; | ||
76 | #endif | ||
77 | |||
73 | static irqreturn_t | 78 | static irqreturn_t |
74 | pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 79 | pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
75 | { | 80 | { |
@@ -77,11 +82,19 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
77 | 82 | ||
78 | write_seqlock(&xtime_lock); | 83 | write_seqlock(&xtime_lock); |
79 | 84 | ||
85 | #ifdef CONFIG_NO_IDLE_HZ | ||
86 | if (match_posponed) { | ||
87 | match_posponed = 0; | ||
88 | OSMR0 = initial_match; | ||
89 | } | ||
90 | #endif | ||
91 | |||
80 | /* Loop until we get ahead of the free running timer. | 92 | /* Loop until we get ahead of the free running timer. |
81 | * This ensures an exact clock tick count and time accuracy. | 93 | * This ensures an exact clock tick count and time accuracy. |
82 | * IRQs are disabled inside the loop to ensure coherence between | 94 | * Since IRQs are disabled at this point, coherence between |
83 | * lost_ticks (updated in do_timer()) and the match reg value, so we | 95 | * lost_ticks(updated in do_timer()) and the match reg value is |
84 | * can use do_gettimeofday() from interrupt handlers. | 96 | * ensured, hence we can use do_gettimeofday() from interrupt |
97 | * handlers. | ||
85 | * | 98 | * |
86 | * HACK ALERT: it seems that the PXA timer regs aren't updated right | 99 | * HACK ALERT: it seems that the PXA timer regs aren't updated right |
87 | * away in all cases when a write occurs. We therefore compare with | 100 | * away in all cases when a write occurs. We therefore compare with |
@@ -126,6 +139,42 @@ static void __init pxa_timer_init(void) | |||
126 | OSCR = 0; /* initialize free-running timer, force first match */ | 139 | OSCR = 0; /* initialize free-running timer, force first match */ |
127 | } | 140 | } |
128 | 141 | ||
142 | #ifdef CONFIG_NO_IDLE_HZ | ||
143 | static int pxa_dyn_tick_enable_disable(void) | ||
144 | { | ||
145 | /* nothing to do */ | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static void pxa_dyn_tick_reprogram(unsigned long ticks) | ||
150 | { | ||
151 | if (ticks > 1) { | ||
152 | initial_match = OSMR0; | ||
153 | OSMR0 = initial_match + ticks * LATCH; | ||
154 | match_posponed = 1; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | static irqreturn_t | ||
159 | pxa_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
160 | { | ||
161 | if (match_posponed) { | ||
162 | match_posponed = 0; | ||
163 | OSMR0 = initial_match; | ||
164 | if ( (signed long)(initial_match - OSCR) <= 8 ) | ||
165 | return pxa_timer_interrupt(irq, dev_id, regs); | ||
166 | } | ||
167 | return IRQ_NONE; | ||
168 | } | ||
169 | |||
170 | static struct dyn_tick_timer pxa_dyn_tick = { | ||
171 | .enable = pxa_dyn_tick_enable_disable, | ||
172 | .disable = pxa_dyn_tick_enable_disable, | ||
173 | .reprogram = pxa_dyn_tick_reprogram, | ||
174 | .handler = pxa_dyn_tick_handler, | ||
175 | }; | ||
176 | #endif | ||
177 | |||
129 | #ifdef CONFIG_PM | 178 | #ifdef CONFIG_PM |
130 | static unsigned long osmr[4], oier; | 179 | static unsigned long osmr[4], oier; |
131 | 180 | ||
@@ -161,4 +210,7 @@ struct sys_timer pxa_timer = { | |||
161 | .suspend = pxa_timer_suspend, | 210 | .suspend = pxa_timer_suspend, |
162 | .resume = pxa_timer_resume, | 211 | .resume = pxa_timer_resume, |
163 | .offset = pxa_gettimeoffset, | 212 | .offset = pxa_gettimeoffset, |
213 | #ifdef CONFIG_NO_IDLE_HZ | ||
214 | .dyn_tick = &pxa_dyn_tick, | ||
215 | #endif | ||
164 | }; | 216 | }; |