Subject: Re: generic TODR changes for shark and ofppc
To: Garrett D'Amore <garrett_damore@tadpole.com>
From: Garrett D'Amore <garrett_damore@tadpole.com>
List: port-arm
Date: 09/12/2006 00:13:58
This is a multi-part message in MIME format.
--------------090900010404040503010107
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

My apologies, the diff didn't have everything.  I missed the most
important files, which was ofrtc, in a different directory.  New diff
attached.

Garrett D'Amore wrote:
> Attached, find a diff that significantly changes the real-time-clock
> support for shark and ofppc.
>
> First, the old oftodclock.c hackery is gone, replaced by dev/ofw/ofrtc.
>
> The old ofrtc.c is changed, it no longer supports character entry
> points, but instead uses the new todr framework.
>
> One side effect of this is that ofppc should gain RTC clock support it
> lacked before.
>
> This has been tested and shown to work on shark. 
>
>   
> ------------------------------------------------------------------------
>
>   


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

Index: sys/arch/shark/conf/files.shark
===================================================================
RCS file: /cvsroot/src/sys/arch/shark/conf/files.shark,v
retrieving revision 1.10
diff -d -p -u -r1.10 files.shark
--- sys/arch/shark/conf/files.shark	11 Dec 2005 12:19:02 -0000	1.10
+++ sys/arch/shark/conf/files.shark	12 Sep 2006 07:13:05 -0000
@@ -43,7 +43,6 @@ include "dev/ofw/files.ofw"
 include "arch/arm/ofw/files.ofw"
 attach	ofbus at root with ofbus_root
 file	arch/shark/ofw/ofw.c
-file	arch/shark/ofw/oftodclock.c
 
 # console initialization
 file	arch/shark/shark/consinit.c
Index: sys/arch/shark/include/types.h
===================================================================
RCS file: /cvsroot/src/sys/arch/shark/include/types.h,v
retrieving revision 1.3
diff -d -p -u -r1.3 types.h
--- sys/arch/shark/include/types.h	3 Sep 2006 13:51:23 -0000	1.3
+++ sys/arch/shark/include/types.h	12 Sep 2006 07:13:05 -0000
@@ -9,5 +9,6 @@
 #define	__ARM_FIQ_INDIRECT
 
 #define	__HAVE_DEVICE_REGISTER
+#define	__HAVE_GENERIC_TODR
 
 #endif
Index: sys/arch/shark/ofw/oftodclock.c
===================================================================
RCS file: sys/arch/shark/ofw/oftodclock.c
diff -N sys/arch/shark/ofw/oftodclock.c
--- sys/arch/shark/ofw/oftodclock.c	11 Dec 2005 12:19:05 -0000	1.5
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,290 +0,0 @@
-/*	$NetBSD: oftodclock.c,v 1.5 2005/12/11 12:19:05 christos Exp $	*/
-
-/*
- * Copyright 1997
- * Digital Equipment Corporation. All rights reserved.
- *
- * This software is furnished under license and may be used and
- * copied only in accordance with the following terms and conditions.
- * Subject to these conditions, you may download, copy, install,
- * use, modify and distribute this software in source and/or binary
- * form. No title or ownership is transferred hereby.
- *
- * 1) Any source code used, modified or distributed must reproduce
- *    and retain this copyright notice and list of conditions as
- *    they appear in the source file.
- *
- * 2) No right is granted to use any trade name, trademark, or logo of
- *    Digital Equipment Corporation. Neither the "Digital Equipment
- *    Corporation" name nor any trademark or logo of Digital Equipment
- *    Corporation may be used to endorse or promote products derived
- *    from this software without the prior written permission of
- *    Digital Equipment Corporation.
- *
- * 3) This software is provided "AS-IS" and any express or implied
- *    warranties, including but not limited to, any implied warranties
- *    of merchantability, fitness for a particular purpose, or
- *    non-infringement are disclaimed. In no event shall DIGITAL be
- *    liable for any damages whatsoever, and in particular, DIGITAL
- *    shall not be liable for special, indirect, consequential, or
- *    incidental damages or damages for lost profits, loss of
- *    revenue or loss of use, whether such damages arise in contract,
- *    negligence, tort, under statute, in equity, at law or otherwise,
- *    even if advised of the possibility of such damage.
- */
-
-/* 
- *   Real time clock (RTC) functions using OFW /rtc device:
- *      inittodr()
- *      resettodr()
- */
-
-#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: oftodclock.c,v 1.5 2005/12/11 12:19:05 christos Exp $");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/time.h>
-#include <sys/kernel.h>
-
-#include <dev/ofw/openfirm.h>
-
-/* The OFW RTC interface, straight from wmb:
-
-selftest  ( -- error? )
-	Designed to be called from the "test" user interface command, e.g.
-		test /rtc
-	which displays a message if the test fails.
-	Basically all this does is to check the battery.
-
-check-battery  ( -- error? )
-	Called from an open instance; returns non-zero if the battery
-	is dead.  Also displays a message to that effect, which it probably
-	should not do.
-
-set-time  ( s m h d m y -- )
-get-time  ( -- s m h d m y )
-	Called from an open instance.
-	seconds: 0-59
-	minutes: 0-59
-	hours: 0-23
-	day: 1-31
-	month: 1-12
-	year: e.g. 1997
-*/
-
-#define OFRTC_SEC 0
-#define OFRTC_MIN 1
-#define OFRTC_HR  2
-#define OFRTC_DOM 3
-#define OFRTC_MON 4
-#define OFRTC_YR  5
-
-static int month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-#define	SECMIN	((unsigned)60)			/* seconds per minute */
-#define	SECHOUR	((unsigned)(60*SECMIN))		/* seconds per hour */
-#define	SECDAY	((unsigned)(24*SECHOUR))	/* seconds per day */
-#define	SECYR	((unsigned)(365*SECDAY))	/* seconds per common year */
-
-static int yeartoday(int);
-static void setthetime(time_t, int);
-
-static int
-yeartoday(year)
-	int year;
-{
-
-	return ((year % 4) ? 365 : 366);
-}
-
-static int timeset = 0;
-
-static void
-setthetime(thetime, warning)
-	time_t thetime;
-	int warning;
-{
-
-	timeset = 1;
-	time.tv_sec = thetime;
-	time.tv_usec = 0;
-
-	if (warning)
-		printf("WARNING: CHECK AND RESET THE DATE!\n");
-}
-
-static int ofrtc_phandle;
-static int ofrtc_ihandle = 0;
-static int ofrtcinited = 0;
-
-static void
-ofrtcinit(void)
-{
-	char buf[256];
-	int  l;
-	int  chosen;
-
-	if (ofrtcinited) return;
-
-	if ((ofrtc_phandle = OF_finddevice("/rtc")) == -1)
-		panic("OFW RTC: no package");
-
-	if ((l = OF_getprop(ofrtc_phandle, "device_type", buf, sizeof buf - 1)) < 0)
-		panic("OFW RTC: no device type");
-
-	if ((l >= sizeof buf) || strcmp(buf, "rtc"))
-		panic("OFW RTC: bad device type");
-
-	if ((chosen = OF_finddevice("/chosen")) == -1 ||
- 	    OF_getprop(chosen, "clock", &ofrtc_ihandle, sizeof(int)) < 0) {
-		ofrtc_ihandle = 0;
-		return;
-	}
-
-	ofrtc_ihandle = of_decode_int((unsigned char *)&ofrtc_ihandle);
-
-	ofrtcinited = 1;
-}
-
-static int
-ofrtcstatus(void)
-{
-	char status[256];
-	int  l;
-
-	if ((ofrtc_ihandle == 0) || (l = OF_getprop(ofrtc_phandle, "status", 
-	    status, sizeof status - 1)) < 0) {
-		printf("OFW RTC: old firmware does not support RTC\n");
-		return 0;
-	}
-
-	status[sizeof status - 1] = 0; /* always null terminate */
-
-	if (strcmp(status, "okay")) { /* something is wrong */
-		printf("RTC: %s\n", status);
-		return 0;
-	}
-
-	return 1; /* all systems are go */
-}
-
-/*
- * Initialize the time of day register, based on the time base which is, e.g.
- * from a filesystem.
- */
-void
-inittodr(base)
-        time_t base;
-{
-	time_t n;
-	int i, days = 0;
-	int date[6];
-	int yr;
-
-	/*
-	 * We mostly ignore the suggested time and go for the RTC clock time
-	 * stored in the CMOS RAM.  If the time can't be obtained from the
-	 * CMOS, or if the time obtained from the CMOS is 5 or more years
-	 * less than the suggested time, we used the suggested time.  (In
-	 * the latter case, it's likely that the CMOS battery has died.)
-	 */
-
-	if (base < 25*SECYR) {	/* if before 1995, something's odd... */
-		printf("WARNING: preposterous time in file system\n");
-		/* read the system clock anyway */
-		/* happy b-day sarina */
-		base = 26*SECYR + 24*SECDAY + 18 * SECHOUR + 58 * SECMIN;
-	}
-
-	ofrtcinit();
-
-	if (!ofrtcstatus()) {
-		setthetime(base, 1);
-		return;
-	}
-
-	if (OF_call_method("get-time", ofrtc_ihandle, 0, 6,
-	    date, date + 1, date + 2, date + 3, date + 4, date + 5)) {
-		printf("OFW RTC: get-time failed\n");
-		setthetime(base, 1);
-		return;
-	}
-	  
-	n  = date[OFRTC_SEC];
-	n += date[OFRTC_MIN]       * SECMIN;
-	n += date[OFRTC_HR]        * SECHOUR;
-	n += (date[OFRTC_DOM] - 1) * SECDAY;
-
-	yr = date[OFRTC_YR];
-
-	if (yeartoday(yr) == 366)
-		month[1] = 29;
-	for (i = date[OFRTC_MON] - 2; i >= 0; i--)
-		days += month[i];
-	month[1] = 28;
-	for (i = 1970; i < yr; i++)
-		days += yeartoday(i);
-	n += days * 3600 * 24;
-
-	n += rtc_offset * 60;
-
-	if (base < n - 5*SECYR)
-		printf("WARNING: file system time much less than clock time\n");
-
-	else if (base > n + 5*SECYR) {
-		printf("WARNING: clock time much less than file system time\n");
-		printf("WARNING: using file system time\n");
-		setthetime(base, 1);
-		return;
-	}
-
-	setthetime(n, 0);
-}
-
-/*
- * Reset the clock.
- */
-void
-resettodr(void)
-{
-	time_t n;
-	int diff, i, j;
-	int sec, minute, hr, dom, mon, yr;
-
-	/* old version of the firmware? */
-	if (ofrtc_ihandle == 0) return;
-
-	/*
-	 * We might have been called by boot() due to a crash early
-	 * on.  Don't reset the clock chip in this case.
-	 */
-	if (!timeset)
-		return;
-
-	diff = rtc_offset * 60;
-	n = (time.tv_sec - diff) % (3600 * 24);   /* hrs+mins+secs */
-	sec = n % 60;
-	n /= 60;
-	minute = n % 60;
-	hr  = n / 60;
-
-	n = (time.tv_sec - diff) / (3600 * 24);	/* days */
-
-	for (j = 1970, i = yeartoday(j); n >= i; j++, i = yeartoday(j))
-		n -= i;
-
-	yr = j;
-
-	if (i == 366)
-		month[1] = 29;
-	for (i = 0; n >= month[i]; i++)
-		n -= month[i];
-	month[1] = 28;
-	mon = ++i;
-	dom = ++n;
-
-	if (OF_call_method("set-time", ofrtc_ihandle, 6, 0,
-	     sec, minute, hr, dom, mon, yr))
-		printf("OFW RTC: set-time failed\n");
-}
Index: sys/arch/ofppc/conf/majors.ofppc
===================================================================
RCS file: /cvsroot/src/sys/arch/ofppc/conf/majors.ofppc,v
retrieving revision 1.19
diff -d -p -u -r1.19 majors.ofppc
--- sys/arch/ofppc/conf/majors.ofppc	11 Dec 2005 12:18:29 -0000	1.19
+++ sys/arch/ofppc/conf/majors.ofppc	12 Sep 2006 07:13:05 -0000
@@ -12,7 +12,7 @@ device-major	log		char 5
 device-major	swap		char 6   block 1	vmswap
 device-major	ofcons		char 7			ofcons
 device-major	ofdisk		char 8   block 0	ofdisk
-device-major	ofrtc		char 9			ofrtc
+#device-major	ofrtc		char 9			ofrtc
 device-major	bpf		char 10			bpfilter
 device-major	rnd		char 11			rnd
 device-major	raid		char 12  block 2	raid
Index: sys/arch/ofppc/include/types.h
===================================================================
RCS file: /cvsroot/src/sys/arch/ofppc/include/types.h,v
retrieving revision 1.5
diff -d -p -u -r1.5 types.h
--- sys/arch/ofppc/include/types.h	22 Sep 2002 08:31:00 -0000	1.5
+++ sys/arch/ofppc/include/types.h	12 Sep 2006 07:13:05 -0000
@@ -3,3 +3,4 @@
 #include <powerpc/types.h>
 
 #define	__HAVE_DEVICE_REGISTER
+#define	__HAVE_GENERIC_TODR
Index: sys/arch/ofppc/ofppc/clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/ofppc/ofppc/clock.c,v
retrieving revision 1.12
diff -d -p -u -r1.12 clock.c
--- sys/arch/ofppc/ofppc/clock.c	24 Dec 2005 22:45:36 -0000	1.12
+++ sys/arch/ofppc/ofppc/clock.c	12 Sep 2006 07:13:05 -0000
@@ -50,28 +50,6 @@ static u_long ns_per_tick = 320;
 long ticks_per_intr;
 volatile u_long lasttb;
 
-/*
- * 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.
- */
-/* ARGSUSED */
-void
-inittodr(base)
-	time_t base;
-{
-}
-
-/*
- * Similar to the above
- */
-void
-resettodr()
-{
-}
-
 void
 decr_intr(frame)
 	struct clockframe *frame;
Index: sys/dev/ofw/ofrtc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ofw/ofrtc.c,v
retrieving revision 1.19
diff -d -p -u -r1.19 ofrtc.c
--- sys/dev/ofw/ofrtc.c	29 Mar 2006 07:10:25 -0000	1.19
+++ sys/dev/ofw/ofrtc.c	12 Sep 2006 07:13:05 -0000
@@ -30,6 +30,38 @@
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+/*
+ * Copyright 1997
+ * Digital Equipment Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and conditions.
+ * Subject to these conditions, you may download, copy, install,
+ * use, modify and distribute this software in source and/or binary
+ * form. No title or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ *    and retain this copyright notice and list of conditions as
+ *    they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or logo of
+ *    Digital Equipment Corporation. Neither the "Digital Equipment
+ *    Corporation" name nor any trademark or logo of Digital Equipment
+ *    Corporation may be used to endorse or promote products derived
+ *    from this software without the prior written permission of
+ *    Digital Equipment Corporation.
+ *
+ * 3) This software is provided "AS-IS" and any express or implied
+ *    warranties, including but not limited to, any implied warranties
+ *    of merchantability, fitness for a particular purpose, or
+ *    non-infringement are disclaimed. In no event shall DIGITAL be
+ *    liable for any damages whatsoever, and in particular, DIGITAL
+ *    shall not be liable for special, indirect, consequential, or
+ *    incidental damages or damages for lost profits, loss of
+ *    revenue or loss of use, whether such damages arise in contract,
+ *    negligence, tort, under statute, in equity, at law or otherwise,
+ *    even if advised of the possibility of such damage.
+ */
 
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: ofrtc.c,v 1.19 2006/03/29 07:10:25 thorpej Exp $");
@@ -40,31 +72,31 @@ __KERNEL_RCSID(0, "$NetBSD: ofrtc.c,v 1.
 #include <sys/conf.h>
 #include <sys/event.h>
 
+#include <dev/clock_subr.h>
 #include <dev/ofw/openfirm.h>
 
+#define OFRTC_SEC 0
+#define OFRTC_MIN 1
+#define OFRTC_HR  2
+#define OFRTC_DOM 3
+#define OFRTC_MON 4
+#define OFRTC_YR  5
+
 struct ofrtc_softc {
 	struct device sc_dev;
 	int sc_phandle;
 	int sc_ihandle;
+	struct todr_chip_handle sc_todr;
 };
 
 static int ofrtc_match(struct device *, struct cfdata *, void *);
 static void ofrtc_attach(struct device *, struct device *, void *);
+static int ofrtc_gettod(todr_chip_handle_t, struct clock_ymdhms *);
+static int ofrtc_settod(todr_chip_handle_t, struct clock_ymdhms *);
 
 CFATTACH_DECL(ofrtc, sizeof(struct ofrtc_softc),
     ofrtc_match, ofrtc_attach, NULL, NULL);
 
-extern struct cfdriver ofrtc_cd;
-
-dev_type_open(ofrtc_open);
-dev_type_read(ofrtc_read);
-dev_type_write(ofrtc_write);
-
-const struct cdevsw ofrtc_cdevsw = {
-	ofrtc_open, nullclose, ofrtc_read, ofrtc_write, noioctl,
-	nostop, notty, nopoll, nommap, nokqfilter,
-};
-
 static int
 ofrtc_match(struct device *parent, struct cfdata *match, void *aux)
 {
@@ -88,6 +120,7 @@ ofrtc_attach(struct device *parent, stru
 	struct ofrtc_softc *of = device_private(self);
 	struct ofbus_attach_args *oba = aux;
 	char name[32];
+	char path[256];
 	int l;
 
 	of->sc_phandle = oba->oba_phandle;
@@ -98,115 +131,74 @@ ofrtc_attach(struct device *parent, stru
 	if (l >= sizeof name)
 		l = sizeof name - 1;
 	name[l] = 0;
-	printf(": %s\n", name);
-}
 
-int
-ofrtc_open(dev_t dev, int flags, int fmt, struct lwp *lwp)
-{
-	struct ofrtc_softc *of;
-	int unit = minor(dev);
-	char path[256];
-	int l;
-
-	if (unit >= ofrtc_cd.cd_ndevs)
-		return ENXIO;
-	if (!(of = ofrtc_cd.cd_devs[unit]))
-		return ENXIO;
 	if (!of->sc_ihandle) {
 		if ((l = OF_package_to_path(of->sc_phandle, path,
-		    sizeof path - 1)) < 0 ||
-		    l >= sizeof path)
-			return ENXIO;
+			 sizeof path - 1)) < 0 ||
+		    l >= sizeof path) {
+			aprint_error(": cannot determine package path\n");
+ 			return;
+		}
 		path[l] = 0;
 
 		if (!(of->sc_ihandle = OF_open(path))) {
-			if (of->sc_ihandle) {
-				OF_close(of->sc_ihandle);
-				of->sc_ihandle = 0;
-			}
-			return ENXIO;
-		}
-
-	}
-
-	return 0;
-}
-
-static void
-twodigit(char *bp, int i)
-{
-	*bp++ = i / 10 + '0';
-	*bp = i % 10 + '0';
-}
-
-static int
-twodigits(char *bp)
-{
-	int i;
+			aprint_error(": cannot open path\n");
+ 			return;
+ 		}
+ 	}
 
-	i = *bp++ - '0';
-	return i * 10 + *bp++ - '0';
+	of->sc_todr.todr_gettime_ymdhms = ofrtc_gettod;
+	of->sc_todr.todr_settime_ymdhms = ofrtc_settod;
+	of->sc_todr.cookie = of;
+	todr_attach(&of->sc_todr);
+	printf(": %s\n", name);
 }
 
 int
-ofrtc_read(dev_t dev, struct uio *uio, int flag)
+ofrtc_gettod(todr_chip_handle_t tch, struct clock_ymdhms *dt)
 {
-	struct ofrtc_softc *of = ofrtc_cd.cd_devs[minor(dev)];
+	struct ofrtc_softc *of = tch->cookie;
 	int date[6];
-	char buf[14];
-	int xlen;
 
-	if (uio->uio_offset >= sizeof buf)
-		return 0;
+	/*
+	 * We mostly ignore the suggested time and go for the RTC clock time
+	 * stored in the CMOS RAM.  If the time can't be obtained from the
+	 * CMOS, or if the time obtained from the CMOS is 5 or more years
+	 * less than the suggested time, we used the suggested time.  (In
+	 * the latter case, it's likely that the CMOS battery has died.)
+	 */
 
 	if (OF_call_method("get-time", of->sc_ihandle, 0, 6,
-			   date, date + 1, date + 2,
-			   date + 3, date + 4, date + 5))
+	    date, date + 1, date + 2, date + 3, date + 4, date + 5)) {
 		return EIO;
+	}
 
-	twodigit(buf, date[5] % 100);
-	twodigit(buf + 2, date[4]);
-	twodigit(buf + 4, date[3]);
-	twodigit(buf + 6, date[2]);
-	twodigit(buf + 8, date[1]);
-	buf[10] = '.';
-	twodigit(buf + 11, date[0]);
-	buf[13] = '\n';
-
-	xlen = sizeof(buf) - uio->uio_offset;
-	if (xlen > uio->uio_resid)
-		xlen = uio->uio_resid;
+	dt->dt_sec = date[OFRTC_SEC];
+	dt->dt_min = date[OFRTC_MIN];
+	dt->dt_hour = date[OFRTC_HR];
+	dt->dt_day = date[OFRTC_DOM];
+	dt->dt_mon = date[OFRTC_MON];
+	dt->dt_year = date[OFRTC_YR];
 
-	return uiomove((caddr_t)buf, xlen, uio);
+	return 0;
 }
 
 int
-ofrtc_write(dev_t dev, struct uio *uio, int flag)
+ofrtc_settod(todr_chip_handle_t tch, struct clock_ymdhms *dt)
 {
-	struct ofrtc_softc *of = ofrtc_cd.cd_devs[minor(dev)];
-	char buf[14];
-	int cnt, year, error;
-
-	/*
-	 * We require atomic updates!
-	 */
-	cnt = uio->uio_resid;
-	if (uio->uio_offset || (cnt != sizeof buf && cnt != sizeof buf - 1))
-		return EINVAL;
-
-	if ((error = uiomove((caddr_t)buf, sizeof buf, uio)) != 0)
-		return error;
+	struct ofrtc_softc *of = tch->cookie;
+	int sec, minute, hr, dom, mon, yr;
 
-	if (cnt == sizeof buf && buf[sizeof buf - 1] != '\n')
-		return EINVAL;
+	sec = dt->dt_sec;
+	minute = dt->dt_min;
+	hr = dt->dt_hour;
+	dom = dt->dt_day;
+	mon = dt->dt_mon;
+	yr = dt->dt_year;
 
-	year = twodigits(buf) + 1900;
-	if (year < 1970)
-		year += 100;
 	if (OF_call_method("set-time", of->sc_ihandle, 6, 0,
-			   twodigits(buf + 11), twodigits(buf + 8), twodigits(buf + 6),
-			   twodigits(buf + 4), twodigits(buf + 2), year))
+	     sec, minute, hr, dom, mon, yr))
 		return EIO;
+
 	return 0;
 }

--------------090900010404040503010107--