Subject: changes for MI todr(9) and mc146818 todclock
To: None <port-cobalt@NetBSD.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-cobalt
Date: 04/09/2006 02:12:21
I'd like to commit the attached diff to make cobalt port
use MI todr(9) functions with MI mc146818 todclock driver.

There is no functional change except attach message on boot,
but kernel config files have to be updated to config mcclock
device at mainbus. (see diff for conf/GENERIC)

If there is no objection, I'll commit this in a few days.
---
Izumi Tsutsui


Index: cobalt/clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/cobalt/cobalt/clock.c,v
retrieving revision 1.10
diff -u -r1.10 clock.c
--- cobalt/clock.c	5 Apr 2006 15:03:27 -0000	1.10
+++ cobalt/clock.c	8 Apr 2006 12:56:40 -0000
@@ -36,14 +36,27 @@
 
 #include <dev/clock_subr.h>
 
-#include <dev/ic/mc146818reg.h>
-
 #include <cobalt/cobalt/clockvar.h>
 
+static	todr_chip_handle_t todr_handle;
+
 void (*timer_start)(void *);
 long (*timer_read)(void *);
 void *timer_cookie;
 
+/*
+ * Common parts of todclock autoconfiguration.
+ */
+void
+todr_attach(todr_chip_handle_t handle)
+{
+
+	if (todr_handle)
+		panic("todr_attach: too many todclocks configured");
+
+	todr_handle = handle;
+}
+
 void
 cpu_initclocks(void)
 {
@@ -56,74 +69,71 @@
 	return;
 }
 
-u_int
-mc146818_read(void *sc, u_int reg)
-{
-
-	(*(volatile u_int8_t *)(MIPS_PHYS_TO_KSEG1(0x10000070))) = reg;
-	return (*(volatile u_int8_t *)(MIPS_PHYS_TO_KSEG1(0x10000071)));
-}
-
-void
-mc146818_write(void *sc, u_int reg, u_int datum)
-{
-
-	(*(volatile u_int8_t *)(MIPS_PHYS_TO_KSEG1(0x10000070))) = reg;
-	(*(volatile u_int8_t *)(MIPS_PHYS_TO_KSEG1(0x10000071))) = datum;
-}
-
+/*
+ * Set up the system's time, given a `reasonable' time value.
+ */
 void
 inittodr(time_t base)
 {
-	struct clock_ymdhms dt;
-	mc_todregs regs;
-	int s;
+	int badbase, waszero;
 
-	s = splclock();
-	MC146818_GETTOD(NULL, &regs)
-	splx(s);
+	if (todr_handle == NULL)
+		panic("inittodr: no todclock configured");
 
-	dt.dt_year = FROMBCD(regs[MC_YEAR]) + 2000;
-	dt.dt_mon = FROMBCD(regs[MC_MONTH]);
-	dt.dt_day = FROMBCD(regs[MC_DOM]);
-	dt.dt_wday = FROMBCD(regs[MC_DOW]);
-	dt.dt_hour = FROMBCD(regs[MC_HOUR]);
-	dt.dt_min = FROMBCD(regs[MC_MIN]);
-	dt.dt_sec = FROMBCD(regs[MC_SEC]);
+	badbase = 0;
+	waszero = (base == 0);
 
-	time.tv_sec = clock_ymdhms_to_secs(&dt);
+	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 */
+		/* 2006/4/1	12:00:00 */
+		base = 36 * SECYR + 91 * SECDAY + SECDAY / 2;
+		badbase = 1;
+	}
 
-	return;
+	if (todr_gettime(todr_handle, &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 clock.
+		 */
+		time.tv_sec = base;
+		if (!badbase)
+			resettodr();
+	} else {
+		int deltat = time.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);
+	}
+	printf(" -- CHECK AND RESET THE DATE!\n");
 }
 
+/*
+ * 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(void)
 {
-	mc_todregs regs;
-	struct clock_ymdhms dt;
-	int s;
 
-	if (cold == 1)
+	if (time.tv_sec == 0)
 		return;
 
-	s = splclock();
-	MC146818_GETTOD(NULL, &regs);
-	splx(s);
-
-	clock_secs_to_ymdhms(time.tv_sec, &dt);
-	regs[MC_YEAR] = TOBCD(dt.dt_year % 100);
-	regs[MC_MONTH] = TOBCD(dt.dt_mon);
-	regs[MC_DOM] = TOBCD(dt.dt_day);
-	regs[MC_DOW] = TOBCD(dt.dt_wday);
-	regs[MC_HOUR] = TOBCD(dt.dt_hour);
-	regs[MC_MIN] = TOBCD(dt.dt_min);
-	regs[MC_SEC] = TOBCD(dt.dt_sec);
-
-	s = splclock();
-	MC146818_PUTTOD(NULL, &regs);
-	splx(s);
-
-	return;
+	if (todr_settime(todr_handle, &time) != 0)
+		printf("resettodr: cannot set time in time-of-day clock\n");
 }
 
 void
Index: conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/cobalt/conf/GENERIC,v
retrieving revision 1.93
diff -u -r1.93 GENERIC
--- conf/GENERIC	8 Apr 2006 12:41:11 -0000	1.93
+++ conf/GENERIC	8 Apr 2006 12:56:40 -0000
@@ -156,6 +156,8 @@
 
 cpu0 		at mainbus?
 
+mcclock0	at mainbus? addr 0x10000070
+
 com0		at mainbus? addr 0x1c800000 level 3
 options 	COM_16650
 
Index: conf/files.cobalt
===================================================================
RCS file: /cvsroot/src/sys/arch/cobalt/conf/files.cobalt,v
retrieving revision 1.24
diff -u -r1.24 files.cobalt
--- conf/files.cobalt	7 Apr 2006 18:55:58 -0000	1.24
+++ conf/files.cobalt	8 Apr 2006 12:56:40 -0000
@@ -20,6 +20,10 @@
 attach com at mainbus with com_mainbus
 file arch/cobalt/dev/com_mainbus.c	com_mainbus	needs-flag
 
+device mcclock: mc146818
+attach mcclock at mainbus
+file arch/cobalt/dev/mcclock.c		mcclock		needs-flag
+
 device panel: hd44780
 attach panel at mainbus
 file arch/cobalt/dev/panel.c		panel
--- /dev/null	2006-04-08 19:28:10.000000000 +0900
+++ dev/mcclock.c	2006-04-06 21:55:55.000000000 +0900
@@ -0,0 +1,125 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (c) 1995, 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+
+#include <dev/clock_subr.h>
+#include <dev/ic/mc146818reg.h>
+#include <dev/ic/mc146818var.h>
+
+#define	MCCLOCK_NPORTS	2
+
+static int mcclock_match(struct device *, struct cfdata *, void *);
+static void mcclock_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(mcclock, sizeof (struct mc146818_softc),
+    mcclock_match, mcclock_attach, NULL, NULL);
+
+static void mcclock_write(struct mc146818_softc *, u_int, u_int);
+static u_int mcclock_read(struct mc146818_softc *, u_int);
+
+
+static int
+mcclock_match(struct device *parent, struct cfdata *match, void *aux)
+{
+	static int mcclock_found;
+
+	if (mcclock_found)
+		return 0;
+
+	mcclock_found = 1;
+
+	return 1;
+}
+
+static void
+mcclock_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct mc146818_softc *sc = (void *)self;
+	struct mainbus_attach_args *ma = aux;
+
+	sc->sc_bst = ma->ma_iot;
+	if (bus_space_map(sc->sc_bst, ma->ma_addr, MCCLOCK_NPORTS,
+	    0, &sc->sc_bsh)) {
+		aprint_error("mcclock_attach: unable to map registers\n");
+		return;
+	}
+
+	sc->sc_year0 = 2000;
+	sc->sc_mcread = mcclock_read;
+	sc->sc_mcwrite = mcclock_write;
+	sc->sc_flag = MC146818_BCD;
+	mc146818_attach(sc);
+
+	printf("\n");
+
+	(*sc->sc_mcwrite)(sc, MC_REGB, MC_REGB_24HR);
+
+	todr_attach(&sc->sc_handle);
+}
+
+static void
+mcclock_write(struct mc146818_softc *sc, u_int reg, u_int datum)
+{
+	bus_space_tag_t iot;
+	bus_space_handle_t ioh;
+
+	iot = sc->sc_bst;
+	ioh = sc->sc_bsh;
+
+	bus_space_write_1(iot, ioh, 0, reg);
+	bus_space_write_1(iot, ioh, 1, datum);
+}
+
+static u_int
+mcclock_read(struct mc146818_softc *sc, u_int reg)
+{
+	bus_space_tag_t iot;
+	bus_space_handle_t ioh;
+	u_int datum;
+
+	iot = sc->sc_bst;
+	ioh = sc->sc_bsh;
+
+	bus_space_write_1(iot, ioh, 0, reg);
+	datum = bus_space_read_1(iot, ioh, 1);
+
+	return datum;
+}