diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2007-11-12 17:48:12 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-01-26 10:07:51 -0500 |
commit | 4ae7806f8b4bf9a1e74c82f3bd4e91d59bd3d697 (patch) | |
tree | 921c819cfa93d70a3e2c5bad328a20c24e3683b3 /arch/arm | |
parent | a88264c24c44924a549f3d596b86d611b7ee9909 (diff) |
[ARM] pxa: Don't wind OSCR backwards over suspend/resume
OSCR is supposed to monotonically increment; however restoring it
to a time prior to OSMR0 may result in it being wound backwards.
Instead, if OSMR0 is within the minimum expiry time, wind OSMR0
forwards.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-pxa/time.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 3c4abbf31803..ac0bbad35238 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c | |||
@@ -181,7 +181,7 @@ static void __init pxa_timer_init(void) | |||
181 | } | 181 | } |
182 | 182 | ||
183 | #ifdef CONFIG_PM | 183 | #ifdef CONFIG_PM |
184 | static unsigned long osmr[4], oier; | 184 | static unsigned long osmr[4], oier, oscr; |
185 | 185 | ||
186 | static void pxa_timer_suspend(void) | 186 | static void pxa_timer_suspend(void) |
187 | { | 187 | { |
@@ -190,23 +190,26 @@ static void pxa_timer_suspend(void) | |||
190 | osmr[2] = OSMR2; | 190 | osmr[2] = OSMR2; |
191 | osmr[3] = OSMR3; | 191 | osmr[3] = OSMR3; |
192 | oier = OIER; | 192 | oier = OIER; |
193 | oscr = OSCR; | ||
193 | } | 194 | } |
194 | 195 | ||
195 | static void pxa_timer_resume(void) | 196 | static void pxa_timer_resume(void) |
196 | { | 197 | { |
198 | /* | ||
199 | * Ensure that we have at least MIN_OSCR_DELTA between match | ||
200 | * register 0 and the OSCR, to guarantee that we will receive | ||
201 | * the one-shot timer interrupt. We adjust OSMR0 in preference | ||
202 | * to OSCR to guarantee that OSCR is monotonically incrementing. | ||
203 | */ | ||
204 | if (osmr[0] - oscr < MIN_OSCR_DELTA) | ||
205 | osmr[0] += MIN_OSCR_DELTA; | ||
206 | |||
197 | OSMR0 = osmr[0]; | 207 | OSMR0 = osmr[0]; |
198 | OSMR1 = osmr[1]; | 208 | OSMR1 = osmr[1]; |
199 | OSMR2 = osmr[2]; | 209 | OSMR2 = osmr[2]; |
200 | OSMR3 = osmr[3]; | 210 | OSMR3 = osmr[3]; |
201 | OIER = oier; | 211 | OIER = oier; |
202 | 212 | OSCR = oscr; | |
203 | /* | ||
204 | * OSCR0 is the system timer, which has to increase | ||
205 | * monotonically until it rolls over in hardware. The value | ||
206 | * (OSMR0 - LATCH) is OSCR0 at the most recent system tick, | ||
207 | * which is a handy value to restore to OSCR0. | ||
208 | */ | ||
209 | OSCR = OSMR0 - LATCH; | ||
210 | } | 213 | } |
211 | #else | 214 | #else |
212 | #define pxa_timer_suspend NULL | 215 | #define pxa_timer_suspend NULL |