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.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 6e5202154f91..72b15e9a373a 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
74static unsigned long initial_match;
75static int match_posponed;
76#endif
77
73static irqreturn_t 78static irqreturn_t
74pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 79pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
75{ 80{
@@ -77,6 +82,13 @@ 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 * IRQs are disabled inside the loop to ensure coherence between
@@ -126,6 +138,42 @@ static void __init pxa_timer_init(void)
126 OSCR = 0; /* initialize free-running timer, force first match */ 138 OSCR = 0; /* initialize free-running timer, force first match */
127} 139}
128 140
141#ifdef CONFIG_NO_IDLE_HZ
142static int pxa_dyn_tick_enable_disable(void)
143{
144 /* nothing to do */
145 return 0;
146}
147
148static void pxa_dyn_tick_reprogram(unsigned long ticks)
149{
150 if (ticks > 1) {
151 initial_match = OSMR0;
152 OSMR0 = initial_match + ticks * LATCH;
153 match_posponed = 1;
154 }
155}
156
157static irqreturn_t
158pxa_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
159{
160 if (match_posponed) {
161 match_posponed = 0;
162 OSMR0 = initial_match;
163 if ( (signed long)(initial_match - OSCR) <= 8 )
164 return pxa_timer_interrupt(irq, dev_id, regs);
165 }
166 return IRQ_NONE;
167}
168
169static struct dyn_tick_timer pxa_dyn_tick = {
170 .enable = pxa_dyn_tick_enable_disable,
171 .disable = pxa_dyn_tick_enable_disable,
172 .reprogram = pxa_dyn_tick_reprogram,
173 .handler = pxa_dyn_tick_handler,
174};
175#endif
176
129#ifdef CONFIG_PM 177#ifdef CONFIG_PM
130static unsigned long osmr[4], oier; 178static unsigned long osmr[4], oier;
131 179
@@ -161,4 +209,7 @@ struct sys_timer pxa_timer = {
161 .suspend = pxa_timer_suspend, 209 .suspend = pxa_timer_suspend,
162 .resume = pxa_timer_resume, 210 .resume = pxa_timer_resume,
163 .offset = pxa_gettimeoffset, 211 .offset = pxa_gettimeoffset,
212#ifdef CONFIG_NO_IDLE_HZ
213 .dyn_tick = &pxa_dyn_tick,
214#endif
164}; 215};