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.
This commit is contained in:
parent
4b1f61b073
commit
a0fd5a136c
@ -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
|
||||
@ -352,19 +357,6 @@ ds1307_settime(device_t dev, struct timespec *ts)
|
||||
|
||||
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) {
|
||||
pmflags = DS1307_HOUR_USE_AMPM;
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user