X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=arch%2Fxtensa%2Fkernel%2Ftime.c;h=8df1e842f6d401d060d077246d97d942c2033cad;hb=133e887f90208d339088dd60cb1d08a72ba27288;hp=4a2c365ba68464d32c03a4c6aa1c10c2e5b431d4;hpb=5f765b8d68fe99c8a575265d81c62382893e1e8a;p=linux-2.6-omap-h63xx.git diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 4a2c365ba68..8df1e842f6d 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -26,18 +26,15 @@ #include -extern volatile unsigned long wall_jiffies; - DEFINE_SPINLOCK(rtc_lock); EXPORT_SYMBOL(rtc_lock); #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT unsigned long ccount_per_jiffy; /* per 1/HZ */ -unsigned long ccount_nsec; /* nsec per ccount increment */ +unsigned long nsec_per_ccount; /* nsec per ccount increment */ #endif -unsigned int last_ccount_stamp; static long last_rtc_update = 0; /* @@ -49,10 +46,10 @@ unsigned long long sched_clock(void) return (unsigned long long)jiffies * (1000000000 / HZ); } -static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t timer_interrupt(int irq, void *dev_id); static struct irqaction timer_irqaction = { .handler = timer_interrupt, - .flags = SA_INTERRUPT, + .flags = IRQF_DISABLED, .name = "timer", }; @@ -80,7 +77,6 @@ void __init time_init(void) xtime.tv_nsec = 0; last_rtc_update = xtime.tv_sec = sec_n; - last_ccount_stamp = get_ccount(); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); @@ -96,7 +92,7 @@ int do_settimeofday(struct timespec *tv) { time_t wtm_sec, sec = tv->tv_sec; long wtm_nsec, nsec = tv->tv_nsec; - unsigned long ccount; + unsigned long delta; if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) return -EINVAL; @@ -108,9 +104,10 @@ int do_settimeofday(struct timespec *tv) * wall time. Discover what correction gettimeofday() would have * made, and then undo it! */ - ccount = get_ccount(); - nsec -= (ccount - last_ccount_stamp) * CCOUNT_NSEC; - nsec -= (jiffies - wall_jiffies) * CCOUNT_PER_JIFFY * CCOUNT_NSEC; + + delta = CCOUNT_PER_JIFFY; + delta += get_ccount() - get_linux_timer(); + nsec -= delta * NSEC_PER_CCOUNT; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); @@ -129,20 +126,21 @@ EXPORT_SYMBOL(do_settimeofday); void do_gettimeofday(struct timeval *tv) { unsigned long flags; - unsigned long sec, usec, delta, lost, seq; + unsigned long volatile sec, usec, delta, seq; do { seq = read_seqbegin_irqsave(&xtime_lock, flags); - delta = get_ccount() - last_ccount_stamp; sec = xtime.tv_sec; usec = (xtime.tv_nsec / NSEC_PER_USEC); - lost = jiffies - wall_jiffies; + delta = get_linux_timer() - get_ccount(); } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - usec += lost * (1000000UL/HZ) + (delta * CCOUNT_NSEC) / NSEC_PER_USEC; + usec += (((unsigned long) CCOUNT_PER_JIFFY - delta) + * (unsigned long) NSEC_PER_CCOUNT) / NSEC_PER_USEC; + for (; usec >= 1000000; sec++, usec -= 1000000) ; @@ -156,7 +154,7 @@ EXPORT_SYMBOL(do_gettimeofday); * The timer interrupt is called HZ times per second. */ -irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t timer_interrupt (int irq, void *dev_id) { unsigned long next; @@ -166,21 +164,23 @@ irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) again: while ((signed long)(get_ccount() - next) > 0) { - profile_tick(CPU_PROFILING, regs); + profile_tick(CPU_PROFILING); #ifndef CONFIG_SMP - update_process_times(user_mode(regs)); + update_process_times(user_mode(get_irq_regs())); #endif write_seqlock(&xtime_lock); - last_ccount_stamp = next; + do_timer(1); /* Linux handler in kernel/timer.c */ + + /* Note that writing CCOMPARE clears the interrupt. */ + next += CCOUNT_PER_JIFFY; - do_timer (regs); /* Linux handler in kernel/timer.c */ + set_linux_timer(next); if (ntp_synced() && xtime.tv_sec - last_rtc_update >= 659 && - abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ && - jiffies - wall_jiffies == 1) { + abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ) { if (platform_set_rtc_time(xtime.tv_sec+1) == 0) last_rtc_update = xtime.tv_sec+1; @@ -191,24 +191,20 @@ again: write_sequnlock(&xtime_lock); } - /* NOTE: writing CCOMPAREn clears the interrupt. */ + /* Allow platform to do something useful (Wdog). */ - set_linux_timer (next); + platform_heartbeat(); /* Make sure we didn't miss any tick... */ if ((signed long)(get_ccount() - next) > 0) goto again; - /* Allow platform to do something useful (Wdog). */ - - platform_heartbeat(); - return IRQ_HANDLED; } #ifndef CONFIG_GENERIC_CALIBRATE_DELAY -void __devinit calibrate_delay(void) +void __cpuinit calibrate_delay(void) { loops_per_jiffy = CCOUNT_PER_JIFFY; printk("Calibrating delay loop (skipped)... "