Subject: timecounters and todr for hpcmips
To: None <port-hpcmips@NetBSD.org>
From: Garrett D'Amore <garrett_damore@tadpole.com>
List: port-hpcmips
Date: 09/13/2006 12:48:42
This is a multi-part message in MIME format.
--------------070809010906060003050600
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Attached find a patch which converts the hpcmips port to timecounters
and todr.  I've not tested it, so I'm looking for people to do so.  (It
does build, at least.)

The following things are noteworthy:

    1) tx39 systems do not appear to have a battery backed clock (or at
least the old code didn't assume one), so they will not see the standard
warning about "no TOD clock present", and will use the filesystem time
(which they always did before).

    2) tx39 systems get a 32kHz timecounter, hopefully giving a much
better estimate for microtime().  The tc is called "tx39rtc", and is
based of the 32kHz RTC.

    3) vrXX systems have an RTC, but appear to have used weird rules for
it -- e.g. an EPOCH starting in 1850.  I've rewritten most of that code
to be simpler, but I'd REALLY appreciate if folks could test.  One side
benefit of these changes is that the RTC will be retrieved and updated
with 1/32 sec accuracy.  (The old code was pretty hairy.)  Note that the
epoch base for some systems (LROUTER as an example) is 1/1/1970, whereas
for others it is 1/1/1850 (Windows CE legacy, I guess).

    4) vrXX get a 32kHz timecounter as well, called "vrrtc", also based
of the 32kHz RTC.

Again, please test it.  src/regress/sys/kern/time is an excellent test. 
So is date; /usr/bin/time sleep 10; date.

To test TODR, make sure the system gets a good time-of-day on boot, and
that it is retained properly across a reboot.  (Ideally without NTP
correction.)

Thanks again!

-- 
Garrett D'Amore, Principal Software Engineer
Tadpole Computer / Computing Technologies Division,
General Dynamics C4 Systems
http://www.tadpolecomputer.com/
Phone: 951 325-2134  Fax: 951 325-2191


--------------070809010906060003050600
Content-Type: text/x-patch;
 name="hpcmips.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="hpcmips.diff"

Index: sys/arch/hpcmips/conf/LROUTER
===================================================================
RCS file: /cvsroot/src/sys/arch/hpcmips/conf/LROUTER,v
retrieving revision 1.34
diff -d -p -u -r1.34 LROUTER
--- sys/arch/hpcmips/conf/LROUTER	26 Aug 2006 20:26:45 -0000	1.34
+++ sys/arch/hpcmips/conf/LROUTER	13 Sep 2006 19:48:33 -0000
@@ -39,7 +39,6 @@ options 	USERCONF		# userconf(4) support
 
 #options 	SCSIVERBOSE		# human readable SCSI error messages
 
-options 	YBASE=2000
 options 	EPOCHYEAR=1970
 
 #options 	RTC_OFFSET=0	# hardware clock is this many mins. west of GMT
Index: sys/arch/hpcmips/conf/std.lcard
===================================================================
RCS file: /cvsroot/src/sys/arch/hpcmips/conf/std.lcard,v
retrieving revision 1.6
diff -d -p -u -r1.6 std.lcard
--- sys/arch/hpcmips/conf/std.lcard	11 Dec 2005 12:17:33 -0000	1.6
+++ sys/arch/hpcmips/conf/std.lcard	13 Sep 2006 19:48:33 -0000
@@ -17,7 +17,6 @@ options		NO_SYMBOLSZ_ENTRY
 
 options 	VR4181			# NEC VR4181
 
-options		YBASE=2000
 options		EPOCHYEAR=1970
 
 mainbus0	at root
Index: sys/arch/hpcmips/hpcmips/clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/hpcmips/hpcmips/clock.c,v
retrieving revision 1.18
diff -d -p -u -r1.18 clock.c
--- sys/arch/hpcmips/hpcmips/clock.c	11 Dec 2005 12:17:33 -0000	1.18
+++ sys/arch/hpcmips/hpcmips/clock.c	13 Sep 2006 19:48:33 -0000
@@ -115,9 +115,6 @@ __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.
 #include <dev/clock_subr.h>
 #include <machine/sysconf.h>		/* platform */
 
-#define MINYEAR			2002	/* "today" */
-#define UNIX_YEAR_OFFSET	0
-
 /* 
  * platform_clock_attach:
  *
@@ -150,15 +147,6 @@ cpu_initclocks()
 
 	hz = clock->hz;
 	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);
-	}
 
 	/* start periodic timer */
 	(*clock->init)(clock->self);
@@ -179,152 +167,6 @@ setstatclockrate(int newhz)
 }
 
 /*
- * inittodr:
- *
- *	initializes the time of day hardware which provides
- *	date functions.  Its primary function is to use some file
- *	system information in case the hardare clock lost state.
- *
- *	Initialze the time of day register, based on the time base which is,
- *	e.g. from a filesystem.  Base provides the time to within six months,
- *	and the time of year clock (if any) provides the rest.
- */
-void
-inittodr(time_t base)
-{
-	struct platform_clock *clock = platform.clock;
-	struct clock_ymdhms dt;
-	int year, badbase;
-	time_t deltat;
-
-	if (clock == NULL)
-		panic("inittodr: no clock attached");		
-
-	if (base < (MINYEAR - 1970) * SECYR) {
-		printf("WARNING: preposterous time in file system");
-		/* read the system clock anyway */
-		base = (MINYEAR - 1970) * SECYR;
-		badbase = 1;
-	} else
-		badbase = 0;
-
-	(*clock->rtc_get)(clock->self, base, &dt);
-#ifdef DEBUG
-	printf("readclock: %d/%d/%d/%d/%d/%d", dt.dt_year, dt.dt_mon, dt.dt_day,
-	    dt.dt_hour, dt.dt_min, dt.dt_sec);
-#endif
-	clock->start = 1;
-
-	year = 1900 + UNIX_YEAR_OFFSET + dt.dt_year;
-	if (year < 1970)
-		year += 100;
-	/* simple sanity checks (2037 = time_t overflow) */
-	if (year < MINYEAR || year > 2037 ||
-	    dt.dt_mon < 1 || dt.dt_mon > 12 || dt.dt_day < 1 ||
-	    dt.dt_day > 31 || dt.dt_hour > 23 || dt.dt_min > 59 ||
-	    dt.dt_sec > 59) {
-		/*
-		 * Believe the time in the file system for lack of
-		 * anything better, resetting the TODR.
-		 */
-		time.tv_sec = base;
-		if (!badbase) {
-			printf("WARNING: preposterous clock chip time\n");
-			resettodr();
-		}
-		goto bad;
-	}
-
-	dt.dt_year = year;
-	time.tv_sec = clock_ymdhms_to_secs(&dt);
-#ifdef DEBUG
-	printf("=>%ld (%ld)\n", time.tv_sec, base);
-#endif
-
-	if (!badbase) {
-		/*
-		 * See if we gained/lost two or more days;
-		 * if so, assume something is amiss.
-		 */
-		deltat = time.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",
-		    (long)deltat / SECDAY);
-	}
- bad:
-	printf(" -- CHECK AND RESET THE DATE!\n");
-}
-
-/*
- * resettodr:
- *
- *	restores the time of day hardware after a time change.
- *
- *	Reset the TODR based on the time value; used when the TODR
- *	has a preposterous value and also when the time is reset
- *	by the stime system call.  Also called when the TODR goes past
- *	TODRZERO + 100*(SECYEAR+2*SECDAY) (e.g. on Jan 2 just after midnight)
- *	to wrap the TODR around.
- */
-void
-resettodr()
-{
-	struct platform_clock *clock = platform.clock;
-	struct clock_ymdhms dt;
-
-	if (clock == NULL)
-		panic("inittodr: no clock attached");		
-
-	if (!clock->start)
-		return;
-
-	clock_secs_to_ymdhms(time.tv_sec, &dt);
-
-	/* rt clock wants 2 digits XXX */
-	dt.dt_year = (dt.dt_year - UNIX_YEAR_OFFSET) % 100;
-#ifdef DEBUG
-	printf("setclock: %d/%d/%d/%d/%d/%d\n", dt.dt_year, dt.dt_mon,
-	    dt.dt_day, dt.dt_hour, dt.dt_min, dt.dt_sec);
-#endif
-
-	(*clock->rtc_set)(clock->self, &dt);
-}
-
-/*
- * microtime:
- *
- *	Return the best possible estimate of the time in the timeval to
- *	which tvp points.  We guarantee that the time will be greater than
- *	the value obtained by a previous call.
- */
-void
-microtime(struct timeval *tvp)
-{
-	int s = splclock();
-	static struct timeval lasttime;
-
-	*tvp = time;
-
-	if (tvp->tv_usec >= 1000000) {
-		tvp->tv_usec -= 1000000;
-		tvp->tv_sec++;
-	}
-
-	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);
-}
-
-/*
  * delay:
  *
  *	Wait at least "n" microseconds.
Index: sys/arch/hpcmips/include/sysconf.h
===================================================================
RCS file: /cvsroot/src/sys/arch/hpcmips/include/sysconf.h,v
retrieving revision 1.11
diff -d -p -u -r1.11 sysconf.h
--- sys/arch/hpcmips/include/sysconf.h	23 Sep 2001 14:32:52 -0000	1.11
+++ sys/arch/hpcmips/include/sysconf.h	13 Sep 2006 19:48:33 -0000
@@ -74,8 +74,6 @@ extern struct platform {
 struct platform_clock {
 	int	hz;
 	void	(*init)(struct device *);
-	void	(*rtc_get)(struct device *, time_t, struct clock_ymdhms *);
-	void	(*rtc_set)(struct device *, struct clock_ymdhms *);
 	void	*self;
 	int	start;
 };
Index: sys/arch/hpcmips/include/types.h
===================================================================
RCS file: /cvsroot/src/sys/arch/hpcmips/include/types.h,v
retrieving revision 1.5
diff -d -p -u -r1.5 types.h
--- sys/arch/hpcmips/include/types.h	23 Mar 2002 03:14:54 -0000	1.5
+++ sys/arch/hpcmips/include/types.h	13 Sep 2006 19:48:33 -0000
@@ -4,3 +4,5 @@
 
 #define	__HAVE_GENERIC_SOFT_INTERRUPTS
 #define	__HAVE_OLD_DISKLABEL
+#define	__HAVE_GENERIC_TODR
+#define	__HAVE_TIMECOUNTER
Index: sys/arch/hpcmips/tx/tx39clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/hpcmips/tx/tx39clock.c,v
retrieving revision 1.20
diff -d -p -u -r1.20 tx39clock.c
--- sys/arch/hpcmips/tx/tx39clock.c	16 Jun 2006 00:08:28 -0000	1.20
+++ sys/arch/hpcmips/tx/tx39clock.c	13 Sep 2006 19:48:34 -0000
@@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: tx39clock.c,
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/timetc.h>
 
 #include <dev/clock_subr.h>
 
@@ -65,12 +66,10 @@ __KERNEL_RCSID(0, "$NetBSD: tx39clock.c,
 	dbg_bitmask_print(r, TX39_CLOCK_EN ## m ## CLK, #m)
 
 void	tx39clock_init(struct device *);
-void	tx39clock_get(struct device *, time_t, struct clock_ymdhms *);
-void	tx39clock_set(struct device *, struct clock_ymdhms *);
 
 struct platform_clock tx39_clock = {
 #define CLOCK_RATE	100
-	CLOCK_RATE, tx39clock_init, tx39clock_get, tx39clock_set,
+	CLOCK_RATE, tx39clock_init,
 };
 
 struct txtime {
@@ -86,6 +85,7 @@ struct tx39clock_softc {
 	int sc_enabled;
 	int sc_year;
 	struct clock_ymdhms sc_epoch;
+	struct timecounter sc_tcounter;
 };
 
 int	tx39clock_match(struct device *, struct cfdata *, void *);
@@ -100,6 +100,7 @@ void	__tx39timer_rtcfreeze(tx_chipset_ta
 void	__tx39timer_rtcreset(tx_chipset_tag_t);
 inline void	__tx39timer_rtcget(struct txtime *);
 inline time_t __tx39timer_rtc2sec(struct txtime *);
+uint32_t tx39_timecount(struct timecounter *);
 
 CFATTACH_DECL(tx39clock, sizeof(struct tx39clock_softc),
     tx39clock_match, tx39clock_attach, NULL, NULL);
@@ -195,13 +196,6 @@ __tx39timer_rtcfreeze(tx_chipset_tag_t t
 	tx_conf_write(tc, TX39_TIMERCONTROL_REG, reg);
 }
 
-inline time_t
-__tx39timer_rtc2sec(struct txtime *t)
-{
-	/* This rely on RTC is 32.768kHz */
-	return ((t->t_lo >> 15) | (t->t_hi << 17));
-}
-
 inline void
 __tx39timer_rtcget(struct txtime *t)
 {
@@ -245,6 +239,20 @@ __tx39timer_rtcreset(tx_chipset_tag_t tc
 	tx_conf_write(tc, TX39_TIMERCONTROL_REG, reg);
 }
 
+uint32_t
+tx39_timecount(struct timecounter *tch)
+{
+	tx_chipset_tag_t tc = tch->tc_priv;
+
+	/*
+	 * since we're only reading the low register, we don't care about
+	 * if the chip increments it.  we assume that the single read will
+	 * always be consistent.  This is much faster than the routine which
+	 * has to get both values, improving the quality.
+	 */
+	return (tx_conf_read(tc, TX39_TIMERRTCLO_REG));
+}
+
 void
 tx39clock_init(struct device *dev)
 {
@@ -268,61 +276,14 @@ tx39clock_init(struct device *dev)
 	reg = tx_conf_read(tc, TX39_INTRENABLE6_REG);
 	reg |= TX39_INTRPRI13_TIMER_PERIODIC_BIT; 	
 	tx_conf_write(tc, TX39_INTRENABLE6_REG, reg); 
-}
-
-void
-tx39clock_get(struct device *dev, time_t base, struct clock_ymdhms *t)
-{
-	struct tx39clock_softc *sc = (void *)dev;
-	struct clock_ymdhms dt;
-	struct txtime tt;
-	time_t sec;
-
-	__tx39timer_rtcget(&tt);		
-	sec = __tx39timer_rtc2sec(&tt);
 
-	if (!sc->sc_enabled) {
-		DPRINTF(("bootstrap: %d sec from previous reboot\n", 
-		    (int)sec));
-
-		sc->sc_enabled = 1;
-		clock_secs_to_ymdhms(base, &dt);
-		sc->sc_epoch = dt;
-		base += sec;
-	} else {
-		dt.dt_year = sc->sc_year;
-		dt.dt_mon = sc->sc_epoch.dt_mon;
-		dt.dt_day = sc->sc_epoch.dt_day;
-		dt.dt_hour = sc->sc_epoch.dt_hour;
-		dt.dt_min = sc->sc_epoch.dt_min;
-		dt.dt_sec = sc->sc_epoch.dt_sec;
-		dt.dt_wday = sc->sc_epoch.dt_wday;
-		base = sec + clock_ymdhms_to_secs(&dt);
-	}
-
-	clock_secs_to_ymdhms(base, &dt);
-
-	t->dt_year = dt.dt_year % 100;
-	t->dt_mon = dt.dt_mon;
-	t->dt_day = dt.dt_day;
-	t->dt_hour = dt.dt_hour;
-	t->dt_min = dt.dt_min;
-	t->dt_sec = dt.dt_sec;
-	t->dt_wday = dt.dt_wday;
-
-	sc->sc_year = dt.dt_year;
-}
-
-void
-tx39clock_set(struct device *dev, struct clock_ymdhms *dt)
-{
-	struct tx39clock_softc *sc = (void *)dev;
-
-	if (sc->sc_enabled) {
-		sc->sc_epoch = *dt;
-		__tx39timer_rtcreset(sc->sc_tc);
-		tx39clock_alarm_refill(sc->sc_tc);
-	}
+	sc->sc_tcounter.tc_name = "tx39rtc";
+	sc->sc_tcounter.tc_get_timecount = tx39_timecount;
+	sc->sc_tcounter.tc_priv = tc;
+	sc->sc_tcounter.tc_counter_mask = 0xffffffff;
+	sc->sc_tcounter.tc_frequency = TX39_RTCLOCK;
+	sc->sc_tcounter.tc_quality = 100;
+	tc_init(&sc->sc_tcounter);
 }
 
 int
Index: sys/arch/hpcmips/vr/rtc.c
===================================================================
RCS file: /cvsroot/src/sys/arch/hpcmips/vr/rtc.c,v
retrieving revision 1.23
diff -d -p -u -r1.23 rtc.c
--- sys/arch/hpcmips/vr/rtc.c	24 Dec 2005 23:24:00 -0000	1.23
+++ sys/arch/hpcmips/vr/rtc.c	13 Sep 2006 19:48:34 -0000
@@ -42,6 +42,7 @@ __KERNEL_RCSID(0, "$NetBSD: rtc.c,v 1.23
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/timetc.h>
 
 #include <machine/sysconf.h>
 #include <machine/bus.h>
@@ -80,15 +81,19 @@ struct vrrtc_softc {
 	int sc_tclk_h_reg, sc_tclk_l_reg;
 	int sc_tclk_cnt_h_reg, sc_tclk_cnt_l_reg;
 #endif /* SINGLE_VRIP_BASE */
+	int64_t sc_epoch;
+	struct todr_chip_handle sc_todr;
+	struct timecounter sc_tc;
 };
 
-void	clock_init(struct device *);
-void	clock_get(struct device *, time_t, struct clock_ymdhms *);
-void	clock_set(struct device *, struct clock_ymdhms *);
+void	vrrtc_init(struct device *);
+int	vrrtc_get(todr_chip_handle_t, volatile struct timeval *);
+int	vrrtc_set(todr_chip_handle_t, volatile struct timeval *);
+uint32_t vrrtc_get_timecount(struct timecounter *);
 
 struct platform_clock vr_clock = {
 #define CLOCK_RATE	128
-	CLOCK_RATE, clock_init, clock_get, clock_set,
+	CLOCK_RATE, vrrtc_init,
 };
 
 int	vrrtc_match(struct device *, struct cfdata *, void *);
@@ -99,27 +104,6 @@ void	vrrtc_dump_regs(struct vrrtc_softc 
 CFATTACH_DECL(vrrtc, sizeof(struct vrrtc_softc),
     vrrtc_match, vrrtc_attach, NULL, NULL);
 
-static inline void vrrtc_write(struct vrrtc_softc *, int, u_int16_t);
-static inline u_int16_t vrrtc_read(struct vrrtc_softc *, int);
-void	cvt_timehl_ymdhms(u_int32_t, u_int32_t, struct clock_ymdhms *);
-
-extern int rtc_offset;
-static int m2d[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-static inline void
-vrrtc_write(struct vrrtc_softc *sc, int port, u_int16_t val)
-{
-
-	bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
-}
-
-static inline u_int16_t
-vrrtc_read(struct vrrtc_softc *sc, int port)
-{
-
-	return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port));
-}
-
 int
 vrrtc_match(struct device *parent, struct cfdata *cf, void *aux)
 {
@@ -140,6 +124,7 @@ vrrtc_attach(struct device *parent, stru
 {
 	struct vrip_attach_args *va = aux;
 	struct vrrtc_softc *sc = (void *)self;
+	int year;
 
 #ifndef SINGLE_VRIP_BASE
 	if (va->va_addr == VR4102_RTC_ADDR) {
@@ -212,6 +197,26 @@ vrrtc_attach(struct device *parent, stru
 	 */
 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, RTCINT_REG_W, RTCINT_ALL);
 
+	/*
+	 * Figure out the epoch, which could be either forward or
+	 * backwards in time.  We assume that the start date will always
+	 * be on Jan 1.
+	 */
+	for (year = EPOCHYEAR; year < POSIX_BASE_YEAR; year++) {
+		sc->sc_epoch += LEAPYEAR4(year) ? SECYR + SECDAY : SECYR;
+	}
+	for (year = POSIX_BASE_YEAR; year < EPOCHYEAR; year++) {
+		sc->sc_epoch -= LEAPYEAR4(year) ? SECYR + SECDAY : SECYR;
+	}
+
+	/*
+	 * Initialize MI todr(9)
+	 */
+	sc->sc_todr.todr_settime = vrrtc_set;
+	sc->sc_todr.todr_gettime = vrrtc_get;
+	sc->sc_todr.cookie = sc;
+	todr_attach(&sc->sc_todr);
+
 	platform_clock_attach(sc, &vr_clock);
 }
 
@@ -230,7 +235,7 @@ vrrtc_intr(void *arg, u_int32_t pc, u_in
 }
 
 void
-clock_init(struct device *dev)
+vrrtc_init(struct device *dev)
 {
 	struct vrrtc_softc *sc = (struct vrrtc_softc *)dev;
 
@@ -241,17 +246,39 @@ clock_init(struct device *dev)
 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, RTCL1_H_REG_W, 0);
 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, RTCL1_L_REG_W,
 	    RTCL1_L_HZ/CLOCK_RATE);
+
+	/*
+	 * Initialize timecounter.
+	 */
+	sc->sc_tc.tc_get_timecount = vrrtc_get_timecount;
+	sc->sc_tc.tc_name = "vrrtc";
+	sc->sc_tc.tc_counter_mask = 0xffff;
+	sc->sc_tc.tc_frequency = ETIME_L_HZ;
+	sc->sc_tc.tc_priv = sc;
+	sc->sc_tc.tc_quality = 100;
+	tc_init(&sc->sc_tc);
 }
 
-void
-clock_get(struct device *dev, time_t base, struct clock_ymdhms *dt)
+uint32_t
+vrrtc_get_timecount(struct timecounter *tc)
 {
+	struct vrrtc_softc *sc = (struct vrrtc_softc *)tc->tc_priv;
+	bus_space_tag_t iot = sc->sc_iot;
+	bus_space_handle_t ioh = sc->sc_ioh;
 
-	struct vrrtc_softc *sc = (struct vrrtc_softc *)dev;
+	return (bus_space_read_2(iot, ioh, ETIME_L_REG_W));
+}
+
+int
+vrrtc_get(todr_chip_handle_t tch, volatile struct timeval *tvp)
+{
+
+	struct vrrtc_softc *sc = (struct vrrtc_softc *)tch->cookie;
 	bus_space_tag_t iot = sc->sc_iot;
 	bus_space_handle_t ioh = sc->sc_ioh;
 	u_int32_t timeh;	/* elapse time (2*timeh sec) */
 	u_int32_t timel;	/* timel/32768 sec */
+	int64_t sec, usec;
 
 	timeh = bus_space_read_2(iot, ioh, ETIME_H_REG_W);
 	timeh = (timeh << 16) | bus_space_read_2(iot, ioh, ETIME_M_REG_W);
@@ -259,135 +286,47 @@ clock_get(struct device *dev, time_t bas
 
 	DPRINTF(("clock_get: timeh %08x timel %08x\n", timeh, timel));
 
-	cvt_timehl_ymdhms(timeh, timel, dt);
+	timeh -= EPOCHOFF;
+	sec = timeh * 2;
+	sec -= sc->sc_epoch;
+	tvp->tv_sec = sec;
+	tvp->tv_sec += timel / ETIME_L_HZ;
 
-	DPRINTF(("clock_get: %d/%d/%d/%d/%d/%d\n", dt->dt_year, dt->dt_mon,
-	    dt->dt_day, dt->dt_hour, dt->dt_min, dt->dt_sec));
+	/* scale from 32kHz to 1MHz */
+	usec = (timel % ETIME_L_HZ);
+	usec *= 1000000;
+	usec /= ETIME_L_HZ;
+	tvp->tv_usec = (uint32_t)usec;
+
+	return 0;
 }
 
-void
-clock_set(struct device *dev, struct clock_ymdhms *dt)
+int
+vrrtc_set(todr_chip_handle_t tch, volatile struct timeval *tvp)
 {
-	struct vrrtc_softc *sc = (struct vrrtc_softc *)dev;
+	struct vrrtc_softc *sc = (struct vrrtc_softc *)tch->cookie;
 	bus_space_tag_t iot = sc->sc_iot;
 	bus_space_handle_t ioh = sc->sc_ioh;
 	u_int32_t timeh;	/* elapse time (2*timeh sec) */
 	u_int32_t timel;	/* timel/32768 sec */
-	int year, month, sec2;
-
-	timeh = 0;
-	timel = 0;
-
-	DPRINTF(("clock_set: %d/%d/%d/%d/%d/%d\n", dt->dt_year, dt->dt_mon,
-	    dt->dt_day, dt->dt_hour, dt->dt_min, dt->dt_sec));
-
-	dt->dt_year += YBASE;
-
-	DPRINTF(("clock_set: %d/%d/%d/%d/%d/%d\n", dt->dt_year, dt->dt_mon,
-	    dt->dt_day, dt->dt_hour, dt->dt_min, dt->dt_sec));
-
-	year = EPOCHYEAR;
-	sec2 = LEAPYEAR4(year)?SEC2YR+SEC2DAY:SEC2YR;
-	while (year < dt->dt_year) {
-		year++;
-		timeh += sec2;
-		sec2 = LEAPYEAR4(year)?SEC2YR+SEC2DAY:SEC2YR;
-	}
-	month = 1; /* now month is 1..12 */
-	sec2 = SEC2DAY * m2d[month-1];
-	while (month < dt->dt_mon) {
-		month++;
-		timeh += sec2;
-		sec2 = SEC2DAY * m2d[month-1];
-		if (month == 2 && LEAPYEAR4(year)) /* feb. and leapyear */
-			sec2 += SEC2DAY;
-	}
-
-	timeh += (dt->dt_day - 1)*SEC2DAY;
-
-	timeh += dt->dt_hour*SEC2HOUR;
-
-	timeh += dt->dt_min*SEC2MIN;
-
-	timeh += dt->dt_sec/2;
-	timel += (dt->dt_sec%2)*ETIME_L_HZ;
+	int64_t sec, cnt;
 
-	timeh += EPOCHOFF;
-	timeh -= (rtc_offset*SEC2MIN);
+	sec = tvp->tv_sec + sc->sc_epoch;
+	sec += sc->sc_epoch;
+	timeh = EPOCHOFF + (sec / 2);
+	timel = sec % 2;
 
-#ifdef VRRTCDEBUG
-	cvt_timehl_ymdhms(timeh, timel, NULL);
-#endif /* RTCDEBUG */
+	cnt = tvp->tv_usec;
+	/* scale from 1MHz to 32kHz */
+	cnt *= ETIME_L_HZ;
+	cnt /= 1000000;
+	timel += (uint32_t)cnt;
 
 	bus_space_write_2(iot, ioh, ETIME_H_REG_W, (timeh >> 16) & 0xffff);
 	bus_space_write_2(iot, ioh, ETIME_M_REG_W, timeh & 0xffff);
 	bus_space_write_2(iot, ioh, ETIME_L_REG_W, timel);
-}
-
-void
-cvt_timehl_ymdhms(
-	u_int32_t timeh, /* 2 sec */
-	u_int32_t timel, /* 1/32768 sec */
-	struct clock_ymdhms *dt)
-{
-	u_int32_t year, month, date, hour, mins, sec, sec2;
-
-	timeh -= EPOCHOFF;
-
-	timeh += (rtc_offset*SEC2MIN);
-
-	year = EPOCHYEAR;
-	sec2 = LEAPYEAR4(year)?SEC2YR+SEC2DAY:SEC2YR;
-	while (timeh > sec2) {
-		year++;
-		timeh -= sec2;
-		sec2 = LEAPYEAR4(year)?SEC2YR+SEC2DAY:SEC2YR;
-	}
-
-	DPRINTF(("cvt_timehl_ymdhms: timeh %08x year %d yrref %d\n", 
-	    timeh, year, sec2));
-
-	month = 0; /* now month is 0..11 */
-	sec2 = SEC2DAY * m2d[month];
-	while (timeh > sec2) {
-		timeh -= sec2;
-		month++;
-		sec2 = SEC2DAY * m2d[month];
-		if (month == 1 && LEAPYEAR4(year)) /* feb. and leapyear */
-			sec2 += SEC2DAY;
-	}
-	month +=1; /* now month is 1..12 */
-
-	DPRINTF(("cvt_timehl_ymdhms: timeh %08x month %d mref %d\n", 
-	    timeh, month, sec2));
 
-	sec2 = SEC2DAY;
-	date = timeh/sec2+1; /* date is 1..31 */
-	timeh -= (date-1)*sec2;
-
-	DPRINTF(("cvt_timehl_ymdhms: timeh %08x date %d dref %d\n", 
-	    timeh, date, sec2));
-
-	sec2 = SEC2HOUR;
-	hour = timeh/sec2;
-	timeh -= hour*sec2;
-
-	sec2 = SEC2MIN;
-	mins = timeh/sec2;
-	timeh -= mins*sec2;
-
-	sec = timeh*2 + timel/ETIME_L_HZ;	
-
-	DPRINTF(("cvt_timehl_ymdhms: hour %d min %d sec %d\n", hour, mins, sec));
-
-	if (dt) {
-		dt->dt_year	= year - YBASE; /* base 1900 */
-		dt->dt_mon	= month;
-		dt->dt_day	= date;
-		dt->dt_hour	= hour;
-		dt->dt_min	= mins;
-		dt->dt_sec	= sec;
-	}
+	return 0;
 }
 
 void
Index: sys/arch/hpcmips/vr/rtcreg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/hpcmips/vr/rtcreg.h,v
retrieving revision 1.8
diff -d -p -u -r1.8 rtcreg.h
--- sys/arch/hpcmips/vr/rtcreg.h	10 Feb 2002 14:36:52 -0000	1.8
+++ sys/arch/hpcmips/vr/rtcreg.h	13 Sep 2006 19:48:34 -0000
@@ -35,22 +35,6 @@
  *
  */
 
-#define	SECMIN	((unsigned)60)			/* seconds per minute */
-#define	SECHOUR	((unsigned)(60*SECMIN))		/* seconds per hour */
-
-#define	SEC2MIN	((unsigned)60/2)		/* 2seconds per minute */
-#define	SEC2HOUR ((unsigned)(60*SECMIN)/2)	/* 2seconds per hour */
-#define	SEC2DAY	((unsigned)(24*SECHOUR)/2)	/* 2seconds per day */
-#define	SEC2YR	((unsigned)(365*SECDAY)/2)	/* 2seconds per common year */
-
-#define	YRREF		1999
-#define	MREF		1
-#define	DREF		1
-
-#ifndef YBASE
-#define YBASE		1900
-#endif
-
 #define EPOCHOFF	0			/* epoch offset */
 #ifndef EPOCHYEAR
 #define EPOCHYEAR	1850	/* XXX */	/* WINCE epoch year */

--------------070809010906060003050600--