diff options
Diffstat (limited to 'arch/alpha/kernel/time.c')
-rw-r--r-- | arch/alpha/kernel/time.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index 2f9363113..a84378926 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -18,6 +18,9 @@ * fixed tick loss calculation in timer_interrupt * (round system clock to nearest tick instead of truncating) * fixed algorithm in time_init for getting time from CMOS clock + * 1999-04-16 Thorsten Kranzkowski (dl8bcu@gmx.net) + * fixed algorithm in do_gettimeofday() for calculating the precise time + * from processor cycle counter (now taking lost_ticks into account) */ #include <linux/config.h> #include <linux/errno.h> @@ -223,7 +226,7 @@ time_init(void) { void (*irq_handler)(int, void *, struct pt_regs *); unsigned int year, mon, day, hour, min, sec, cc1, cc2; - unsigned long cycle_freq; + unsigned long cycle_freq, diff, one_percent; /* * The Linux interpretation of the CMOS clock register contents: @@ -237,19 +240,30 @@ time_init(void) /* Read cycle counter exactly on falling edge of update flag */ cc1 = rpcc(); - /* If our cycle frequency isn't valid, go another round and give - a guess at what it should be. */ - cycle_freq = hwrpb->cycle_freq; - if (cycle_freq == 0) { - printk("HWRPB cycle frequency bogus. Estimating... "); - + if (!est_cycle_freq) { + /* Sometimes the hwrpb->cycle_freq value is bogus. + Go another round to check up on it and see. */ do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); cc2 = rpcc(); - est_cycle_freq = cycle_freq = cc2 - cc1; + est_cycle_freq = cc2 - cc1; cc1 = cc2; + } - printk("%lu Hz\n", cycle_freq); + /* If the given value is within 1% of what we calculated, + accept it. Otherwise, use what we found. */ + cycle_freq = hwrpb->cycle_freq; + one_percent = cycle_freq / 100; + diff = cycle_freq - est_cycle_freq; + if (diff < 0) + diff = -diff; + if (diff > one_percent) { + cycle_freq = est_cycle_freq; + printk("HWRPB cycle frequency bogus. Estimated %lu Hz\n", + cycle_freq); + } + else { + est_cycle_freq = 0; } /* From John Bowman <bowman@math.ualberta.ca>: allow the values @@ -314,8 +328,10 @@ time_init(void) void do_gettimeofday(struct timeval *tv) { - unsigned long flags, now, delta_cycles, delta_usec; + unsigned long flags, delta_cycles, delta_usec; unsigned long sec, usec; + __u32 now; + extern volatile unsigned long lost_ticks; /*kernel/sched.c*/ now = rpcc(); save_and_cli(flags); @@ -337,9 +353,15 @@ do_gettimeofday(struct timeval *tv) * with no clear gain. */ - delta_usec = delta_cycles * state.scaled_ticks_per_cycle * 15625; + delta_usec = (delta_cycles * state.scaled_ticks_per_cycle + + state.partial_tick + + (lost_ticks << FIX_SHIFT) ) * 15625; delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2; + /* the 'lost_tics' term above implements this: + * delta_usec += lost_ticks * (1000000 / HZ); + */ + usec += delta_usec; if (usec >= 1000000) { sec += 1; @@ -357,7 +379,6 @@ do_settimeofday(struct timeval *tv) xtime = *tv; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; - time_state = TIME_ERROR; /* p. 24, (a) */ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; sti(); |