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);
}
Exemple #2
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;
}
Exemple #3
0
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);
}