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. _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"