diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2007-04-13 18:48:39 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2007-04-13 18:48:39 +0000 |
commit | 8359a21404ea2d54efab7d672ceb2d364b054ebf (patch) | |
tree | 94dfd0f14a587c72b298e275f0aea8ef513dce03 | |
parent | aeed09682d670db93b1f23228d1df88ae910fdc3 (diff) |
Timecounters for macppc. As clean and simple as sparc64. Uses the %tb
special register.
ok drahn@
-rw-r--r-- | sys/arch/macppc/macppc/clock.c | 112 | ||||
-rw-r--r-- | sys/arch/powerpc/include/_types.h | 3 |
2 files changed, 59 insertions, 56 deletions
diff --git a/sys/arch/macppc/macppc/clock.c b/sys/arch/macppc/macppc/clock.c index 71cdb2f332b..cc981575063 100644 --- a/sys/arch/macppc/macppc/clock.c +++ b/sys/arch/macppc/macppc/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.18 2007/03/20 20:59:54 kettenis Exp $ */ +/* $OpenBSD: clock.c,v 1.19 2007/04/13 18:48:38 kettenis Exp $ */ /* $NetBSD: clock.c,v 1.1 1996/09/30 16:34:40 ws Exp $ */ /* @@ -36,6 +36,7 @@ #include <sys/kernel.h> #include <sys/systm.h> #include <sys/evcount.h> +#include <sys/timetc.h> #include <machine/autoconf.h> #include <machine/pio.h> @@ -44,10 +45,8 @@ #include <machine/powerpc.h> #include <dev/ofw/openfirm.h> -void resettodr(void); - -/* XXX, called from asm code */ void decr_intr(struct clockframe *frame); +u_int tb_get_timecount(struct timecounter *); /* * Initially we assume a processor with a bus frequency of 12.5 MHz. @@ -57,7 +56,9 @@ static u_int32_t ns_per_tick = 320; static int32_t ticks_per_intr; static volatile u_int64_t lasttb; -#define SECYR (SECDAY * 365) +static struct timecounter tb_timecounter = { + tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL +}; time_read_t *time_read; time_write_t *time_write; @@ -76,18 +77,15 @@ static int clk_irq = PPC_CLK_IRQ; static int stat_irq = PPC_STAT_IRQ; /* - * For now we let the machine run with boot time, not changing the clock - * at inittodr at all. - * - * We might continue to do this due to setting up the real wall clock with - * a user level utility in the future. + * Set up the system's time, given a `reasonable' time value. */ - -/* ARGSUSED */ void inittodr(time_t base) { int badbase = 0, waszero = base == 0; + char *bad = NULL; + struct timeval tv; + struct timespec ts; if (base < 5 * SECYR) { /* @@ -104,43 +102,54 @@ inittodr(time_t base) if (time_read != NULL) { u_int32_t cursec; (*time_read)(&cursec); - time.tv_sec = cursec; + tv.tv_sec = cursec; + tv.tv_usec = 0; } else { /* force failure */ - time.tv_sec = 0; + tv.tv_sec = tv.tv_usec = 0; } - if (time.tv_sec == 0) { - printf("WARNING: unable to get date/time"); + if (tv.tv_sec == 0) { /* * Believe the time in the file system for lack of * anything better, resetting the clock. */ - time.tv_sec = base; + bad = "WARNING: unable to get date/time"; + tv.tv_sec = base; + tv.tv_usec = 0; if (!badbase) resettodr(); } else { int deltat; - time.tv_sec += tz.tz_minuteswest * 60; + tv.tv_sec += tz.tz_minuteswest * 60; if (tz.tz_dsttime) - time.tv_sec -= 3600; + tv.tv_sec -= 3600; - deltat = time.tv_sec - base; + deltat = tv.tv_sec - base; if (deltat < 0) deltat = -deltat; - if (waszero || deltat < 2 * SECDAY) - return; - printf("WARNING: clock %s %d days", - time.tv_sec < base ? "lost" : "gained", deltat / SECDAY); - - if (time.tv_sec < base && deltat > 1000 * SECDAY) { - printf(", using FS time"); - time.tv_sec = base; + if (!(waszero || deltat < 2 * SECDAY)) { + printf("WARNING: clock %s %d days", + tv.tv_sec < base ? "lost" : "gained", deltat / SECDAY); + bad = ""; + + if (tv.tv_sec < base && deltat > 1000 * SECDAY) { + printf(", using FS time"); + tv.tv_sec = base; + } } } - printf(" -- CHECK AND RESET THE DATE!\n"); + + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + tc_setclock(&ts); + + if (bad) { + printf("%s", bad); + printf(" -- CHECK AND RESET THE DATE!\n"); + } } /* @@ -149,13 +158,19 @@ inittodr(time_t base) void resettodr(void) { - struct timeval curtime = time; + struct timeval tv; + + if (time_second == 0) + return; + + microtime(&tv); + if (time_write != NULL) { - curtime.tv_sec -= tz.tz_minuteswest * 60; + tv.tv_sec -= tz.tz_minuteswest * 60; if (tz.tz_dsttime) { - curtime.tv_sec += 3600; + tv.tv_sec += 3600; } - (*time_write)(curtime.tv_sec); + (*time_write)(tv.tv_sec); } } @@ -293,6 +308,9 @@ cpu_initclocks() evcount_attach(&clk_count, "clock", (void *)&clk_irq, &evcount_intr); evcount_attach(&stat_count, "stat", (void *)&stat_irq, &evcount_intr); + tb_timecounter.tc_frequency = ticks_per_sec; + tc_init(&tb_timecounter); + ppc_mtdec(nextevent-lasttb); ppc_intr_enable(intrstate); } @@ -335,28 +353,6 @@ calc_delayconst(void) } /* - * Fill in *tvp with current time with microsecond resolution. - */ -void -microtime(struct timeval *tvp) -{ - u_int64_t tb; - u_int32_t ticks; - int s; - - s = ppc_intr_disable(); - tb = ppc_mftb(); - ticks = ((tb - lasttb) * ns_per_tick) / 1000; - *tvp = time; - ppc_intr_enable(s); - tvp->tv_usec += ticks; - while (tvp->tv_usec >= 1000000) { - tvp->tv_usec -= 1000000; - tvp->tv_sec++; - } -} - -/* * Wait for about n microseconds (us) (at least!). */ void @@ -400,3 +396,9 @@ setstatclockrate(int newhz) * to the new frequency. Rather than switching instantly. */ } + +u_int +tb_get_timecount(struct timecounter *tc) +{ + return ppc_mftbl(); +} diff --git a/sys/arch/powerpc/include/_types.h b/sys/arch/powerpc/include/_types.h index 2704dabf203..b0d801a32f6 100644 --- a/sys/arch/powerpc/include/_types.h +++ b/sys/arch/powerpc/include/_types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: _types.h,v 1.4 2007/03/22 19:26:28 kettenis Exp $ */ +/* $OpenBSD: _types.h,v 1.5 2007/04/13 18:48:38 kettenis Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -118,5 +118,6 @@ typedef void * __wctype_t; /* Feature test macros */ #define __HAVE_CPUINFO #define __HAVE_MUTEX +#define __HAVE_TIMECOUNTER #endif /* _POWERPC__TYPES_H_ */ |