svn commit: r321746 - head/sys/dev/iicbus

Ian Lepore ian at FreeBSD.org
Mon Jul 31 01:36:52 UTC 2017


Author: ian
Date: Mon Jul 31 01:36:51 2017
New Revision: 321746
URL: https://svnweb.freebsd.org/changeset/base/321746

Log:
  Use the new clock_schedule() to arrange for clock_settime() to be called
  at the right time to keep the RTC hardware time in sync, instead of using
  pause_sbt() to sleep until the right time.

Modified:
  head/sys/dev/iicbus/ds1307.c
  head/sys/dev/iicbus/nxprtc.c

Modified: head/sys/dev/iicbus/ds1307.c
==============================================================================
--- head/sys/dev/iicbus/ds1307.c	Mon Jul 31 01:18:21 2017	(r321745)
+++ head/sys/dev/iicbus/ds1307.c	Mon Jul 31 01:36:51 2017	(r321746)
@@ -295,8 +295,13 @@ ds1307_start(void *xdev)
 	    CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
 	    ds1307_sqw_out_sysctl, "IU", "DS1307 square-wave output state");
 
-	/* Register as a clock with 1 second resolution. */
+        /*
+         * Register as a clock with 1 second resolution.  Schedule the
+         * clock_settime() method to be called just after top-of-second;
+         * resetting the time resets top-of-second in the hardware.
+         */
 	clock_register_flags(dev, 1000000, CLOCKF_SETTIME_NO_TS);
+	clock_schedule(dev, 1);
 }
 
 static int
@@ -351,19 +356,6 @@ ds1307_settime(device_t dev, struct timespec *ts)
 	uint8_t pmflags;
 
 	sc = device_get_softc(dev);
-
-	/* Sleep until 1ms into the second, to align RTC's second to ours. */
-	getnanotime(ts);
-	waitns = 1000000 - ts->tv_nsec;
-	if (waitns < 0)
-		waitns += 1000000000;
-	pause_sbt("set1307", nstosbt(waitns), 0, C_PREL(31));
-
-	/* Grab a fresh post-sleep idea of the time. */
-	getnanotime(ts);
-	ts->tv_sec -= utc_offset();
-	ts->tv_nsec = 0;
-	clock_ts_to_ct(ts, &ct);
 
 	/* If the chip is in AM/PM mode, adjust hour and set flags as needed. */
 	if (sc->sc_use_ampm) {

Modified: head/sys/dev/iicbus/nxprtc.c
==============================================================================
--- head/sys/dev/iicbus/nxprtc.c	Mon Jul 31 01:18:21 2017	(r321745)
+++ head/sys/dev/iicbus/nxprtc.c	Mon Jul 31 01:36:51 2017	(r321746)
@@ -513,10 +513,15 @@ nxprtc_start(void *dev)
 	 * we're using the timer to count fractional seconds, our resolution is
 	 * 1e6/64, about 15.6ms.  Without the timer we still align the RTC clock
 	 * when setting it so our error is an average .5s when reading it.
+	 * Schedule our clock_settime() method to be called at a .495ms offset
+	 * into the second, because the clock hardware resets the divider chain
+	 * to the mid-second point when you set the time and it takes about 5ms
+	 * of i2c bus activity to set the clock.
 	 */
 	resolution = sc->use_timer ? 1000000 / TMR_TICKS_SEC : 1000000 / 2;
 	clockflags = CLOCKF_GETTIME_NO_ADJ | CLOCKF_SETTIME_NO_TS;
 	clock_register_flags(sc->dev, resolution, clockflags);
+	clock_schedule(sc->dev, 495000000);
 }
 
 static int
@@ -599,7 +604,6 @@ nxprtc_settime(device_t dev, struct timespec *ts)
 	struct clocktime ct;
 	struct time_regs tregs;
 	struct nxprtc_softc *sc;
-	long waitns;
 	int err;
 	uint8_t cflag, cs1, pmflag;
 
@@ -608,16 +612,9 @@ nxprtc_settime(device_t dev, struct timespec *ts)
 	/*
 	 * We stop the clock, set the time, then restart the clock.  Half a
 	 * second after restarting the clock it ticks over to the next second.
-	 * So to align the RTC, sleep until system time is halfway through the
-	 * current second (shoot for .495 to allow time for i2c operations).
-	 */
-	getnanotime(ts);
-	waitns = 495000000 - ts->tv_nsec;
-	if (waitns < 0)
-		waitns += 1000000000;
-	pause_sbt("nxpset", nstosbt(waitns), 0, C_PREL(31));
-
-	/*
+	 * So to align the RTC, we schedule this function to be called when
+	 * system time is roughly halfway (.495) through the current second.
+	 *
 	 * Reserve use of the i2c bus and stop the RTC clock.  Note that if
 	 * anything goes wrong from this point on, we leave the clock stopped,
 	 * because we don't really know what state it's in.


More information about the svn-src-all mailing list