diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2007-04-23 10:07:44 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2007-04-23 10:07:44 +0000 |
commit | b41a3dfa9ac078d78d5e49d89aa1b8c88bd26b8e (patch) | |
tree | 077e3660edff7dc47ef9d17f7e9f540955f173d8 /sys/arch | |
parent | 210b61e6bccd8bf072cc37c00135115aa80a1891 (diff) |
Switch alpha to timecounters.
We use rpcc for the clock. We don't try to get the frequency from the
hwrpb, since from experience we know that it's very unreliable and
can be several % off from the real frequency. Instead we calibrate
the timecounter frequency by using the clock device and count the
number of cycles between two second ticks of the clocks.
This is not perfect, but still much better than what we had before.
We'll have to add an i8254 clock for MP though.
miod@ ok
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/alpha/alpha/clock.c | 72 | ||||
-rw-r--r-- | sys/arch/alpha/alpha/machdep.c | 34 | ||||
-rw-r--r-- | sys/arch/alpha/include/_types.h | 3 |
3 files changed, 58 insertions, 51 deletions
diff --git a/sys/arch/alpha/alpha/clock.c b/sys/arch/alpha/alpha/clock.c index e828b9430ac..3813b19a840 100644 --- a/sys/arch/alpha/alpha/clock.c +++ b/sys/arch/alpha/alpha/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.14 2004/06/28 02:28:42 aaron Exp $ */ +/* $OpenBSD: clock.c,v 1.15 2007/04/23 10:07:43 art Exp $ */ /* $NetBSD: clock.c,v 1.29 2000/06/05 21:47:10 thorpej Exp $ */ /* @@ -44,6 +44,7 @@ #include <sys/systm.h> #include <sys/device.h> #include <sys/evcount.h> +#include <sys/timetc.h> #include <dev/clock_subr.h> @@ -75,6 +76,11 @@ int clockinitted; struct evcount clk_count; int clk_irq = 0; +u_int rpcc_get_timecount(struct timecounter *); +struct timecounter rpcc_timecounter = { + rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL +}; + void clockattach(dev, fns) struct device *dev; @@ -110,20 +116,17 @@ clockattach(dev, fns) * are no other timers available. */ void -cpu_initclocks() +cpu_initclocks(void) { + u_int32_t cycles_per_sec; + struct clocktime ct; + u_int32_t first_rpcc, second_rpcc; /* only lower 32 bits are valid */ + int first_sec; + if (clockfns == NULL) panic("cpu_initclocks: no clock attached"); tick = 1000000 / hz; /* number of microseconds between interrupts */ - tickfix = 1000000 - (hz * tick); - if (tickfix) { - int ftp; - - ftp = min(ffs(tickfix), ffs(hz)); - tickfix >>= (ftp - 1); - tickfixinterval = hz >> (ftp - 1); - } /* * Establish the clock interrupt; it's a special case. @@ -146,6 +149,30 @@ cpu_initclocks() * Get the clock started. */ (*clockfns->cf_init)(clockdev); + + /* + * Calibrate the cycle counter frequency. + */ + (*clockfns->cf_get)(clockdev, 0, &ct); + first_sec = ct.sec; + + /* Let the clock tick one second. */ + do { + first_rpcc = alpha_rpcc(); + (*clockfns->cf_get)(clockdev, 0, &ct); + } while (ct.sec == first_sec); + first_sec = ct.sec; + /* Let the clock tick one more second. */ + do { + second_rpcc = alpha_rpcc(); + (*clockfns->cf_get)(clockdev, 0, &ct); + } while (ct.sec == first_sec); + + cycles_per_sec = second_rpcc - first_rpcc; + + rpcc_timecounter.tc_frequency = cycles_per_sec; + + tc_init(&rpcc_timecounter); } /* @@ -167,14 +194,16 @@ setstatclockrate(newhz) * and the time of year clock (if any) provides the rest. */ void -inittodr(base) - time_t base; +inittodr(time_t base) { struct clocktime ct; int year; struct clock_ymdhms dt; time_t deltat; int badbase; + struct timespec ts; + + ts.tv_sec = ts.tv_nsec = 0; if (base < (MINYEAR-1970)*SECYR) { printf("WARNING: preposterous time in file system"); @@ -202,7 +231,7 @@ inittodr(base) * Believe the time in the file system for lack of * anything better, resetting the TODR. */ - time.tv_sec = base; + ts.tv_sec = base; if (!badbase) { printf("WARNING: preposterous clock chip time\n"); resettodr(); @@ -216,9 +245,9 @@ inittodr(base) dt.dt_hour = ct.hour; dt.dt_min = ct.min; dt.dt_sec = ct.sec; - time.tv_sec = clock_ymdhms_to_secs(&dt); + ts.tv_sec = clock_ymdhms_to_secs(&dt); #ifdef DEBUG - printf("=>%ld (%d)\n", time.tv_sec, base); + printf("=>%ld (%d)\n", ts.tv_sec, base); #endif if (!badbase) { @@ -226,15 +255,16 @@ inittodr(base) * See if we gained/lost two or more days; * if so, assume something is amiss. */ - deltat = time.tv_sec - base; + deltat = ts.tv_sec - base; if (deltat < 0) deltat = -deltat; if (deltat < 2 * SECDAY) return; printf("WARNING: clock %s %ld days", - time.tv_sec < base ? "lost" : "gained", + ts.tv_sec < base ? "lost" : "gained", (long)deltat / SECDAY); } + tc_setclock(&ts); bad: printf(" -- CHECK AND RESET THE DATE!\n"); } @@ -255,7 +285,7 @@ resettodr() if (!clockinitted) return; - clock_secs_to_ymdhms(time.tv_sec, &dt); + clock_secs_to_ymdhms(time_second, &dt); /* rt clock wants 2 digits */ ct.year = (dt.dt_year - UNIX_YEAR_OFFSET) % 100; @@ -272,3 +302,9 @@ resettodr() (*clockfns->cf_set)(clockdev, &ct); } + +u_int +rpcc_get_timecount(struct timecounter *tc) +{ + return alpha_rpcc(); +} diff --git a/sys/arch/alpha/alpha/machdep.c b/sys/arch/alpha/alpha/machdep.c index d7d2d43255c..3d600589dd7 100644 --- a/sys/arch/alpha/alpha/machdep.c +++ b/sys/arch/alpha/alpha/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.106 2007/04/18 16:53:19 martin Exp $ */ +/* $OpenBSD: machdep.c,v 1.107 2007/04/23 10:07:43 art Exp $ */ /* $NetBSD: machdep.c,v 1.210 2000/06/01 17:12:38 thorpej Exp $ */ /*- @@ -96,6 +96,7 @@ #ifdef SYSVMSG #include <sys/msg.h> #endif +#include <sys/timetc.h> #include <sys/mount.h> #include <sys/syscallargs.h> @@ -2007,37 +2008,6 @@ remrunqueue(p) } /* - * Return the best possible estimate of the time in the timeval - * to which tvp points. Unfortunately, we can't read the hardware registers. - * We guarantee that the time will be greater than the value obtained by a - * previous call. - */ -void -microtime(tvp) - register struct timeval *tvp; -{ - int s = splclock(); - static struct timeval lasttime; - - *tvp = time; -#ifdef notdef - tvp->tv_usec += clkread(); - while (tvp->tv_usec >= 1000000) { - tvp->tv_sec++; - tvp->tv_usec -= 1000000; - } -#endif - if (tvp->tv_sec == lasttime.tv_sec && - tvp->tv_usec <= lasttime.tv_usec && - (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { - tvp->tv_sec++; - tvp->tv_usec -= 1000000; - } - lasttime = *tvp; - splx(s); -} - -/* * Wait "n" microseconds. */ void diff --git a/sys/arch/alpha/include/_types.h b/sys/arch/alpha/include/_types.h index 6f005758e56..480e591a94a 100644 --- a/sys/arch/alpha/include/_types.h +++ b/sys/arch/alpha/include/_types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: _types.h,v 1.3 2007/04/21 21:37:09 martin Exp $ */ +/* $OpenBSD: _types.h,v 1.4 2007/04/23 10:07:43 art Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -122,5 +122,6 @@ typedef void * __wctype_t; #define __HAVE_DEVICE_REGISTER #define __HAVE_CPUINFO #define __HAVE_GENERIC_SOFT_INTERRUPTS +#define __HAVE_TIMECOUNTER #endif /* _ALPHA__TYPES_H_ */ |