X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fmach-pxa%2Ftime.c;h=473fb6173f7210a3ac7561983f05a437c8b8f910;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=a49fc02994795611176cc9c24e410ccce7128526;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index a49fc0299..473fb6173 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -75,6 +75,8 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int next_match; + write_seqlock(&xtime_lock); + /* Loop until we get ahead of the free running timer. * This ensures an exact clock tick count and time accuracy. * IRQs are disabled inside the loop to ensure coherence between @@ -96,6 +98,8 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) next_match = (OSMR0 += LATCH); } while( (signed long)(next_match - OSCR) <= 8 ); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -105,11 +109,10 @@ static struct irqaction pxa_timer_irq = { .handler = pxa_timer_interrupt }; -void __init pxa_init_time(void) +static void __init pxa_timer_init(void) { struct timespec tv; - gettimeoffset = pxa_gettimeoffset; set_rtc = pxa_set_rtc; tv.tv_nsec = 0; @@ -123,3 +126,39 @@ void __init pxa_init_time(void) OSCR = 0; /* initialize free-running timer, force first match */ } +#ifdef CONFIG_PM +static unsigned long osmr[4], oier; + +static void pxa_timer_suspend(void) +{ + osmr[0] = OSMR0; + osmr[1] = OSMR1; + osmr[2] = OSMR2; + osmr[3] = OSMR3; + oier = OIER; +} + +static void pxa_timer_resume(void) +{ + OSMR0 = osmr[0]; + OSMR1 = osmr[1]; + OSMR2 = osmr[2]; + OSMR3 = osmr[3]; + OIER = oier; + + /* + * OSMR0 is the system timer: make sure OSCR is sufficiently behind + */ + OSCR = OSMR0 - LATCH; +} +#else +#define pxa_timer_suspend NULL +#define pxa_timer_resume NULL +#endif + +struct sys_timer pxa_timer = { + .init = pxa_timer_init, + .suspend = pxa_timer_suspend, + .resume = pxa_timer_resume, + .offset = pxa_gettimeoffset, +};