static int snvs_gettime(device_t dev, struct timespec *ts) { struct snvs_softc *sc; sbintime_t counter1, counter2; sc = device_get_softc(dev); /* If the clock is not enabled and valid, we can't help. */ if (!(RD4(sc, SNVS_LPCR) & LPCR_SRTC_ENV)) { return (EINVAL); } /* * The counter is clocked asynchronously to cpu accesses; read and * assemble the pieces of the counter until we get the same value twice. * The counter is 47 bits, organized as a 32.15 binary fixed-point * value. If we shift it up to the high order part of a 64-bit word it * turns into an sbintime. */ do { counter1 = (uint64_t)RD4(sc, SNVS_LPSRTCMR) << (SBT_LSB + 32); counter1 |= (uint64_t)RD4(sc, SNVS_LPSRTCLR) << (SBT_LSB); counter2 = (uint64_t)RD4(sc, SNVS_LPSRTCMR) << (SBT_LSB + 32); counter2 |= (uint64_t)RD4(sc, SNVS_LPSRTCLR) << (SBT_LSB); } while (counter1 != counter2); *ts = sbttots(counter1); clock_dbgprint_ts(sc->dev, CLOCK_DBG_READ, ts); return (0); }
static inline uint64_t sbintime2tick(sbintime_t time) { struct timespec val; val = sbttots(time); return val.tv_sec * HV_TIMER_FREQUENCY + val.tv_nsec / 100; }
static __inline uint64_t hyperv_sbintime2count(sbintime_t time) { struct timespec val; val = sbttots(time); return (val.tv_sec * HYPERV_TIMER_FREQ) + (val.tv_nsec / HYPERV_TIMER_NS_FACTOR); }