Subject: MI mcclock (mc146818) with todr(9) support
To: None <tech-kern@netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: tech-kern
Date: 10/26/2003 06:29:38
Hi,

Today I've made MI mc146818 time-of-day driver which
uses MI todr(9) functions like mk48txx(4) driver.

Currently I've only written and tested MD attachment for arc port,
but migrating from old mcclock used on many ports should be trivial.
(though we should re-think API for NVRAM access used by isa/fd.c etc.)

Comments?
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp

--- /dev/null	2003-10-26 03:43:46.000000000 +0900
+++ dev/ic/mc146818.c	2003-10-26 05:11:06.000000000 +0900
@@ -0,0 +1,201 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (c) 2003 Izumi Tsutsui.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * mc146818 and compatible time of day chip subroutines
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+
+#include <machine/bus.h>
+
+#include <dev/clock_subr.h>
+
+#include <dev/ic/mc146818reg.h>
+#include <dev/ic/mc146818var.h>
+
+int mc146818_gettime(todr_chip_handle_t, struct timeval *);
+int mc146818_settime(todr_chip_handle_t, struct timeval *);
+int mc146818_getcal(todr_chip_handle_t, int *);
+int mc146818_setcal(todr_chip_handle_t, int);
+
+void
+mc146818_attach(sc)
+	struct mc146818_softc *sc;
+{
+	todr_chip_handle_t handle;
+
+#ifdef DIAGNOSTIC
+	if (sc->sc_mcread == NULL ||
+	    sc->sc_mcwrite == NULL)
+		panic("mc146818_attach: invalid read/write functions");
+#endif
+
+	printf(": mc146818 compatible time-of-day clock");
+
+	handle = &sc->sc_handle;
+	handle->cookie = sc;
+	handle->todr_gettime = mc146818_gettime;
+	handle->todr_settime = mc146818_settime;
+	handle->todr_getcal  = mc146818_getcal;
+	handle->todr_setcal  = mc146818_setcal;
+	handle->todr_setwen  = NULL;
+}
+
+/*
+ * todr_gettime function:
+ *  Get time of day and convert it to a struct timeval.
+ *  Return 0 on success, an error number othersize.
+ */
+int
+mc146818_gettime(handle, tv)
+	todr_chip_handle_t handle;
+	struct timeval *tv;
+{
+	struct mc146818_softc *sc;
+	struct clock_ymdhms dt;
+	int s, timeout, year;
+
+	sc = handle->cookie;
+
+	s = splclock();		/* XXX really needed? */
+
+	todr_wenable(handle, 1);
+
+	timeout = 1000000;	/* XXX how long should we wait? */
+	for (;;) {
+		if ((*sc->sc_mcread)(sc, MC_REGA) & MC_REGA_UIP)
+			break;
+		if (--timeout < 0) {
+			printf("mc146818_gettime: timeout\n");
+			return EBUSY;
+		}
+	}
+
+	dt.dt_sec  = (*sc->sc_mcread)(sc, MC_SEC);
+	dt.dt_min  = (*sc->sc_mcread)(sc, MC_MIN);
+	dt.dt_hour = (*sc->sc_mcread)(sc, MC_HOUR);
+	dt.dt_wday = (*sc->sc_mcread)(sc, MC_DOW);
+	dt.dt_day  = (*sc->sc_mcread)(sc, MC_DOM);
+	dt.dt_mon  = (*sc->sc_mcread)(sc, MC_MONTH);
+	year = (*sc->sc_mcread)(sc, MC_YEAR);
+
+	year += sc->sc_year0;
+	if (year < POSIX_BASE_YEAR &&
+	    (sc->sc_flag & NO_CENTURY_ADJUST) == 0)
+		year += 100;
+	dt.dt_year = year;
+
+	todr_wenable(handle, 0);
+
+	splx(s);
+
+	/* simple sanity checks */
+	if (dt.dt_mon > 12 || dt.dt_day > 31 ||
+	    dt.dt_hour >= 24 || dt.dt_min >= 60 || dt.dt_sec >= 60)
+		return EIO;
+
+	tv->tv_sec = clock_ymdhms_to_secs(&dt);
+	tv->tv_usec = 0;
+	return 0;
+}
+
+/*
+ * todr_settime function:
+ *  Set the time of day clock based on the value of the struct timeval arg.
+ *  Return 0 on success, an error number othersize.
+ */
+int
+mc146818_settime(handle, tv)
+	todr_chip_handle_t handle;
+	struct timeval *tv;
+{
+	struct mc146818_softc *sc;
+	struct clock_ymdhms dt;
+	int s, timeout, year;
+
+	sc = handle->cookie;
+
+	/* Note: we ignore `tv_usec' */
+	clock_secs_to_ymdhms(tv->tv_sec, &dt);
+
+	year = dt.dt_year - sc->sc_year0;
+	if (year > 99 && (sc->sc_flag & NO_CENTURY_ADJUST) == 0)
+		year -= 100;
+
+	s = splclock();		/* XXX really needed? */
+
+	todr_wenable(handle, 1);
+
+	timeout = 1000000;	/* XXX how long should we wait? */
+	for (;;) {
+		if ((*sc->sc_mcread)(sc, MC_REGA) & MC_REGA_UIP)
+			break;
+		if (--timeout < 0) {
+			printf("mc146818_settime: timeout\n");
+			return EBUSY;
+		}
+	}
+
+	(*sc->sc_mcwrite)(sc, MC_SEC, dt.dt_sec);
+	(*sc->sc_mcwrite)(sc, MC_MIN, dt.dt_min);
+	(*sc->sc_mcwrite)(sc, MC_HOUR, dt.dt_hour);
+	(*sc->sc_mcwrite)(sc, MC_DOW, dt.dt_wday);
+	(*sc->sc_mcwrite)(sc, MC_DOM, dt.dt_day);
+	(*sc->sc_mcwrite)(sc, MC_MONTH, dt.dt_mon);
+	(*sc->sc_mcwrite)(sc, MC_YEAR, year);
+
+	todr_wenable(handle, 0);
+
+	splx(s);
+
+	return 0;
+}
+
+int
+mc146818_getcal(handle, vp)
+	todr_chip_handle_t handle;
+	int *vp;
+{
+
+	return EOPNOTSUPP;
+}
+
+int
+mc146818_setcal(handle, v)
+	todr_chip_handle_t handle;
+	int v;
+{
+
+	return EOPNOTSUPP;
+}
--- /dev/null	2003-10-26 03:43:46.000000000 +0900
+++ dev/ic/mc146818var.h	2003-10-26 04:51:01.000000000 +0900
@@ -0,0 +1,45 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (c) 2003 Izumi Tsutsui.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+struct mc146818_softc {
+	struct device sc_dev;
+
+	bus_space_tag_t sc_bst;			/* bus space tag */
+	bus_space_handle_t sc_bsh;		/* bus space handle */
+
+	struct todr_chip_handle sc_handle;	/* TODR handle */
+	u_int sc_year0;				/* year counter offset */
+	u_int sc_flag;				/* MD flags */
+#define NO_CENTURY_ADJUST	0x0001		/* don't adjust century */
+
+	/* MD chip register read/write functions */
+	u_int (*sc_mcread)(struct mc146818_softc *, u_int);
+	void (*sc_mcwrite)(struct mc146818_softc *, u_int, u_int);
+};
+
+void mc146818_attach(struct mc146818_softc *);
Index: conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.642
diff -u -r1.642 files
--- conf/files	17 Oct 2003 18:16:42 -0000	1.642
+++ conf/files	25 Oct 2003 20:19:08 -0000
@@ -778,6 +778,11 @@
 #
 define	mm58167
 file	dev/ic/mm58167.c		mm58167
+
+# Motorola mc146818 (and compatible) time-of-day clock
+#
+define	mc146818
+file	dev/ic/mc146818.c		mc146818
 
 # D-Link DL10019/10022 NE2000-compatible network interface subroutines
 #
Index: dev/ic/mc146818reg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/mc146818reg.h,v
retrieving revision 1.3
diff -u -r1.3 mc146818reg.h
--- dev/ic/mc146818reg.h	8 Jul 2003 10:06:31 -0000	1.3
+++ dev/ic/mc146818reg.h	25 Oct 2003 20:19:08 -0000
@@ -61,6 +61,11 @@
  * automatically reset; they must be reprogrammed with correct values.
  */
 
+/* XXX not yet all port switch to MI mc146818(4) with todr(9) support */
+#if defined(arc)
+#define USE_TODR_MCCLOCK
+#endif
+
 /*
  * The registers, and the bits within each register.
  */
@@ -142,7 +147,7 @@
 #define	MC_BASE_NONE	0x60		/* actually, both of these reset */
 #define	MC_BASE_RESET	0x70
 
-
+#ifndef USE_TODR_MCCLOCK
 /*
  * RTC register/NVRAM read and write functions -- machine-dependent.
  * Appropriately manipulate RTC registers to get/put data values.
@@ -192,3 +197,4 @@
 		mc146818_write(sc, MC_REGB,				\
 		    mc146818_read(sc, MC_REGB) & ~MC_REGB_SET);		\
 	} while (0);
+#endif /* USE_TODR_MCCLOCK */
Index: arch/arc/arc/c_jazz_eisa.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/c_jazz_eisa.c,v
retrieving revision 1.7
diff -u -r1.7 c_jazz_eisa.c
--- arch/arc/arc/c_jazz_eisa.c	15 Jul 2003 00:04:41 -0000	1.7
+++ arch/arc/arc/c_jazz_eisa.c	25 Oct 2003 20:19:08 -0000
@@ -44,10 +44,12 @@
 #include <machine/pio.h>
 #include <machine/platform.h>
 
+#include <dev/clock_subr.h>
+#include <dev/ic/mc146818var.h>
+
 #include <arc/arc/arcbios.h>
 #include <arc/jazz/pica.h>
 #include <arc/jazz/jazziovar.h>
-#include <arc/dev/mcclockvar.h>
 #include <arc/jazz/mcclock_jazziovar.h>
 
 #include "pc.h"
@@ -92,37 +94,39 @@
 /*
  * chipset-dependent mcclock routines.
  */
-u_int mc_jazz_eisa_read __P((struct mcclock_softc *, u_int));
-void mc_jazz_eisa_write __P((struct mcclock_softc *, u_int, u_int));
+static u_int mc_jazz_eisa_read(struct mc146818_softc *, u_int);
+static void mc_jazz_eisa_write(struct mc146818_softc *, u_int, u_int);
 
 struct mcclock_jazzio_config mcclock_jazz_eisa_conf = {
-	0x80004000, 1,
-	{ mc_jazz_eisa_read, mc_jazz_eisa_write }
+	0x80004000,		/* I/O base */
+	1,			/* I/O size */
+	mc_jazz_eisa_read,	/* read function */
+	mc_jazz_eisa_write	/* write function */
 };
 
-u_int
+static u_int
 mc_jazz_eisa_read(sc, reg)
-	struct mcclock_softc *sc;
+	struct mc146818_softc *sc;
 	u_int reg;
 {
-	int i, as;
+	u_int i, as;
 
 	as = in32(arc_bus_io.bs_vbase + C_JAZZ_EISA_TODCLOCK_AS) & 0x80;
 	out32(arc_bus_io.bs_vbase + C_JAZZ_EISA_TODCLOCK_AS, as | reg);
-	i = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0);
+	i = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 0);
 	return i;
 }
 
-void
+static void
 mc_jazz_eisa_write(sc, reg, datum)
-	struct mcclock_softc *sc;
+	struct mc146818_softc *sc;
 	u_int reg, datum;
 {
-	int as;
+	u_int as;
 
 	as = in32(arc_bus_io.bs_vbase + C_JAZZ_EISA_TODCLOCK_AS) & 0x80;
 	out32(arc_bus_io.bs_vbase + C_JAZZ_EISA_TODCLOCK_AS, as | reg);
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0, datum);
+	bus_space_write_1(sc->sc_bst, sc->sc_bsh, 0, datum);
 }
 
 /*
Index: arch/arc/arc/c_nec_pci.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/c_nec_pci.c,v
retrieving revision 1.7
diff -u -r1.7 c_nec_pci.c
--- arch/arc/arc/c_nec_pci.c	15 Jul 2003 00:04:41 -0000	1.7
+++ arch/arc/arc/c_nec_pci.c	25 Oct 2003 20:19:08 -0000
@@ -40,10 +40,14 @@
 #include <uvm/uvm_extern.h>
 
 #include <machine/autoconf.h>
+#include <machine/bus.h>
 #include <machine/pio.h>
 #include <machine/platform.h>
 #include <mips/pte.h>
 
+#include <dev/clock_subr.h>
+#include <dev/ic/mc146818var.h>
+
 #include <dev/pci/pcivar.h>
 
 #include <arc/arc/arcbios.h>
@@ -51,7 +55,6 @@
 #include <arc/jazz/pica.h>
 #include <arc/jazz/rd94.h>
 #include <arc/jazz/jazziovar.h>
-#include <arc/dev/mcclockvar.h>
 #include <arc/jazz/mcclock_jazziovar.h>
 #include <arc/pci/necpbvar.h>
 
@@ -93,12 +96,14 @@
  * chipset-dependent mcclock routines.
  */
 
-u_int	mc_nec_pci_read __P((struct mcclock_softc *, u_int));
-void	mc_nec_pci_write __P((struct mcclock_softc *, u_int, u_int));
+static u_int	mc_nec_pci_read(struct mc146818_softc *, u_int);
+static void	mc_nec_pci_write(struct mc146818_softc *, u_int, u_int);
 
 struct mcclock_jazzio_config mcclock_nec_pci_conf = {
-	0x80004000, 2,
-	{ mc_nec_pci_read, mc_nec_pci_write }
+	0x80004000,		/* I/O base */
+	2,			/* I/O size */
+	mc_nec_pci_read,	/* read function */
+	mc_nec_pci_write	/* write function */
 };
 
 /*
@@ -146,29 +151,29 @@
 		MIPS_INT_MASK_5,		/* IPL_{CLOCK,HIGH} */
 };
 
-u_int
+static u_int
 mc_nec_pci_read(sc, reg)
-	struct mcclock_softc *sc;
+	struct mc146818_softc *sc;
 	u_int reg;
 {
-	int i, as;
+	u_int i, as;
 
-	as = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 1) & 0x80;
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, 1, as | reg);
-	i = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 0);
-	return (i);
+	as = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 1) & 0x80;
+	bus_space_write_1(sc->sc_bst, sc->sc_bsh, 1, as | reg);
+	i = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 0);
+	return i;
 }
 
-void
+static void
 mc_nec_pci_write(sc, reg, datum)
-	struct mcclock_softc *sc;
+	struct mc146818_softc *sc;
 	u_int reg, datum;
 {
-	int as;
+	u_int as;
 
-	as = bus_space_read_1(sc->sc_iot, sc->sc_ioh, 1) & 0x80;
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, 1, as | reg);
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0, datum);
+	as = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 1) & 0x80;
+	bus_space_write_1(sc->sc_bst, sc->sc_bsh, 1, as | reg);
+	bus_space_write_1(sc->sc_bst, sc->sc_bsh, 0, datum);
 }
 
 /*
Index: arch/arc/arc/todclock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/arc/todclock.c,v
retrieving revision 1.4
diff -u -r1.4 todclock.c
--- arch/arc/arc/todclock.c	7 Aug 2003 16:26:48 -0000	1.4
+++ arch/arc/arc/todclock.c	25 Oct 2003 20:19:09 -0000
@@ -1,13 +1,17 @@
 /* $NetBSD: todclock.c,v 1.4 2003/08/07 16:26:48 agc Exp $ */
-/* NetBSD: clock.c,v 1.31 2001/05/27 13:53:24 sommerfeld Exp  */
 
 /*
  * Copyright (c) 1992, 1993
- *	The Regents of the University of California.  All rights reserved.
+ *      The Regents of the University of California.  All rights reserved.
  *
- * This code is derived from software contributed to Berkeley by
- * the Systems Programming Group of the University of Utah Computer
- * Science Department and Ralph Campbell.
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Lawrence Berkeley Laboratory.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,209 +37,96 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * from: Utah Hdr: clock.c 1.18 91/01/21
- *
- *	@(#)clock.c	8.1 (Berkeley) 6/10/93
+ *      @(#)clock.c     8.1 (Berkeley) 6/11/93
  */
-/*
- * Copyright (c) 1988 University of Utah.
- *
- * This code is derived from software contributed to Berkeley by
- * the Systems Programming Group of the University of Utah Computer
- * Science Department and Ralph Campbell.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * from: Utah Hdr: clock.c 1.18 91/01/21
- *
- *	@(#)clock.c	8.1 (Berkeley) 6/10/93
- */
-
-#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: todclock.c,v 1.4 2003/08/07 16:26:48 agc Exp $");
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.12 2003/08/07 16:28:51 agc Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/systm.h>
+#include <sys/device.h>
 
 #include <dev/clock_subr.h>
 
-#include <arc/arc/todclockvar.h>
-
-#define MINYEAR 2002 /* "today" */
-
-struct device *todclockdev;
-const struct todclockfns *todclockfns;
-int todclock_year_offset;
-int todclockinitted;
+static	todr_chip_handle_t todr_handle;
 
+/*
+ * Common parts of todclock autoconfiguration.
+ */
 void
-todclockattach(dev, fns, year_offset)
-	struct device *dev;
-	const struct todclockfns *fns;
-	int year_offset;
+todr_attach(handle)
+	todr_chip_handle_t handle;
 {
 
-	/*
-	 * Just bookkeeping.
-	 */
-	if (todclockfns != NULL)
-		panic("todclockattach: multiple todclocks");
-
-	todclockdev = dev;
-	todclockfns = fns;
-	todclock_year_offset = year_offset;
-}
+	if (todr_handle)
+		panic("todr_attach: too many todclocks configured");
 
-/*
- * Machine-dependent real-time clock routines.
- *
- * 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.
- *
- * Resettodr restores the time of day hardware after a time change.
- */
+	todr_handle = handle;
+}
 
 /*
- * 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.
+ * Set up the system's time, given a `reasonable' time value.
  */
 void
 inittodr(base)
 	time_t base;
 {
-	struct todclocktime ct;
-	int year;
-	struct clock_ymdhms dt;
-	time_t deltat;
-	int badbase;
-
-	if (todclockfns == NULL)
-		panic("inittodr: no real time clock attached");
-
-	if (base < (MINYEAR - POSIX_BASE_YEAR) * SECYR) {
-		printf("WARNING: preposterous time in file system");
-		/* read the system clock anyway */
-		base = (MINYEAR - POSIX_BASE_YEAR) * SECYR;
+	int badbase, waszero;
+
+	badbase = 0;
+	waszero = (base == 0);
+
+	if (base < 5 * SECYR) {
+		/*
+		 * If base is 0, assume filesystem time is just unknown
+		 * in stead of preposterous. Don't bark.
+		 */
+		if (base != 0)
+			printf("WARNING: preposterous time in file system\n");
+		/* not going to use it anyway, if the chip is readable */
+		/* 2002/7/1	12:00:00 */
+		base = 32*SECYR + 186*SECDAY + SECDAY/2;
 		badbase = 1;
-	} else
-		badbase = 0;
+	}
 
-	(*todclockfns->tcf_get)(todclockdev, base, &ct);
-#ifdef DEBUG
-	printf("readclock: %02d/%02d/%02d/%02d/%02d/%02d",
-	    ct.year, ct.mon, ct.day, ct.hour, ct.min, ct.sec);
-#endif
-	todclockinitted = 1;
-
-	year = 1900 + todclock_year_offset + ct.year;
-	if (year < POSIX_BASE_YEAR)
-		year += 100;
-	/* simple sanity checks (2037 = time_t overflow) */
-	if (year < MINYEAR || year > 2037 ||
-	    ct.mon < 1 || ct.mon > 12 || ct.day < 1 || ct.day > 31 ||
-	    ct.hour >= 24 || ct.min >= 60 || ct.sec >= 60) {
+	if (todr_gettime(todr_handle, (struct timeval *)&time) != 0 ||
+	    time.tv_sec == 0) {
+		printf("WARNING: bad date in battery clock");
 		/*
 		 * Believe the time in the file system for lack of
-		 * anything better, resetting the TODR.
+		 * anything better, resetting the clock.
 		 */
 		time.tv_sec = base;
-		if (!badbase) {
-			printf("WARNING: preposterous clock chip time\n");
+		if (!badbase)
 			resettodr();
-		}
-		goto bad;
-	}
-
-	dt.dt_year = year;
-	dt.dt_mon  = ct.mon;
-	dt.dt_day  = ct.day;
-	dt.dt_hour = ct.hour;
-	dt.dt_min  = ct.min;
-	dt.dt_sec  = ct.sec;
-	time.tv_sec = clock_ymdhms_to_secs(&dt);
-#ifdef DEBUG
-	printf("=>%ld (%ld)\n", time.tv_sec, base);
-#endif
+	} else {
+		int deltat = time.tv_sec - base;
 
-	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)
+		if (waszero || deltat < 2 * SECDAY)
 			return;
-		printf("WARNING: clock %s %ld days",
-		    time.tv_sec < base ? "lost" : "gained",
-		    (long)deltat / SECDAY);
+		printf("WARNING: clock %s %d days",
+		    time.tv_sec < base ? "lost" : "gained", deltat / SECDAY);
 	}
- bad:
 	printf(" -- CHECK AND RESET THE DATE!\n");
 }
 
 /*
- * 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.
+ * Reset the clock based on the current time.
+ * Used when the current clock is preposterous, when the time is changed,
+ * and when rebooting.  Do nothing if the time is not yet known, e.g.,
+ * when crashing during autoconfig.
  */
 void
 resettodr()
 {
-	struct clock_ymdhms dt;
-	struct todclocktime ct;
 
-	if (!todclockinitted)
+	if (time.tv_sec == 0)
 		return;
 
-	clock_secs_to_ymdhms(time.tv_sec, &dt);
-
-	/* rt clock wants 2 digits */
-	ct.year = (dt.dt_year - todclock_year_offset) % 100;
-	ct.mon  = dt.dt_mon;
-	ct.day  = dt.dt_day;
-	ct.hour = dt.dt_hour;
-	ct.min  = dt.dt_min;
-	ct.sec  = dt.dt_sec;
-	ct.dow  = dt.dt_wday;
-#ifdef DEBUG
-	printf("setclock: %02d/%02d/%02d/%02d/%02d/%02d\n",
-	    ct.year, ct.mon, ct.day,
-	       ct.hour, ct.min, ct.sec);
-#endif
-
-	(*todclockfns->tcf_set)(todclockdev, &ct);
+	if (todr_settime(todr_handle, (struct timeval *)&time) != 0)
+		printf("resettodr: cannot set time in time-of-day clock\n");
 }
Index: arch/arc/conf/files.arc
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/conf/files.arc,v
retrieving revision 1.47
diff -u -r1.47 files.arc
--- arch/arc/conf/files.arc	27 Jul 2003 01:17:40 -0000	1.47
+++ arch/arc/conf/files.arc	25 Oct 2003 20:19:09 -0000
@@ -217,10 +217,9 @@
 file	arch/arc/isa/timer_isa.c	timer & timer_isa needs-flag
 
 #	Real time clock, must have one..
-device	mcclock
+device	mcclock: mc146818
 attach	mcclock at jazzio with mcclock_jazzio
 attach	mcclock at isa with mcclock_isa
-file	arch/arc/dev/mcclock.c		mcclock needs-flag
 file	arch/arc/jazz/mcclock_jazzio.c	mcclock & mcclock_jazzio needs-flag
 file	arch/arc/isa/mcclock_isa.c	mcclock & mcclock_isa needs-flag
 
Index: arch/arc/isa/mcclock_isa.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/isa/mcclock_isa.c,v
retrieving revision 1.6
diff -u -r1.6 mcclock_isa.c
--- arch/arc/isa/mcclock_isa.c	7 Aug 2003 16:26:50 -0000	1.6
+++ arch/arc/isa/mcclock_isa.c	25 Oct 2003 20:19:09 -0000
@@ -90,24 +90,22 @@
 #include <dev/isa/isareg.h>
 #include <dev/isa/isavar.h>
 
+#include <dev/clock_subr.h>
+
 #include <dev/ic/mc146818reg.h>
+#include <dev/ic/mc146818var.h>
 
-#include <arc/dev/mcclockvar.h>
 #include <arc/isa/mcclock_isavar.h>
 
-int mcclock_isa_match __P((struct device *, struct cfdata *, void *));
-void mcclock_isa_attach __P((struct device *, struct device *, void *));
+int mcclock_isa_match(struct device *, struct cfdata *, void *);
+void mcclock_isa_attach(struct device *, struct device *, void *);
 
-CFATTACH_DECL(mcclock_isa, sizeof(struct mcclock_softc),
+CFATTACH_DECL(mcclock_isa, sizeof(struct mc146818_softc),
     mcclock_isa_match, mcclock_isa_attach, NULL, NULL);
 
 /* Deskstation clock access code */
-u_int mc_isa_read __P((struct mcclock_softc *, u_int));
-void mc_isa_write __P((struct mcclock_softc *, u_int, u_int));
-
-struct mcclock_busfns mcclock_isa_busfns = {
-	mc_isa_read, mc_isa_write
-};
+static u_int mc_isa_read(struct mc146818_softc *, u_int);
+static void mc_isa_write(struct mc146818_softc *, u_int, u_int);
 
 int mcclock_isa_conf = 0;
 
@@ -162,37 +160,45 @@
 	struct device *self;
 	void *aux;
 {
-	struct mcclock_softc *sc = (struct mcclock_softc *)self;
+	struct mc146818_softc *sc = (void *)self;
 	struct isa_attach_args *ia = aux;
 
-	sc->sc_iot = ia->ia_iot;
-	if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr,
-	    ia->ia_io[0].ir_size, 0, &sc->sc_ioh))
+	sc->sc_bst = ia->ia_iot;
+	if (bus_space_map(sc->sc_bst, ia->ia_io[0].ir_addr,
+	    ia->ia_io[0].ir_size, 0, &sc->sc_bsh))
 		panic("mcclock_isa_attach: couldn't map clock I/O space");
 
-	mcclock_attach(sc, &mcclock_isa_busfns, 80);
+	sc->sc_year0 = 1980;
+	sc->sc_mcread  = mc_isa_read;
+	sc->sc_mcwrite = mc_isa_write;
+
+	mc146818_attach(sc);
+
+	printf("\n");
 
 	/* Turn interrupts off, just in case. */
-	mc146818_write(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR);
+	mc_isa_write(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR);
+
+	todr_attach(&sc->sc_handle);
 }
 
 u_int
 mc_isa_read(sc, reg)
-	struct mcclock_softc *sc;
+	struct mc146818_softc *sc;
 	u_int reg;
 {
 
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0, reg);
-	return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, 1));
+	bus_space_write_1(sc->sc_bst, sc->sc_bsh, 0, reg);
+	return bus_space_read_1(sc->sc_bst, sc->sc_bsh, 1);
 }
 
 void
 mc_isa_write(sc, reg, datum)
-	struct mcclock_softc *sc;
+	struct mc146818_softc *sc;
 	u_int reg, datum;
 {
 
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, 0, reg);
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, 1, datum);
+	bus_space_write_1(sc->sc_bst, sc->sc_bsh, 0, reg);
+	bus_space_write_1(sc->sc_bst, sc->sc_bsh, 1, datum);
 }
 
Index: arch/arc/jazz/mcclock_jazzio.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/jazz/mcclock_jazzio.c,v
retrieving revision 1.5
diff -u -r1.5 mcclock_jazzio.c
--- arch/arc/jazz/mcclock_jazzio.c	7 Aug 2003 16:26:51 -0000	1.5
+++ arch/arc/jazz/mcclock_jazzio.c	25 Oct 2003 20:19:09 -0000
@@ -88,20 +88,22 @@
 #include <machine/autoconf.h>
 #include <machine/bus.h>
 
+#include <dev/clock_subr.h>
+
 #include <dev/ic/mc146818reg.h>
+#include <dev/ic/mc146818var.h>
 
-#include <arc/dev/mcclockvar.h>
 #include <arc/jazz/jazziovar.h>
 #include <arc/jazz/mcclock_jazziovar.h>
 
-int mcclock_jazzio_match __P((struct device *, struct cfdata *, void *));
-void mcclock_jazzio_attach __P((struct device *, struct device *, void *));
+int mcclock_jazzio_match(struct device *, struct cfdata *, void *);
+void mcclock_jazzio_attach(struct device *, struct device *, void *);
 
-CFATTACH_DECL(mcclock_jazzio, sizeof(struct mcclock_softc),
+CFATTACH_DECL(mcclock_jazzio, sizeof(struct mc146818_softc),
     mcclock_jazzio_match, mcclock_jazzio_attach, NULL, NULL);
 
 struct mcclock_jazzio_config *mcclock_jazzio_conf = NULL;
-int mcclock_jazzio_found = 0;
+static int mcclock_jazzio_found = 0;
 
 int
 mcclock_jazzio_match(parent, match, aux)
@@ -127,23 +129,31 @@
 	struct device *self;
 	void *aux;
 {
-	struct mcclock_softc *sc = (struct mcclock_softc *)self;
+	struct mc146818_softc *sc = (void *)self;
 	struct jazzio_attach_args *ja = aux;
 
 	if (mcclock_jazzio_conf == NULL)
 		panic("mcclock_jazzio_conf isn't initialized");
 
-	sc->sc_iot = ja->ja_bust;
-	if (bus_space_map(sc->sc_iot,
-	    ja->ja_addr, mcclock_jazzio_conf->mjc_iosize, 0, &sc->sc_ioh)) {
+	sc->sc_bst = ja->ja_bust;
+	if (bus_space_map(sc->sc_bst,
+	    ja->ja_addr, mcclock_jazzio_conf->mjc_iosize, 0, &sc->sc_bsh)) {
 		printf(": unable to map I/O space\n");
 		return;
 	}
 
-	mcclock_attach(sc, &mcclock_jazzio_conf->mjc_mcbusfns, 80);
+	sc->sc_year0 = 1980;
+	sc->sc_mcread  = mcclock_jazzio_conf->mjc_mc_read;
+	sc->sc_mcwrite = mcclock_jazzio_conf->mjc_mc_write;
+
+	mc146818_attach(sc);
+
+	printf("\n");
 
 	/* Turn interrupts off, just in case. */
-	mc146818_write(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR);
+	(*sc->sc_mcwrite)(sc, MC_REGB, MC_REGB_BINARY | MC_REGB_24HR);
 
 	mcclock_jazzio_found = 1;
+
+	todr_attach(&sc->sc_handle);
 }
Index: arch/arc/jazz/mcclock_jazziovar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/arc/jazz/mcclock_jazziovar.h,v
retrieving revision 1.1
diff -u -r1.1 mcclock_jazziovar.h
--- arch/arc/jazz/mcclock_jazziovar.h	13 Jun 2001 15:02:15 -0000	1.1
+++ arch/arc/jazz/mcclock_jazziovar.h	25 Oct 2003 20:19:09 -0000
@@ -39,7 +39,8 @@
 struct mcclock_jazzio_config {
 	bus_addr_t mjc_iobase;
 	bus_size_t mjc_iosize;
-	struct mcclock_busfns mjc_mcbusfns;
+	u_int (*mjc_mc_read)(struct mc146818_softc *, u_int);
+	void  (*mjc_mc_write)(struct mc146818_softc *, u_int, u_int);
 };
 
-struct mcclock_jazzio_config *mcclock_jazzio_conf;
+extern struct mcclock_jazzio_config *mcclock_jazzio_conf;