summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2007-04-13 18:48:39 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2007-04-13 18:48:39 +0000
commit8359a21404ea2d54efab7d672ceb2d364b054ebf (patch)
tree94dfd0f14a587c72b298e275f0aea8ef513dce03
parentaeed09682d670db93b1f23228d1df88ae910fdc3 (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.c112
-rw-r--r--sys/arch/powerpc/include/_types.h3
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_ */