diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2007-11-12 22:48:12 +0000 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-01-26 15:07:51 +0000 |
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 3c4abbf3180..ac0bbad3523 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) } #ifdef CONFIG_PM -static unsigned long osmr[4], oier; +static unsigned long osmr[4], oier, oscr; static void pxa_timer_suspend(void) { @@ -190,23 +190,26 @@ static void pxa_timer_suspend(void) osmr[2] = OSMR2; osmr[3] = OSMR3; oier = OIER; + oscr = OSCR; } static void pxa_timer_resume(void) { + /* + * Ensure that we have at least MIN_OSCR_DELTA between match + * register 0 and the OSCR, to guarantee that we will receive + * the one-shot timer interrupt. We adjust OSMR0 in preference + * to OSCR to guarantee that OSCR is monotonically incrementing. + */ + if (osmr[0] - oscr < MIN_OSCR_DELTA) + osmr[0] += MIN_OSCR_DELTA; + OSMR0 = osmr[0]; OSMR1 = osmr[1]; OSMR2 = osmr[2]; OSMR3 = osmr[3]; OIER = oier; - - /* - * OSCR0 is the system timer, which has to increase - * monotonically until it rolls over in hardware. The value - * (OSMR0 - LATCH) is OSCR0 at the most recent system tick, - * which is a handy value to restore to OSCR0. - */ - OSCR = OSMR0 - LATCH; + OSCR = oscr; } #else #define pxa_timer_suspend NULL |