summaryrefslogtreecommitdiffstats
path: root/arch/alpha/kernel/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha/kernel/time.c')
-rw-r--r--arch/alpha/kernel/time.c45
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();