Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 Mar 2018 23:01:10 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r331503 - in stable/11/sys: conf dev/iicbus kern modules/i2c modules/i2c/ds1672 modules/i2c/rtc8583 sys x86/isa
Message-ID:  <201803242301.w2ON1AiX023472@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sat Mar 24 23:01:10 2018
New Revision: 331503
URL: https://svnweb.freebsd.org/changeset/base/331503

Log:
  MFC r325233, r328956, r329170, r329172-r329173, r329224, r330403-r330407,
      r330411-r330412, r330416, r330430-r330431, r330433, r330528-r330529,
      r330767
  
  r325233:
  [i2c/clock] add support for EPSON RTC-8583
  
  RTC-8583 is time-of-day clock used in some SOHO routers. This clock has
  only 2 bits for year values, but thanks to user SRAM it's possible to save
  year value and keep it up to date via driver code.
  
  Tested on Planex_MZK-W300NAG (SoC is RT2880)
  
  Submitted by:	Hiroki Mori <yamori83@yahoo.co.jp>
  Differential Revision:	https://reviews.freebsd.org/D12833
  
  r328956:
  Use const pointers for input data not modified by clock utility functions.
  
  r329170:
  Replace the existing print_ct() private debugging function with a set of
  three public functions to format and print the three major data structures
  used by realtime clock drivers (clocktime, bcd_clocktime, and timespec).
  
  r329172:
  Add a set of convenience routines for RTC drivers to use for debug output,
  and a debug.clock_show_io sysctl to control debugging output.
  
  r329173:
  Add a new sysctl, debug.clock_do_io, to allow manully triggering a one-shot
  read or write of all registered realtime clocks.  In the read case, the
  values read are simply discarded.  For writes, there's no alternative but
  to actually write the current system time to the device.
  
  r329224:
  Fix bad indentation.  Whitespace only, no functional changes.
  
  Reported by:	bde@
  
  r330403:
  Add calls to the new clock_dbgprint_xxx() functions.
  
  r330404:
  Add calls to the new clock_dbgprint_xxx() functions.
  
  r330405:
  Oops, fix a paste-o.
  
  r330406:
  Add calls to the new clock_dbgprint_xxx() functions.
  
  r330407:
  Add calls to the new clock_dbgprint_xxx() functions.  Also, stop applying
  a local .5 second adjustment to the time, since that is now done by the
  code in subr_rtc.c.
  
  r330411:
  Convert to the new(ish) bcd_clocktime conversion functions, add calls to
  the new debug output functions, and when setting the clock, propagate the
  timespec nsecs to the 1/100ths register.
  
  r330412:
  Build iicbus/rtc8583 as a module.
  
  r330416:
  The year is stored in a single byte in sram, in binary format, as a count
  of years since the century, so strip the century out when converting to or
  from bcd_clocktime format (the conversion routines will infer century by
  pivoting on 70).
  
  r330430:
  Switch to the new bcd_clocktime conversion routines, and add calls to the
  new clock_dbgprint_xxx() functions.
  
  r330431:
  Switch to the new bcd_clocktime conversion routines, and add calls to the
  new clock_dbgprint_xxx() functions.
  
  r330433:
  Switch to the new bcd_clocktime conversion routines, and add calls to the
  new clock_dbgprint_xxx() functions.
  
  r330528:
  Fix a paste-o that broke the build.  There is no softc pointer here, just
  use the dev arg.
  
  Reported by:	Jonathan Looney <jonlooney@gmail.com>
  Pointy hat:	ian@
  
  r330529:
  Build the ds1672 driver as a module.  Add a detach() to unregister the rtc.
  
  r330767:
  Convert atrtc the new style rtc debugging output.  Remove the db show
  command handler which provided much the same information.  Removing the
  possibility of accessing the hardware regs from the debugger context
  paves the way for simplifying the locking code in the driver.

Added:
  stable/11/sys/dev/iicbus/rtc8583.c
     - copied, changed from r325233, head/sys/dev/iicbus/rtc8583.c
  stable/11/sys/modules/i2c/ds1672/
     - copied from r330529, head/sys/modules/i2c/ds1672/
  stable/11/sys/modules/i2c/rtc8583/
     - copied from r330412, head/sys/modules/i2c/rtc8583/
Modified:
  stable/11/sys/conf/files
  stable/11/sys/dev/iicbus/ds1307.c
  stable/11/sys/dev/iicbus/ds13rtc.c
  stable/11/sys/dev/iicbus/ds1672.c
  stable/11/sys/dev/iicbus/ds3231.c
  stable/11/sys/dev/iicbus/isl12xx.c
  stable/11/sys/dev/iicbus/nxprtc.c
  stable/11/sys/dev/iicbus/s35390a.c
  stable/11/sys/kern/subr_clock.c
  stable/11/sys/kern/subr_fattime.c
  stable/11/sys/kern/subr_rtc.c
  stable/11/sys/modules/i2c/Makefile
  stable/11/sys/sys/clock.h
  stable/11/sys/x86/isa/atrtc.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/conf/files
==============================================================================
--- stable/11/sys/conf/files	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/conf/files	Sat Mar 24 23:01:10 2018	(r331503)
@@ -1768,6 +1768,7 @@ dev/iicbus/ds1307.c		optional ds1307
 dev/iicbus/ds13rtc.c		optional ds13rtc | ds133x | ds1374
 dev/iicbus/ds1672.c		optional ds1672
 dev/iicbus/ds3231.c		optional ds3231
+dev/iicbus/rtc8583.c		optional rtc8583
 dev/iicbus/icee.c		optional icee
 dev/iicbus/if_ic.c		optional ic
 dev/iicbus/iic.c		optional iic

Modified: stable/11/sys/dev/iicbus/ds1307.c
==============================================================================
--- stable/11/sys/dev/iicbus/ds1307.c	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/dev/iicbus/ds1307.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -359,6 +359,7 @@ ds1307_gettime(device_t dev, struct timespec *ts)
 	bct.mon  = data[DS1307_MONTH] & DS1307_MONTH_MASK;
 	bct.year = data[DS1307_YEAR]  & DS1307_YEAR_MASK;
 
+	clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_READ, &bct); 
 	return (clock_bcd_to_ts(&bct, ts, sc->sc_use_ampm));
 }
 
@@ -379,6 +380,7 @@ ds1307_settime(device_t dev, struct timespec *ts)
 	 */
 	ts->tv_sec -= utc_offset();
 	clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm);
+	clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_WRITE, &bct);
 
 	/* If the chip is in AM/PM mode, adjust hour and set flags as needed. */
 	if (sc->sc_use_ampm) {

Modified: stable/11/sys/dev/iicbus/ds13rtc.c
==============================================================================
--- stable/11/sys/dev/iicbus/ds13rtc.c	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/dev/iicbus/ds13rtc.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -395,6 +395,7 @@ ds13rtc_gettime(device_t dev, struct timespec *ts)
 	if (sc->use_century)
 		bct.year += (tregs.month & DS13xx_B_MONTH_CENTURY) ? 0x100 : 0;
 
+	clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct); 
 	err = clock_bcd_to_ts(&bct, ts, sc->use_ampm);
 
 	return (err);
@@ -422,6 +423,7 @@ ds13rtc_settime(device_t dev, struct timespec *ts)
 		return (write_timeword(sc, ts->tv_sec));
 
 	clock_ts_to_bcd(ts, &bct, sc->use_ampm);
+	clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct); 
 
 	/* If the chip is in AMPM mode deal with the PM flag. */
 	pmflags = 0;

Modified: stable/11/sys/dev/iicbus/ds1672.c
==============================================================================
--- stable/11/sys/dev/iicbus/ds1672.c	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/dev/iicbus/ds1672.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -54,8 +54,6 @@ __FBSDID("$FreeBSD$");
 
 #define	DS1672_CTRL_EOSC	(1 << 7)	/* Stop/start flag. */
 
-#define NANOSEC		1000000000
-
 #define	MAX_IIC_DATA_SIZE	4
 
 struct ds1672_softc {
@@ -120,6 +118,14 @@ ds1672_init(device_t dev)
 }
 
 static int
+ds1672_detach(device_t dev)
+{
+
+    clock_unregister(dev);
+    return (0);
+}
+
+static int
 ds1672_attach(device_t dev)
 {
 	struct ds1672_softc *sc = device_get_softc(dev);
@@ -144,8 +150,9 @@ ds1672_gettime(device_t dev, struct timespec *ts)
 		/* counter has seconds since epoch */
 		ts->tv_sec = (secs[3] << 24) | (secs[2] << 16)
 			   | (secs[1] <<  8) | (secs[0] <<  0);
-		ts->tv_nsec = NANOSEC / 2;
+		ts->tv_nsec = 0;
 	}
+	clock_dbgprint_ts(dev, CLOCK_DBG_READ, ts); 
 	return (error);
 }
 
@@ -159,12 +166,15 @@ ds1672_settime(device_t dev, struct timespec *ts)
 	data[2] = (ts->tv_sec >> 16) & 0xff;
 	data[3] = (ts->tv_sec >> 24) & 0xff;
 
+	ts->tv_nsec = 0;
+	clock_dbgprint_ts(dev, CLOCK_DBG_WRITE, ts);
 	return (ds1672_write(dev, DS1672_COUNTER, data, 4));
 }
 
 static device_method_t ds1672_methods[] = {
 	DEVMETHOD(device_probe,		ds1672_probe),
 	DEVMETHOD(device_attach,	ds1672_attach),
+	DEVMETHOD(device_detach,	ds1672_detach),
 
 	DEVMETHOD(clock_gettime,	ds1672_gettime),
 	DEVMETHOD(clock_settime,	ds1672_settime),

Modified: stable/11/sys/dev/iicbus/ds3231.c
==============================================================================
--- stable/11/sys/dev/iicbus/ds3231.c	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/dev/iicbus/ds3231.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -377,7 +377,7 @@ ds3231_attach(device_t dev)
 	sc->sc_dev = dev;
 	sc->sc_addr = iicbus_get_addr(dev);
 	sc->sc_last_c = -1;
-	sc->sc_year0 = 1900;
+	sc->sc_year0 = 0;
 	sc->enum_hook.ich_func = ds3231_start;
 	sc->enum_hook.ich_arg = dev;
 
@@ -477,7 +477,7 @@ static int
 ds3231_gettime(device_t dev, struct timespec *ts)
 {
 	int c, error;
-	struct clocktime ct;
+	struct bcd_clocktime bct;
 	struct ds3231_softc *sc;
 	uint8_t data[7], hourmask;
 
@@ -505,13 +505,14 @@ ds3231_gettime(device_t dev, struct timespec *ts)
 	} else
 		hourmask = DS3231_HOUR_MASK_24HR;
 
-	ct.nsec = 0;
-	ct.sec  = FROMBCD(data[DS3231_SECS]  & DS3231_SECS_MASK);
-	ct.min  = FROMBCD(data[DS3231_MINS]  & DS3231_MINS_MASK);
-	ct.hour = FROMBCD(data[DS3231_HOUR]  & hourmask);
-	ct.day  = FROMBCD(data[DS3231_DATE]  & DS3231_DATE_MASK);
-	ct.mon  = FROMBCD(data[DS3231_MONTH] & DS3231_MONTH_MASK);
-	ct.year = FROMBCD(data[DS3231_YEAR]  & DS3231_YEAR_MASK);
+	bct.nsec = 0;
+	bct.sec  = data[DS3231_SECS]  & DS3231_SECS_MASK;
+	bct.min  = data[DS3231_MINS]  & DS3231_MINS_MASK;
+	bct.hour = data[DS3231_HOUR]  & hourmask;
+	bct.day  = data[DS3231_DATE]  & DS3231_DATE_MASK;
+	bct.mon  = data[DS3231_MONTH] & DS3231_MONTH_MASK;
+	bct.year = data[DS3231_YEAR]  & DS3231_YEAR_MASK;
+	bct.ispm = data[DS3231_HOUR]  & DS3231_HOUR_IS_PM;
 
 	/*
 	 * If the century flag has toggled since we last saw it, there has been
@@ -522,29 +523,20 @@ ds3231_gettime(device_t dev, struct timespec *ts)
 	if (sc->sc_last_c == -1)
 		sc->sc_last_c = c;
 	else if (c != sc->sc_last_c) {
-		sc->sc_year0 += 100;
+		sc->sc_year0 += 0x100;
 		sc->sc_last_c = c;
 	}
-	ct.year += sc->sc_year0;
-	if (ct.year < POSIX_BASE_YEAR)
-		ct.year += 100;	/* assume [1970, 2069] */
+	bct.year |= sc->sc_year0;
 
-	/* If running in AM/PM mode, deal with it. */
-	if (sc->sc_use_ampm) {
-		if (ct.hour == 12)
-			ct.hour = 0;
-		if (data[DS3231_HOUR] & DS3231_HOUR_IS_PM)
-			ct.hour += 12;
-	}
-
-	return (clock_ct_to_ts(&ct, ts));
+	clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_READ, &bct); 
+	return (clock_bcd_to_ts(&bct, ts, sc->sc_use_ampm));
 }
 
 static int
 ds3231_settime(device_t dev, struct timespec *ts)
 {
 	int error;
-	struct clocktime ct;
+	struct bcd_clocktime bct;
 	struct ds3231_softc *sc;
 	uint8_t data[7];
 	uint8_t pmflags;
@@ -556,27 +548,24 @@ ds3231_settime(device_t dev, struct timespec *ts)
 	 * disables utc adjustment, so apply that ourselves.
 	 */
 	ts->tv_sec -= utc_offset();
-	clock_ts_to_ct(ts, &ct);
+	clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm);
+	clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_WRITE, &bct); 
 
 	/* If the chip is in AM/PM mode, adjust hour and set flags as needed. */
 	if (sc->sc_use_ampm) {
 		pmflags = DS3231_HOUR_USE_AMPM;
-		if (ct.hour >= 12) {
-			ct.hour -= 12;
+		if (bct.ispm)
 			pmflags |= DS3231_HOUR_IS_PM;
-		}
-		if (ct.hour == 0)
-			ct.hour = 12;
 	} else
 		pmflags = 0;
 
-	data[DS3231_SECS]    = TOBCD(ct.sec);
-	data[DS3231_MINS]    = TOBCD(ct.min);
-	data[DS3231_HOUR]    = TOBCD(ct.hour) | pmflags;
-	data[DS3231_DATE]    = TOBCD(ct.day);
-	data[DS3231_WEEKDAY] = ct.dow + 1;
-	data[DS3231_MONTH]   = TOBCD(ct.mon);
-	data[DS3231_YEAR]    = TOBCD(ct.year % 100);
+	data[DS3231_SECS]    = bct.sec;
+	data[DS3231_MINS]    = bct.min;
+	data[DS3231_HOUR]    = bct.hour | pmflags;
+	data[DS3231_DATE]    = bct.day;
+	data[DS3231_WEEKDAY] = bct.dow + 1;
+	data[DS3231_MONTH]   = bct.mon;
+	data[DS3231_YEAR]    = bct.year & 0xff;
 	if (sc->sc_last_c)
 		data[DS3231_MONTH] |= DS3231_C_MASK;
 

Modified: stable/11/sys/dev/iicbus/isl12xx.c
==============================================================================
--- stable/11/sys/dev/iicbus/isl12xx.c	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/dev/iicbus/isl12xx.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -233,7 +233,7 @@ static int
 isl12xx_gettime(device_t dev, struct timespec *ts)
 {
 	struct isl12xx_softc *sc = device_get_softc(dev);
-	struct clocktime ct;
+	struct bcd_clocktime bct;
 	struct time_regs tregs;
 	int err;
 	uint8_t hourmask, sreg;
@@ -263,29 +263,24 @@ isl12xx_gettime(device_t dev, struct timespec *ts)
 		hourmask = ISL12xx_12HR_MASK;
 	}
 
-	ct.nsec = 0;
-	ct.sec  = FROMBCD(tregs.sec);
-	ct.min  = FROMBCD(tregs.min);
-	ct.hour = FROMBCD(tregs.hour & hourmask);
-	ct.day  = FROMBCD(tregs.day);
-	ct.mon  = FROMBCD(tregs.month);
-	ct.year = FROMBCD(tregs.year);
+	bct.nsec = 0;
+	bct.sec  = tregs.sec;
+	bct.min  = tregs.min;
+	bct.hour = tregs.hour & hourmask;
+	bct.day  = tregs.day;
+	bct.mon  = tregs.month;
+	bct.year = tregs.year;
+	bct.ispm = tregs.hour & ISL12XX_PM_FLAG;
 
-	if (sc->use_ampm) {
-		if (ct.hour == 12)
-			ct.hour = 0;
-		if (tregs.hour & ISL12XX_PM_FLAG)
-			ct.hour += 12;
-	}
-
-	return (clock_ct_to_ts(&ct, ts));
+	clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct); 
+	return (clock_bcd_to_ts(&bct, ts, sc->use_ampm));
 }
 
 static int
 isl12xx_settime(device_t dev, struct timespec *ts)
 {
 	struct isl12xx_softc *sc = device_get_softc(dev);
-	struct clocktime ct;
+	struct bcd_clocktime bct;
 	struct time_regs tregs;
 	int err;
 	uint8_t ampmflags, sreg;
@@ -296,27 +291,21 @@ isl12xx_settime(device_t dev, struct timespec *ts)
 	 */
 	ts->tv_sec -= utc_offset();
 	ts->tv_nsec = 0;
-	clock_ts_to_ct(ts, &ct);
+	clock_ts_to_bcd(ts, &bct, sc->use_ampm);
+	clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct); 
 
-	/* If the chip is in AM/PM mode, adjust hour and set flags as needed. */
-	if (!sc->use_ampm) {
+	/* If the chip is in AM/PM mode, set flags as needed. */
+	if (!sc->use_ampm)
 		ampmflags = ISL12XX_24HR_FLAG;
-	} else {
-		ampmflags = 0;
-		if (ct.hour >= 12) {
-			ct.hour -= 12;
-			ampmflags |= ISL12XX_PM_FLAG;
-		}
-		if (ct.hour == 0)
-			ct.hour = 12;
-	}
+	else
+		ampmflags = bct.ispm ? ISL12XX_PM_FLAG : 0;
 
-	tregs.sec   = TOBCD(ct.sec);
-	tregs.min   = TOBCD(ct.min);
-	tregs.hour  = TOBCD(ct.hour) | ampmflags;
-	tregs.day   = TOBCD(ct.day);
-	tregs.month = TOBCD(ct.mon);
-	tregs.year  = TOBCD(ct.year % 100);
+	tregs.sec   = bct.sec;
+	tregs.min   = bct.min;
+	tregs.hour  = bct.hour | ampmflags;
+	tregs.day   = bct.day;
+	tregs.month = bct.mon;
+	tregs.year  = bct.year % 100;
 
 	/*
 	 * To set the time we have to set the WRTC enable bit in the control

Modified: stable/11/sys/dev/iicbus/nxprtc.c
==============================================================================
--- stable/11/sys/dev/iicbus/nxprtc.c	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/dev/iicbus/nxprtc.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -608,6 +608,7 @@ nxprtc_gettime(device_t dev, struct timespec *ts)
 				sc->flags |= SC_F_CPOL;
 	}
 
+	clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct); 
 	err = clock_bcd_to_ts(&bct, ts, sc->use_ampm);
 	ts->tv_sec += utc_offset();
 
@@ -648,6 +649,7 @@ nxprtc_settime(device_t dev, struct timespec *ts)
 	ts->tv_sec -= utc_offset();
 	ts->tv_nsec = 0;
 	clock_ts_to_bcd(ts, &bct, sc->use_ampm);
+	clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct);
 
 	/* On 8563 set the century based on the polarity seen when reading. */
 	cflag = 0;

Copied and modified: stable/11/sys/dev/iicbus/rtc8583.c (from r325233, head/sys/dev/iicbus/rtc8583.c)
==============================================================================
--- head/sys/dev/iicbus/rtc8583.c	Tue Oct 31 12:15:00 2017	(r325233, copy source)
+++ stable/11/sys/dev/iicbus/rtc8583.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -190,7 +190,7 @@ static int
 rtc8583_gettime(device_t dev, struct timespec *ts)
 {
 	struct rtc8583_softc	*sc;
-	struct clocktime	 ct;
+	struct bcd_clocktime	 bct;
 	struct time_regs	 tregs;
 	uint8_t			 y, ytmp, sreg;
 	int 			 err;
@@ -227,42 +227,49 @@ rtc8583_gettime(device_t dev, struct timespec *ts)
 		iicbus_release_bus(sc->busdev, sc->dev);
 	}
 
-	ct.nsec = FROMBCD(tregs.msec) * 10 * 1000 * 1000;
-	ct.sec  = FROMBCD(tregs.sec);
-	ct.min  = FROMBCD(tregs.min);
-	ct.hour = FROMBCD(tregs.hour & 0x3f);
-	ct.day  = FROMBCD(tregs.day & 0x3f);
-	ct.mon  = FROMBCD(tregs.month & 0x1f);
-	ct.year = 2000 + sreg;
+	if (!validbcd(tregs.msec))
+		return (EINVAL);
 
-	return (clock_ct_to_ts(&ct, ts));
+        /* The 'msec' reg is actually 1/100ths, in bcd.  */
+	bct.nsec = bcd2bin(tregs.msec) * 10 * 1000 * 1000;
+	bct.sec  = tregs.sec;
+	bct.min  = tregs.min;
+	bct.hour = tregs.hour & 0x3f;
+	bct.day  = tregs.day & 0x3f;
+	bct.mon  = tregs.month & 0x1f;
+	bct.year = bin2bcd(sreg % 100);
+
+	clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct); 
+	return (clock_bcd_to_ts(&bct, ts, false));
 }
 
 static int
 rtc8583_settime(device_t dev, struct timespec *ts)
 {
 	struct rtc8583_softc	*sc;
-	struct clocktime 	 ct;
+	struct bcd_clocktime 	 bct;
 	struct time_regs	 tregs;
 	uint8_t			 sreg;
 	int 			 err;
 
 	sc = device_get_softc(dev);
 	ts->tv_sec -= utc_offset();
-	ts->tv_nsec = 0;
-	clock_ts_to_ct(ts, &ct);
+	clock_ts_to_bcd(ts, &bct, false);
+	clock_dbgprint_bcd(sc->dev, CLOCK_DBG_WRITE, &bct);
 
-	tregs.sec   = TOBCD(ct.sec);
-	tregs.min   = TOBCD(ct.min);
-	tregs.hour  = TOBCD(ct.hour);
-	tregs.day   = TOBCD(ct.day) | ((ct.year & 0x03) << 6);
-	tregs.month = TOBCD(ct.mon);
+	/* The 'msec' reg is actually 1/100ths, in bcd.  */
+	tregs.msec  = bin2bcd(ts->tv_nsec / (10 * 1000 * 1000));
+	tregs.sec   = bct.sec;
+	tregs.min   = bct.min;
+	tregs.hour  = bct.hour;
+	tregs.day   = bct.day | (bct.year & 0x03 << 6);
+	tregs.month = bct.mon;
 
 	if ((err = iicbus_request_bus(sc->busdev, sc->dev, IIC_WAIT)) != 0)
 		return (err);
 	err = rtc8583_writeto(sc->dev, RTC8583_SC_REG, &tregs,
 	    sizeof(tregs), IIC_WAIT);
-	sreg = ct.year - 2000;
+	sreg = bcd2bin(bct.year & 0xff);
 	/* save to year to sram */
 	rtc8583_write1(sc, RTC8583_USERSRAM_REG, sreg);
 	iicbus_release_bus(sc->busdev, sc->dev);

Modified: stable/11/sys/dev/iicbus/s35390a.c
==============================================================================
--- stable/11/sys/dev/iicbus/s35390a.c	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/dev/iicbus/s35390a.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -297,7 +297,7 @@ static int
 s390rtc_gettime(device_t dev, struct timespec *ts)
 {
 	uint8_t bcd[S390_RT1_NBYTES];
-	struct clocktime ct;
+	struct bcd_clocktime bct;
 	int error;
 
 	error = s390rtc_read(dev, S390_REALTIME1, bcd, S390_RT1_NBYTES);
@@ -310,37 +310,39 @@ s390rtc_gettime(device_t dev, struct timespec *ts)
 	/*
 	 * Convert the register values into something useable.
 	 */
-	ct.nsec = 0;
-	ct.sec = FROMBCD(bcd[S390_RT1_SECOND]);
-	ct.min = FROMBCD(bcd[S390_RT1_MINUTE]);
-	ct.hour = FROMBCD(bcd[S390_RT1_HOUR] & 0x3f);
-	ct.day = FROMBCD(bcd[S390_RT1_DAY]);
-	ct.dow = bcd[S390_RT1_WDAY] & 0x07;
-	ct.mon = FROMBCD(bcd[S390_RT1_MONTH]);
-	ct.year = FROMBCD(bcd[S390_RT1_YEAR]) + 2000;
+	bct.nsec = 0;
+	bct.sec  = bcd[S390_RT1_SECOND];
+	bct.min  = bcd[S390_RT1_MINUTE];
+	bct.hour = bcd[S390_RT1_HOUR] & 0x3f;
+	bct.day  = bcd[S390_RT1_DAY];
+	bct.dow  = bcd[S390_RT1_WDAY] & 0x07;
+	bct.mon  = bcd[S390_RT1_MONTH];
+	bct.year = bcd[S390_RT1_YEAR];
 
-	return (clock_ct_to_ts(&ct, ts));
+	clock_dbgprint_bcd(dev, CLOCK_DBG_READ, &bct); 
+	return (clock_bcd_to_ts(&bct, ts, false));
 }
 
 static int
 s390rtc_settime(device_t dev, struct timespec *ts)
 {
 	uint8_t bcd[S390_RT1_NBYTES];
-	struct clocktime ct;
+	struct bcd_clocktime bct;
 
-	clock_ts_to_ct(ts, &ct);
+	clock_ts_to_bcd(ts, &bct, false);
+	clock_dbgprint_bcd(dev, CLOCK_DBG_WRITE, &bct); 
 
 	/*
 	 * Convert our time representation into something the S-xx390
 	 * can understand.
 	 */
-	bcd[S390_RT1_SECOND] = TOBCD(ct.sec);
-	bcd[S390_RT1_MINUTE] = TOBCD(ct.min);
-	bcd[S390_RT1_HOUR] = TOBCD(ct.hour);
-	bcd[S390_RT1_DAY] = TOBCD(ct.day);
-	bcd[S390_RT1_WDAY] = ct.dow;
-	bcd[S390_RT1_MONTH] = TOBCD(ct.mon);
-	bcd[S390_RT1_YEAR] = TOBCD(ct.year % 100);
+	bcd[S390_RT1_SECOND] = bct.sec;
+	bcd[S390_RT1_MINUTE] = bct.min;
+	bcd[S390_RT1_HOUR]   = bct.hour;
+	bcd[S390_RT1_DAY]    = bct.day;
+	bcd[S390_RT1_WDAY]   = bct.dow;
+	bcd[S390_RT1_MONTH]  = bct.mon;
+	bcd[S390_RT1_YEAR]   = bct.year & 0xff;
 
 	return (s390rtc_write(dev, S390_REALTIME1, bcd, S390_RT1_NBYTES));
 }

Modified: stable/11/sys/kern/subr_clock.c
==============================================================================
--- stable/11/sys/kern/subr_clock.c	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/kern/subr_clock.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -108,6 +108,14 @@ static const int recent_base_year = 2017;
 static const int recent_base_days = 17167;
 
 /*
+ * Table to 'calculate' pow(10, 9 - nsdigits) via lookup of nsdigits.
+ * Before doing the lookup, the code asserts 0 <= nsdigits <= 9.
+ */
+static u_int nsdivisors[] = {
+    1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1
+};
+
+/*
  * This inline avoids some unnecessary modulo operations
  * as compared with the usual macro:
  *   ( ((year % 4) == 0 &&
@@ -131,23 +139,15 @@ leapyear(int year)
 	return (rv);
 }
 
-static void
-print_ct(struct clocktime *ct)
-{
-	printf("[%04d-%02d-%02d %02d:%02d:%02d]",
-	    ct->year, ct->mon, ct->day,
-	    ct->hour, ct->min, ct->sec);
-}
-
 int
-clock_ct_to_ts(struct clocktime *ct, struct timespec *ts)
+clock_ct_to_ts(const struct clocktime *ct, struct timespec *ts)
 {
 	int i, year, days;
 
 	if (ct_debug) {
-		printf("ct_to_ts(");
-		print_ct(ct);
-		printf(")");
+		printf("ct_to_ts([");
+		clock_print_ct(ct, 9);
+		printf("])");
 	}
 
 	/*
@@ -200,7 +200,7 @@ clock_ct_to_ts(struct clocktime *ct, struct timespec *
 }
 
 int
-clock_bcd_to_ts(struct bcd_clocktime *bct, struct timespec *ts, bool ampm)
+clock_bcd_to_ts(const struct bcd_clocktime *bct, struct timespec *ts, bool ampm)
 {
 	struct clocktime ct;
 	int bcent, byear;
@@ -249,7 +249,7 @@ clock_bcd_to_ts(struct bcd_clocktime *bct, struct time
 }
 
 void
-clock_ts_to_ct(struct timespec *ts, struct clocktime *ct)
+clock_ts_to_ct(const struct timespec *ts, struct clocktime *ct)
 {
 	int i, year, days;
 	time_t rsec;	/* remainder seconds */
@@ -288,15 +288,15 @@ clock_ts_to_ct(struct timespec *ts, struct clocktime *
 	ct->sec  = rsec;
 	ct->nsec = ts->tv_nsec;
 	if (ct_debug) {
-		printf("ts_to_ct(%jd.%09ld) = ",
+		printf("ts_to_ct(%jd.%09ld) = [",
 		    (intmax_t)ts->tv_sec, ts->tv_nsec);
-		print_ct(ct);
-		printf("\n");
+		clock_print_ct(ct, 9);
+		printf("]\n");
 	}
 }
 
 void
-clock_ts_to_bcd(struct timespec *ts, struct bcd_clocktime *bct, bool ampm)
+clock_ts_to_bcd(const struct timespec *ts, struct bcd_clocktime *bct, bool ampm)
 {
 	struct clocktime ct;
 
@@ -321,6 +321,51 @@ clock_ts_to_bcd(struct timespec *ts, struct bcd_clockt
 	bct->sec  = TOBCD(ct.sec);
 	bct->dow  = ct.dow;
 	bct->nsec = ct.nsec;
+}
+
+void
+clock_print_bcd(const struct bcd_clocktime *bct, int nsdigits)
+{
+
+	KASSERT(nsdigits >= 0 && nsdigits <= 9, ("bad nsdigits %d", nsdigits));
+
+	if (nsdigits > 0) {
+		printf("%4.4x-%2.2x-%2.2x %2.2x:%2.2x:%2.2x.%*.*ld",
+		    bct->year, bct->mon, bct->day,
+		    bct->hour, bct->min, bct->sec,
+		    nsdigits, nsdigits, bct->nsec / nsdivisors[nsdigits]);
+	} else {
+		printf("%4.4x-%2.2x-%2.2x %2.2x:%2.2x:%2.2x",
+		    bct->year, bct->mon, bct->day,
+		    bct->hour, bct->min, bct->sec);
+	}
+}
+
+void
+clock_print_ct(const struct clocktime *ct, int nsdigits)
+{
+
+	KASSERT(nsdigits >= 0 && nsdigits <= 9, ("bad nsdigits %d", nsdigits));
+
+	if (nsdigits > 0) {
+		printf("%04d-%02d-%02d %02d:%02d:%02d.%*.*ld",
+		    ct->year, ct->mon, ct->day,
+		    ct->hour, ct->min, ct->sec,
+		    nsdigits, nsdigits, ct->nsec / nsdivisors[nsdigits]);
+	} else {
+		printf("%04d-%02d-%02d %02d:%02d:%02d",
+		    ct->year, ct->mon, ct->day,
+		    ct->hour, ct->min, ct->sec);
+	}
+}
+
+void
+clock_print_ts(const struct timespec *ts, int nsdigits)
+{
+	struct clocktime ct;
+
+	clock_ts_to_ct(ts, &ct);
+	clock_print_ct(&ct, nsdigits);
 }
 
 int

Modified: stable/11/sys/kern/subr_fattime.c
==============================================================================
--- stable/11/sys/kern/subr_fattime.c	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/kern/subr_fattime.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -135,7 +135,8 @@ static const struct {
 
 
 void
-timespec2fattime(struct timespec *tsp, int utc, uint16_t *ddp, uint16_t *dtp, uint8_t *dhp)
+timespec2fattime(const struct timespec *tsp, int utc, uint16_t *ddp,
+    uint16_t *dtp, uint8_t *dhp)
 {
 	time_t t1;
 	unsigned t2, l, m;
@@ -215,7 +216,8 @@ static const uint16_t daytab[64] = {
 };
 
 void
-fattime2timespec(unsigned dd, unsigned dt, unsigned dh, int utc, struct timespec *tsp)
+fattime2timespec(unsigned dd, unsigned dt, unsigned dh, int utc,
+    struct timespec *tsp)
 {
 	unsigned day;
 

Modified: stable/11/sys/kern/subr_rtc.c
==============================================================================
--- stable/11/sys/kern/subr_rtc.c	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/kern/subr_rtc.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -76,6 +76,15 @@ __FBSDID("$FreeBSD$");
 
 #include "clock_if.h"
 
+static int show_io;
+SYSCTL_INT(_debug, OID_AUTO, clock_show_io, CTLFLAG_RWTUN, &show_io, 0,
+    "Enable debug printing of RTC clock I/O; 1=reads, 2=writes, 3=both.");
+
+static int sysctl_clock_do_io(SYSCTL_HANDLER_ARGS);
+SYSCTL_PROC(_debug, OID_AUTO, clock_do_io, CTLTYPE_INT | CTLFLAG_RW,
+    0, 0, sysctl_clock_do_io, "I",
+    "Trigger one-time IO on RTC clocks; 1=read (and discard), 2=write");
+
 /* XXX: should be kern. now, it's no longer machdep.  */
 static int disable_rtc_set;
 SYSCTL_INT(_machdep, OID_AUTO, disable_rtc_set, CTLFLAG_RW, &disable_rtc_set,
@@ -144,7 +153,61 @@ settime_task_func(void *arg, int pending)
 	CLOCK_SETTIME(rtc->clockdev, &ts);
 }
 
+static void
+clock_dbgprint_hdr(device_t dev, int rw)
+{
+	struct timespec now;
+
+	getnanotime(&now);
+	device_printf(dev, "%s at ", (rw & CLOCK_DBG_READ) ? "read " : "write");
+	clock_print_ts(&now, 9);
+	printf(": "); 
+}
+
 void
+clock_dbgprint_bcd(device_t dev, int rw, const struct bcd_clocktime *bct)
+{
+
+	if (show_io & rw) {
+		clock_dbgprint_hdr(dev, rw);
+		clock_print_bcd(bct, 9);
+		printf("\n");
+	}
+}
+
+void
+clock_dbgprint_ct(device_t dev, int rw, const struct clocktime *ct)
+{
+
+	if (show_io & rw) {
+		clock_dbgprint_hdr(dev, rw);
+		clock_print_ct(ct, 9);
+		printf("\n");
+	}
+}
+
+void
+clock_dbgprint_err(device_t dev, int rw, int err)
+{
+
+	if (show_io & rw) {
+		clock_dbgprint_hdr(dev, rw);
+		printf("error = %d\n", err);
+	}
+}
+
+void
+clock_dbgprint_ts(device_t dev, int rw, const struct timespec *ts)
+{
+
+	if (show_io & rw) {
+		clock_dbgprint_hdr(dev, rw);
+		clock_print_ts(ts, 9);
+		printf("\n");
+	}
+}
+
+void
 clock_register_flags(device_t clockdev, long resolution, int flags)
 {
 	struct rtc_instance *rtc, *newrtc;
@@ -203,7 +266,7 @@ clock_unregister(device_t clockdev)
 	if (rtc != NULL) {
 		taskqueue_cancel_timeout(taskqueue_thread, &rtc->stask, NULL);
 		taskqueue_drain_timeout(taskqueue_thread, &rtc->stask);
-                free(rtc, M_DEVBUF);
+		free(rtc, M_DEVBUF);
 	}
 }
 
@@ -222,6 +285,36 @@ clock_schedule(device_t clockdev, u_int offsetns)
 	sx_xunlock(&rtc_list_lock);
 }
 
+static int
+read_clocks(struct timespec *ts, bool debug_read)
+{
+	struct rtc_instance *rtc;
+	int error;
+
+	error = ENXIO;
+	sx_xlock(&rtc_list_lock);
+	LIST_FOREACH(rtc, &rtc_list, rtc_entries) {
+		if ((error = CLOCK_GETTIME(rtc->clockdev, ts)) != 0)
+			continue;
+		if (ts->tv_sec < 0 || ts->tv_nsec < 0) {
+			error = EINVAL;
+			continue;
+		}
+		if (!(rtc->flags & CLOCKF_GETTIME_NO_ADJ)) {
+			timespecadd(ts, &rtc->resadj);
+			ts->tv_sec += utc_offset();
+		}
+		if (!debug_read) {
+			if (bootverbose)
+				device_printf(rtc->clockdev,
+				    "providing initial system time\n");
+			break;
+		}
+	}
+	sx_xunlock(&rtc_list_lock);
+	return (error);
+}
+
 /*
  * Initialize the system time.  Must be called from a context which does not
  * restrict any locking or sleeping that clock drivers may need to do.
@@ -238,28 +331,9 @@ void
 inittodr(time_t base)
 {
 	struct timespec ts;
-	struct rtc_instance *rtc;
 	int error;
 
-	error = ENXIO;
-	sx_xlock(&rtc_list_lock);
-	LIST_FOREACH(rtc, &rtc_list, rtc_entries) {
-		if ((error = CLOCK_GETTIME(rtc->clockdev, &ts)) != 0)
-			continue;
-		if (ts.tv_sec < 0 || ts.tv_nsec < 0) {
-			error = EINVAL;
-			continue;
-		}
-		if (!(rtc->flags & CLOCKF_GETTIME_NO_ADJ)) {
-			timespecadd(&ts, &rtc->resadj);
-			ts.tv_sec += utc_offset();
-		}
-		if (bootverbose)
-			device_printf(rtc->clockdev,
-			    "providing initial system time\n");
-		break;
-	}
-	sx_xunlock(&rtc_list_lock);
+	error = read_clocks(&ts, false);
 
 	/*
 	 * Do not report errors from each clock; it is expected that some clocks
@@ -321,4 +395,30 @@ resettodr(void)
 		    &rtc->stask, -sbt, 0, C_PREL(31));
 	}
 	sx_xunlock(&rtc_list_lock);
+}
+
+static int
+sysctl_clock_do_io(SYSCTL_HANDLER_ARGS)
+{
+	struct timespec ts_discard;
+	int error, value;
+
+	value = 0;
+	error = sysctl_handle_int(oidp, &value, 0, req);
+	if (error != 0 || req->newptr == NULL)
+		return (error);
+
+	switch (value) {
+	case CLOCK_DBG_READ:
+		if (read_clocks(&ts_discard, true) == ENXIO)
+			printf("No registered RTC clocks\n");
+		break;
+	case CLOCK_DBG_WRITE:
+		resettodr();
+		break;
+	default:
+                return (EINVAL);
+	}
+
+	return (0);
 }

Modified: stable/11/sys/modules/i2c/Makefile
==============================================================================
--- stable/11/sys/modules/i2c/Makefile	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/modules/i2c/Makefile	Sat Mar 24 23:01:10 2018	(r331503)
@@ -5,6 +5,7 @@ SUBDIR = \
 	cyapa \
 	ds1307 \
 	ds13rtc \
+	ds1672 \
 	ds3231 \
 	icee \
 	if_ic \
@@ -17,6 +18,7 @@ SUBDIR = \
 	jedec_dimm \
 	jedec_ts \
 	nxprtc \
+	rtc8583 \
 	s35390a \
 	smb \
 	smbus \

Modified: stable/11/sys/sys/clock.h
==============================================================================
--- stable/11/sys/sys/clock.h	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/sys/clock.h	Sat Mar 24 23:01:10 2018	(r331503)
@@ -88,8 +88,8 @@ struct clocktime {
 	long	nsec;			/* nano seconds */
 };
 
-int clock_ct_to_ts(struct clocktime *, struct timespec *);
-void clock_ts_to_ct(struct timespec *, struct clocktime *);
+int clock_ct_to_ts(const struct clocktime *, struct timespec *);
+void clock_ts_to_ct(const struct timespec *, struct clocktime *);
 
 /*
  * Structure to hold the values typically reported by time-of-day clocks,
@@ -125,8 +125,8 @@ struct bcd_clocktime {
 	bool     ispm;			/* true if hour represents pm time */
 };
 
-int clock_bcd_to_ts(struct bcd_clocktime *, struct timespec *, bool ampm);
-void clock_ts_to_bcd(struct timespec *, struct bcd_clocktime *, bool ampm);
+int clock_bcd_to_ts(const struct bcd_clocktime *, struct timespec *, bool ampm);
+void clock_ts_to_bcd(const struct timespec *, struct bcd_clocktime *, bool ampm);
 
 /*
  * Time-of-day clock functions and flags.  These functions might sleep.
@@ -177,8 +177,31 @@ void clock_unregister(device_t _clockdev);
 /* Traditional POSIX base year */
 #define	POSIX_BASE_YEAR	1970
 
-void timespec2fattime(struct timespec *tsp, int utc, u_int16_t *ddp, u_int16_t *dtp, u_int8_t *dhp);
-void fattime2timespec(unsigned dd, unsigned dt, unsigned dh, int utc, struct timespec *tsp);
+void timespec2fattime(const struct timespec *tsp, int utc, u_int16_t *ddp,
+    u_int16_t *dtp, u_int8_t *dhp);
+void fattime2timespec(unsigned dd, unsigned dt, unsigned dh, int utc,
+    struct timespec *tsp);
+
+/*
+ * Print a [bcd_]clocktime or timespec, optionally with fractional seconds.  The
+ * nsdig argument can range from 0-9, and specifies how many decimal digits to
+ * display for fractional seconds.
+ */
+void clock_print_bcd(const struct bcd_clocktime *bct, int nsdig);
+void clock_print_ct(const struct clocktime *ct, int nsdig);
+void clock_print_ts(const struct timespec  *ts, int nsdig);
+
+/*
+ * Debugging helpers for RTC clock drivers.  Print a [bcd_]clocktime or
+ * timespec, only if rtc clock debugging has been enabled.  The rw argument is
+ * one of CLOCK_DBG_READ or CLOCK_DBG_WRITE.
+ */
+#define	CLOCK_DBG_READ	0x01
+#define	CLOCK_DBG_WRITE	0x02
+void clock_dbgprint_bcd(device_t dev, int rw, const struct bcd_clocktime *bct);
+void clock_dbgprint_ct(device_t dev, int rw, const struct clocktime *ct);
+void clock_dbgprint_err(device_t dev, int rw, int err);
+void clock_dbgprint_ts(device_t dev, int rw, const struct timespec *ts);
 
 #endif /* _KERNEL */
 

Modified: stable/11/sys/x86/isa/atrtc.c
==============================================================================
--- stable/11/sys/x86/isa/atrtc.c	Sat Mar 24 22:50:59 2018	(r331502)
+++ stable/11/sys/x86/isa/atrtc.c	Sat Mar 24 23:01:10 2018	(r331503)
@@ -316,6 +316,7 @@ atrtc_settime(device_t dev __unused, struct timespec *
 	struct bcd_clocktime bct;
 
 	clock_ts_to_bcd(ts, &bct, false);
+	clock_dbgprint_bcd(dev, CLOCK_DBG_WRITE, &bct);
 
 	mtx_lock(&atrtc_time_lock);
 	RTC_LOCK;
@@ -383,6 +384,7 @@ atrtc_gettime(device_t dev, struct timespec *ts)
 	/* dow is unused in timespec conversion and we have no nsec info. */
 	bct.dow  = 0;
 	bct.nsec = 0;
+	clock_dbgprint_bcd(dev, CLOCK_DBG_READ, &bct);
 	return (clock_bcd_to_ts(&bct, ts, false));
 }
 
@@ -413,16 +415,3 @@ static devclass_t atrtc_devclass;
 
 DRIVER_MODULE(atrtc, isa, atrtc_driver, atrtc_devclass, 0, 0);
 DRIVER_MODULE(atrtc, acpi, atrtc_driver, atrtc_devclass, 0, 0);
-
-#include "opt_ddb.h"
-#ifdef DDB
-#include <ddb/ddb.h>
-
-DB_SHOW_COMMAND(rtc, rtc)
-{
-	printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n",
-		rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY),
-		rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC),
-		rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR));
-}
-#endif /* DDB */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803242301.w2ON1AiX023472>