diff options
| author | Nicolas Pitre <nico@cam.org> | 2005-09-01 07:48:48 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2005-09-01 07:48:48 -0400 |
| commit | 569d2c34dcf259b07977835492aa8813d1168230 (patch) | |
| tree | aa16ba481ff295b1cf7d0bafa503078bc54249a2 | |
| parent | 20e912680842504ab4633deaa644c2b855ad3d44 (diff) | |
[ARM] 2864/1: VST aka CONFIG_NO_IDLE_HZ support for SA11x0
Patch from Nicolas Pitre
Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
| -rw-r--r-- | arch/arm/Kconfig | 4 | ||||
| -rw-r--r-- | arch/arm/mach-sa1100/time.c | 51 |
2 files changed, 53 insertions, 2 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index dc0fafc7f9bd..68dfdba71d74 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -365,8 +365,8 @@ config NO_IDLE_HZ | |||
| 365 | 365 | ||
| 366 | Please note that dynamic tick may affect the accuracy of | 366 | Please note that dynamic tick may affect the accuracy of |
| 367 | timekeeping on some platforms depending on the implementation. | 367 | timekeeping on some platforms depending on the implementation. |
| 368 | Currently at least OMAP and PXA2xx platforms are known to have | 368 | Currently at least OMAP, PXA2xx and SA11x0 platforms are known |
| 369 | accurate timekeeping with dynamic tick. | 369 | to have accurate timekeeping with dynamic tick. |
| 370 | 370 | ||
| 371 | config ARCH_DISCONTIGMEM_ENABLE | 371 | config ARCH_DISCONTIGMEM_ENABLE |
| 372 | bool | 372 | bool |
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index a084b38698cf..47e0420623fc 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c | |||
| @@ -70,6 +70,11 @@ static unsigned long sa1100_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 | sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 79 | sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
| 75 | { | 80 | { |
| @@ -77,6 +82,13 @@ sa1100_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 | /* | 92 | /* |
| 81 | * Loop until we get ahead of the free running timer. | 93 | * Loop until we get ahead of the free running timer. |
| 82 | * This ensures an exact clock tick count and time accuracy. | 94 | * This ensures an exact clock tick count and time accuracy. |
| @@ -119,6 +131,42 @@ static void __init sa1100_timer_init(void) | |||
| 119 | OSCR = 0; /* initialize free-running timer, force first match */ | 131 | OSCR = 0; /* initialize free-running timer, force first match */ |
| 120 | } | 132 | } |
| 121 | 133 | ||
| 134 | #ifdef CONFIG_NO_IDLE_HZ | ||
| 135 | static int sa1100_dyn_tick_enable_disable(void) | ||
| 136 | { | ||
| 137 | /* nothing to do */ | ||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | static void sa1100_dyn_tick_reprogram(unsigned long ticks) | ||
| 142 | { | ||
| 143 | if (ticks > 1) { | ||
| 144 | initial_match = OSMR0; | ||
| 145 | OSMR0 = initial_match + ticks * LATCH; | ||
| 146 | match_posponed = 1; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | static irqreturn_t | ||
| 151 | sa1100_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs) | ||
| 152 | { | ||
| 153 | if (match_posponed) { | ||
| 154 | match_posponed = 0; | ||
| 155 | OSMR0 = initial_match; | ||
| 156 | if ((signed long)(initial_match - OSCR) <= 0) | ||
| 157 | return sa1100_timer_interrupt(irq, dev_id, regs); | ||
| 158 | } | ||
| 159 | return IRQ_NONE; | ||
| 160 | } | ||
| 161 | |||
| 162 | static struct dyn_tick_timer sa1100_dyn_tick = { | ||
| 163 | .enable = sa1100_dyn_tick_enable_disable, | ||
| 164 | .disable = sa1100_dyn_tick_enable_disable, | ||
| 165 | .reprogram = sa1100_dyn_tick_reprogram, | ||
| 166 | .handler = sa1100_dyn_tick_handler, | ||
| 167 | }; | ||
| 168 | #endif | ||
| 169 | |||
| 122 | #ifdef CONFIG_PM | 170 | #ifdef CONFIG_PM |
| 123 | unsigned long osmr[4], oier; | 171 | unsigned long osmr[4], oier; |
| 124 | 172 | ||
| @@ -155,4 +203,7 @@ struct sys_timer sa1100_timer = { | |||
| 155 | .suspend = sa1100_timer_suspend, | 203 | .suspend = sa1100_timer_suspend, |
| 156 | .resume = sa1100_timer_resume, | 204 | .resume = sa1100_timer_resume, |
| 157 | .offset = sa1100_gettimeoffset, | 205 | .offset = sa1100_gettimeoffset, |
| 206 | #ifdef CONFIG_NO_IDLE_HZ | ||
| 207 | .dyn_tick = &sa1100_dyn_tick, | ||
| 208 | #endif | ||
| 158 | }; | 209 | }; |
