X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fmach-sa1100%2Ftime.c;h=19b0c0fd63772085cf37e3ae51232e2e32fa9324;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=1c3d082f8d491561c1a2e8b3c81f2eb673d6e229;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 1c3d082f8..19b0c0fd6 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -84,12 +84,16 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned int next_match; + write_seqlock(&xtime_lock); + do { timer_tick(regs); OSSR = OSSR_M0; /* Clear match on timer 0 */ next_match = (OSMR0 += LATCH); } while ((signed long)(next_match - OSCR) <= 0); + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; } @@ -99,11 +103,10 @@ static struct irqaction sa1100_timer_irq = { .handler = sa1100_timer_interrupt }; -void __init sa1100_init_time(void) +static void __init sa1100_timer_init(void) { struct timespec tv; - gettimeoffset = sa1100_gettimeoffset; set_rtc = sa1100_set_rtc; tv.tv_nsec = 0; @@ -117,3 +120,40 @@ void __init sa1100_init_time(void) OSCR = 0; /* initialize free-running timer, force first match */ } +#ifdef CONFIG_PM +unsigned long osmr[4], oier; + +static void sa1100_timer_suspend(void) +{ + osmr[0] = OSMR0; + osmr[1] = OSMR1; + osmr[2] = OSMR2; + osmr[3] = OSMR3; + oier = OIER; +} + +static void sa1100_timer_resume(void) +{ + OSSR = 0x0f; + 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 sa1100_timer_suspend NULL +#define sa1100_timer_resume NULL +#endif + +struct sys_timer sa1100_timer = { + .init = sa1100_timer_init, + .suspend = sa1100_timer_suspend, + .resume = sa1100_timer_resume, + .offset = sa1100_gettimeoffset, +};