Beispiel #1
0
static int
opal_gettime(device_t dev, struct timespec *ts)
{
	int rv;
	struct clocktime ct;
	uint32_t ymd;
	uint64_t hmsm;

	do {
		rv = opal_call(OPAL_RTC_READ, vtophys(&ymd), vtophys(&hmsm));
		if (rv == OPAL_BUSY_EVENT) {
			rv = opal_call(OPAL_POLL_EVENTS, 0);
			pause("opalrtc", 1);
		}
	} while (rv == OPAL_BUSY_EVENT);

	if (rv != OPAL_SUCCESS)
		return (ENXIO);

	hmsm = be64toh(hmsm);
	ymd = be32toh(ymd);

	ct.nsec	= bcd2bin32((hmsm & 0x000000ffffff0000) >> 16) * 1000;
	ct.sec	= bcd2bin((hmsm & 0x0000ff0000000000) >> 40);
	ct.min	= bcd2bin((hmsm & 0x00ff000000000000) >> 48);
	ct.hour	= bcd2bin((hmsm & 0xff00000000000000) >> 56);

	ct.day	= bcd2bin((ymd & 0x000000ff) >> 0);
	ct.mon	= bcd2bin((ymd & 0x0000ff00) >> 8);
	ct.year	= bcd2bin32((ymd & 0xffff0000) >> 16);

	return (clock_ct_to_ts(&ct, ts));
}
Beispiel #2
0
static int
s3c2xx0_rtc_gettime(device_t dev, struct timespec *ts)
{
	struct s3c2xx0_rtc_softc *sc;
	struct clocktime ct;

#define READ_TIME() do {						\
	ct.year = YEAR_BASE + FROMBCD(bus_read_1(sc->mem_res, RTC_BCDYEAR)); \
	ct.mon = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDMON));		\
	ct.dow = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDDAY));		\
	ct.day = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDDATE));		\
	ct.hour = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDHOUR));	\
	ct.min = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDMIN));		\
	ct.sec = FROMBCD(bus_read_1(sc->mem_res, RTC_BCDSEC));		\
} while (0)

	sc = device_get_softc(dev);

	ct.nsec = 0;
	READ_TIME();
	/*
	 * Check if we could have read incorrect values
	 * as the values could have changed.
	 */
	if (ct.sec == 0) {
		READ_TIME();
	}

	ct.dow = -1;

#undef READ_TIME
	return (clock_ct_to_ts(&ct, ts));
}
Beispiel #3
0
static int
aw_rtc_gettime(device_t dev, struct timespec *ts)
{
	struct aw_rtc_softc *sc  = device_get_softc(dev);
	struct clocktime ct;
	uint32_t rdate, rtime;

	rdate = RTC_READ(sc, sc->rtc_date);
	rtime = RTC_READ(sc, sc->rtc_time);
	
	if ((rtime & TIME_MASK) == 0)
		rdate = RTC_READ(sc, sc->rtc_date);

	ct.sec = GET_SEC_VALUE(rtime);
	ct.min = GET_MIN_VALUE(rtime);
	ct.hour = GET_HOUR_VALUE(rtime);
	ct.day = GET_DAY_VALUE(rdate);
	ct.mon = GET_MON_VALUE(rdate);
	ct.year = GET_YEAR_VALUE(rdate) + YEAR_OFFSET;
	ct.dow = -1;
	/* RTC resolution is 1 sec */
	ct.nsec = 0;
	
	return (clock_ct_to_ts(&ct, ts));
}
Beispiel #4
0
static int
mv_rtc_gettime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	struct mv_rtc_softc *sc;
	uint32_t val;

	sc = device_get_softc(dev);

	val = mv_rtc_reg_read(sc, MV_RTC_TIME_REG);

	ct.nsec = 0;
	ct.sec = FROMBCD(val & 0x7f);
	ct.min = FROMBCD((val & 0x7f00) >> 8);
	ct.hour = FROMBCD((val & 0x3f0000) >> 16);
	ct.dow = FROMBCD((val & 0x7000000) >> 24) - 1;

	val = mv_rtc_reg_read(sc, MV_RTC_DATE_REG);

	ct.day = FROMBCD(val & 0x7f);
	ct.mon = FROMBCD((val & 0x1f00) >> 8);
	ct.year = YEAR_BASE + FROMBCD((val & 0xff0000) >> 16);

	return (clock_ct_to_ts(&ct, ts));
}
Beispiel #5
0
int
as3722_rtc_gettime(device_t dev, struct timespec *ts)
{
	struct as3722_softc *sc;
	struct clocktime ct;
	uint8_t buf[6];
	int rv;

	sc = device_get_softc(dev);

	rv = as3722_read_buf(sc, AS3722_RTC_SECOND, buf, 6);
	if (rv != 0) {
		device_printf(sc->dev, "Failed to read RTC data\n");
		return (rv);
	}
	ct.nsec = 0;
	ct.sec = bcd2bin(buf[0] & 0x7F);
	ct.min = bcd2bin(buf[1] & 0x7F);
	ct.hour = bcd2bin(buf[2] & 0x3F);
	ct.day = bcd2bin(buf[3] & 0x3F);
	ct.mon = bcd2bin(buf[4] & 0x1F);
	ct.year = bcd2bin(buf[5] & 0x7F) + AS3722_RTC_START_YEAR;
	ct.dow = -1;

	return clock_ct_to_ts(&ct, ts);
}
Beispiel #6
0
static int
ds1307_gettime(device_t dev, struct timespec *ts)
{
	int error;
	struct clocktime ct;
	struct ds1307_softc *sc;
	uint8_t data[7];

	sc = device_get_softc(dev);
	memset(data, 0, sizeof(data));
	error = ds1307_read(sc->sc_dev, sc->sc_addr, DS1307_SECS,
	    data, sizeof(data)); 
	if (error != 0) {
		device_printf(dev, "cannot read from RTC.\n");
		return (error);
	}
	ct.nsec = 0;
	ct.sec = FROMBCD(data[DS1307_SECS] & DS1307_SECS_MASK);
	ct.min = FROMBCD(data[DS1307_MINS] & DS1307_MINS_MASK);
	ct.hour = FROMBCD(data[DS1307_HOUR] & DS1307_HOUR_MASK);
	ct.day = FROMBCD(data[DS1307_DATE] & DS1307_DATE_MASK);
	ct.dow = data[DS1307_WEEKDAY] & DS1307_WEEKDAY_MASK;
	ct.mon = FROMBCD(data[DS1307_MONTH] & DS1307_MONTH_MASK);
	ct.year = FROMBCD(data[DS1307_YEAR] & DS1307_YEAR_MASK);
	ct.year += sc->sc_year0;
	if (ct.year < POSIX_BASE_YEAR)
		ct.year += 100;	/* assume [1970, 2069] */

	return (clock_ct_to_ts(&ct, ts));
}
Beispiel #7
0
static int
rtas_gettime(device_t dev, struct timespec *ts) {
    struct clocktime ct;
    cell_t tod[8];
    cell_t token;
    int error;

    token = rtas_token_lookup("get-time-of-day");
    if (token == -1)
        return (ENXIO);
    error = rtas_call_method(token, 0, 8, &tod[0], &tod[1], &tod[2],
                             &tod[3], &tod[4], &tod[5], &tod[6], &tod[7]);
    if (error < 0)
        return (ENXIO);
    if (tod[0] != 0)
        return ((tod[0] == -1) ? ENXIO : EAGAIN);

    ct.year = tod[1];
    ct.mon  = tod[2];
    ct.day  = tod[3];
    ct.hour = tod[4];
    ct.min  = tod[5];
    ct.sec  = tod[6];
    ct.nsec = tod[7];

    return (clock_ct_to_ts(&ct, ts));
}
static int
nexus_gettime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	struct efi_tm tm;

	efi_get_time(&tm);

	/*
	 * This code was written in 2005, so logically EFI cannot return
	 * a year smaller than that. Assume the EFI clock is out of whack
	 * in that case and reset the EFI clock.
	 */
	if (tm.tm_year < 2005)
		return (EINVAL);

	ct.nsec = tm.tm_nsec;
	ct.sec = tm.tm_sec;
	ct.min = tm.tm_min;
	ct.hour = tm.tm_hour;
	ct.day = tm.tm_mday;
	ct.mon = tm.tm_mon;
	ct.year = tm.tm_year;
	ct.dow = -1;
	return (clock_ct_to_ts(&ct, ts));
}
Beispiel #9
0
/*
 * Board-specifc RTC read
 * Time is expressed in seconds from epoch (Jan 1 1970 at 00:00:00 UTC)
 * and converted internally to calendar format.
 */
uint32_t cvmx_rtc_ds1337_read(void)
{
    int       i, retry;
    uint8_t   reg[8];
    uint8_t   sec;
    struct clocktime ct;
    struct timespec ts;


    memset(&reg, 0, sizeof(reg));
    memset(&ct, 0, sizeof(ct));

    for(retry=0; retry<2; retry++)
    {
	/* Lockless read: detects the infrequent roll-over and retries */
	reg[0] = cvmx_twsi_read8(CVMX_RTC_DS1337_ADDR, 0x0);
	for(i=1; i<7; i++)
	    reg[i] = cvmx_twsi_read8_cur_addr(CVMX_RTC_DS1337_ADDR);

	sec = cvmx_twsi_read8(CVMX_RTC_DS1337_ADDR, 0x0);
	if ((sec & 0xf) == (reg[0] & 0xf))
	    break; /* Time did not roll-over, value is correct */
    }

    ct.sec  = bcd2bin(reg[0] & 0x7f);
    ct.min  = bcd2bin(reg[1] & 0x7f);
    ct.hour = bcd2bin(reg[2] & 0x3f);
    if ((reg[2] & 0x40) && (reg[2] & 0x20))   /* AM/PM format and is PM time */
    {
	ct.hour = (ct.hour + 12) % 24;
    }
    ct.dow = (reg[3] & 0x7);         /* Day of week field is 1..7 */
    ct.day = bcd2bin(reg[4] & 0x3f);
    ct.mon  = bcd2bin(reg[5] & 0x1f); /* Month field is 1..12 */
#if defined(OCTEON_BOARD_CAPK_0100ND)
    /*
     * CAPK-0100ND uses DS1307 that does not have century bit
     */
    ct.year = 2000 + bcd2bin(reg[6]);
#else
    ct.year = ((reg[5] & 0x80) ? 2000 : 1900) + bcd2bin(reg[6]);
#endif


    if (validate_ct_struct(&ct))
	cvmx_dprintf("Warning: RTC calendar is not configured properly\n");

    if (clock_ct_to_ts(&ct, &ts) != 0) {
	cvmx_dprintf("Warning: RTC calendar is not configured properly\n");
        return 0;
    }

    return ts.tv_sec;
}
Beispiel #10
0
/*
 * Get time of day and convert it to a struct timespec.
 * Return 0 on success, an error number otherwise.
 */
int
mc146818_gettime(device_t dev, struct timespec *ts)
{
	struct mc146818_softc *sc;
	struct clocktime ct;
	int timeout, cent, year;

	sc = device_get_softc(dev);

	timeout = 1000000;	/* XXX how long should we wait? */

	/*
	 * XXX:	Use a spinlock to mutex register access and increase the
	 *	likelihood that all registers are read before an update
	 *	occurs.
	 */

	/*
	 * If MC_REGA_UIP is 0 we have at least 244us before the next
	 * update. If it's 1 an update is imminent.
	 */
	for (;;) {
		if (!((*sc->sc_mcread)(dev, MC_REGA) & MC_REGA_UIP))
			break;
		if (--timeout < 0) {
			device_printf(dev, "mc146818_gettime: timeout\n");
			return (EBUSY);
		}
	}

#define	FROMREG(x)	((sc->sc_flag & MC146818_BCD) ? FROMBCD(x) : (x))

	ct.nsec = 0;
	ct.sec = FROMREG((*sc->sc_mcread)(dev, MC_SEC));
	ct.min = FROMREG((*sc->sc_mcread)(dev, MC_MIN));
	ct.hour = FROMREG((*sc->sc_mcread)(dev, MC_HOUR));
	ct.dow = FROMREG((*sc->sc_mcread)(dev, MC_DOW)) - 1;
	ct.day = FROMREG((*sc->sc_mcread)(dev, MC_DOM));
	ct.mon = FROMREG((*sc->sc_mcread)(dev, MC_MONTH));
	year = FROMREG((*sc->sc_mcread)(dev, MC_YEAR));
	if (sc->sc_getcent) {
		cent = (*sc->sc_getcent)(dev);
		year += cent * 100;
	}

	year += sc->sc_year0;
	if (year < POSIX_BASE_YEAR && !(sc->sc_flag & MC146818_NO_CENT_ADJUST))
		year += 100;
	ct.year = year;

	return (clock_ct_to_ts(&ct, ts));
}
/*
 * Get time of day and convert it to a struct timespec.
 * Return 0 on success, an error number otherwise.
 */
int
mc146818_gettime(device_t dev, struct timespec *ts)
{
	struct mc146818_softc *sc;
	struct clocktime ct;
	int timeout, cent, year;

	sc = device_get_softc(dev);

	timeout = 1000000;	/* XXX how long should we wait? */

	/*
	 * If MC_REGA_UIP is 0 we have at least 244us before the next
	 * update. If it's 1 an update is imminent.
	 */
	for (;;) {
		mtx_lock_spin(&sc->sc_mtx);
		if (!((*sc->sc_mcread)(dev, MC_REGA) & MC_REGA_UIP))
			break;
		mtx_unlock_spin(&sc->sc_mtx);
		if (--timeout < 0) {
			device_printf(dev, "%s: timeout\n", __func__);
			return (EBUSY);
		}
	}

#define	FROMREG(x)	((sc->sc_flag & MC146818_BCD) ? FROMBCD(x) : (x))

	ct.nsec = 0;
	ct.sec = FROMREG((*sc->sc_mcread)(dev, MC_SEC));
	ct.min = FROMREG((*sc->sc_mcread)(dev, MC_MIN));
	ct.hour = FROMREG((*sc->sc_mcread)(dev, MC_HOUR));
	/* Map dow from 1 - 7 to 0 - 6. */
	ct.dow = FROMREG((*sc->sc_mcread)(dev, MC_DOW)) - 1;
	ct.day = FROMREG((*sc->sc_mcread)(dev, MC_DOM));
	ct.mon = FROMREG((*sc->sc_mcread)(dev, MC_MONTH));
	year = FROMREG((*sc->sc_mcread)(dev, MC_YEAR));
	year += sc->sc_year0;
	if (sc->sc_flag & MC146818_NO_CENT_ADJUST) {
		cent = (*sc->sc_getcent)(dev);
		year += cent * 100;
	} else if (year < POSIX_BASE_YEAR)
		year += 100;
	mtx_unlock_spin(&sc->sc_mtx);

	ct.year = year;

	return (clock_ct_to_ts(&ct, ts));
}
Beispiel #12
0
static int
efirtc_gettime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	struct efi_tm tm;
	int error;

	error = efi_get_time(&tm);
	if (error != 0)
		return (error);

	ct.sec = tm.tm_sec;
	ct.min = tm.tm_min;
	ct.hour = tm.tm_hour;
	ct.day = tm.tm_mday;
	ct.mon = tm.tm_mon;
	ct.year = tm.tm_year;
	ct.nsec = tm.tm_nsec;

	clock_dbgprint_ct(dev, CLOCK_DBG_READ, &ct);
	return (clock_ct_to_ts(&ct, ts));
}
Beispiel #13
0
static int
pcf2123_rtc_gettime(device_t dev, struct timespec *ts)
{
    struct clocktime ct;
    struct spi_command cmd;
    unsigned char rxTimedate[8];
    unsigned char txTimedate[8];
    int err;

    memset(&cmd, 0, sizeof(cmd));
    memset(rxTimedate, 0, sizeof(rxTimedate));
    memset(txTimedate, 0, sizeof(txTimedate));

    /*
     * Counter is stopped when access to time registers is in progress
     * So there is no need to stop/start counter
     */
    /* Start reading from seconds */
    txTimedate[0] = PCF2123_READ(PCF2123_REG_SECONDS);
    cmd.rx_cmd = rxTimedate;
    cmd.tx_cmd = txTimedate;
    cmd.rx_cmd_sz = sizeof(rxTimedate);
    cmd.tx_cmd_sz = sizeof(txTimedate);
    err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd);
    DELAY(PCF2123_DELAY);

    ct.nsec = 0;
    ct.sec = FROMBCD(rxTimedate[1] & 0x7f);
    ct.min = FROMBCD(rxTimedate[2] & 0x7f);
    ct.hour = FROMBCD(rxTimedate[3] & 0x3f);

    ct.dow = FROMBCD(rxTimedate[5] & 0x3f);

    ct.day = FROMBCD(rxTimedate[4] & 0x3f);
    ct.mon = FROMBCD(rxTimedate[6] & 0x1f);
    ct.year = YEAR_BASE + FROMBCD(rxTimedate[7]);

    return (clock_ct_to_ts(&ct, ts));
}
Beispiel #14
0
static int
pcf8563_gettime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	uint8_t reg = PCF8563_R_SECOND, val[PCF8563_NCLOCKREGS];
	struct iic_msg msgs[] = {
		{ 0, IIC_M_WR, sizeof(reg), &reg },
		{ 0, IIC_M_RD, PCF8563_NCLOCKREGS, &val[PCF8563_R_SECOND] }
	};
	struct pcf8563_softc *sc;
	int error;

	sc = device_get_softc(dev);
	msgs[0].slave = msgs[1].slave = sc->sc_addr;
	error = iicbus_transfer(dev, msgs, nitems(msgs));
	if (error != 0) {
		device_printf(dev, "%s: cannot read RTC\n", __func__);
		return (error);
	}

	ct.nsec = 0;
	ct.sec = FROMBCD(val[PCF8563_R_SECOND] & PCF8563_M_SECOND);
	ct.min = FROMBCD(val[PCF8563_R_MINUTE] & PCF8563_M_MINUTE);
	ct.hour = FROMBCD(val[PCF8563_R_HOUR] & PCF8563_M_HOUR);
	ct.day = FROMBCD(val[PCF8563_R_DAY] & PCF8563_M_DAY);
	ct.dow = val[PCF8563_R_WEEKDAY] & PCF8563_M_WEEKDAY;
	ct.mon = FROMBCD(val[PCF8563_R_MONTH] & PCF8563_M_MONTH);
	ct.year = FROMBCD(val[PCF8563_R_YEAR] & PCF8563_M_YEAR);
	ct.year += sc->sc_year0;
	if (ct.year < POSIX_BASE_YEAR)
		ct.year += 100;	/* assume [1970, 2069] */
	if ((val[PCF8563_R_MONTH] & PCF8563_R_MONTH_C) != 0) {
		if (ct.year >= 100 + sc->sc_year0)
			sc->sc_flags |= PCF8563_CPOL;
	} else if (ct.year < 100 + sc->sc_year0)
			sc->sc_flags |= PCF8563_CPOL;

	return (clock_ct_to_ts(&ct, ts));
}
Beispiel #15
0
/*
 * Get time of day and convert it to a struct timespec.
 * Return 0 on success, an error number otherwise.
 */
int
ds1553_gettime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	struct ds1553_softc *sc;
	uint8_t control;

	sc = device_get_softc(dev);

	mtx_lock_spin(&sc->sc_mtx);

	control = (*sc->sc_read)(dev, DS1553_OFF_CONTROL) | DS1553_BIT_READ;
	(*sc->sc_write)(dev, DS1553_OFF_CONTROL, control);

	ct.nsec = 0;
	ct.sec = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_SECONDS) &
	    DS1553_MASK_SECONDS);
	ct.min = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_MINUTES) &
	    DS1553_MASK_MINUTES);
	ct.hour = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_HOURS) &
	    DS1553_MASK_HOUR);
	ct.dow = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_DAYOFWEEK) &
	    DS1553_MASK_DAYOFWEEK) - 1;
	ct.day = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_DATE) &
	    DS1553_MASK_DATE);
	ct.mon = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_MONTH) &
	    DS1553_MASK_MONTH);
	ct.year = FROMBCD((*sc->sc_read)(dev, DS1553_OFF_YEAR));

	control &= ~DS1553_BIT_READ;
	(*sc->sc_write)(dev, DS1553_OFF_CONTROL, control);

	ct.year += sc->year_offset;

	mtx_unlock_spin(&sc->sc_mtx);

	return (clock_ct_to_ts(&ct, ts));
}
Beispiel #16
0
/*
 * Get the time of day clock and return it in ts.
 * Return 0 on success, an error number otherwise.
 */
static int
at91_rtc_gettime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	uint32_t calr, calr2, timr, timr2;
	struct at91_rtc_softc *sc;

	sc = device_get_softc(dev);

	/* If the error bits are set we can't return useful values. */

	if (RD4(sc, RTC_VER) & (RTC_VER_NVTIM | RTC_VER_NVCAL))
		return EINVAL;

	/*
	 * The RTC hardware can update registers while the CPU is reading them.
	 * The manual advises reading until you obtain the same values twice.
	 * Interleaving the reads (rather than timr, timr2, calr, calr2 order)
	 * also ensures we don't miss a midnight rollover/carry between reads.
	 */
	do {
		timr = RD4(sc, RTC_TIMR);
		calr = RD4(sc, RTC_CALR);
		timr2 = RD4(sc, RTC_TIMR);
		calr2 = RD4(sc, RTC_CALR);
	} while (timr != timr2 || calr != calr2);

	ct.nsec = 0;
	ct.sec = RTC_TIMR_SEC(timr);
	ct.min = RTC_TIMR_MIN(timr);
	ct.hour = RTC_TIMR_HR(timr);
	ct.year = RTC_CALR_CEN(calr) * 100 + RTC_CALR_YEAR(calr);
	ct.mon = RTC_CALR_MON(calr);
	ct.day = RTC_CALR_DAY(calr);
	ct.dow = -1;
	return clock_ct_to_ts(&ct, ts);
}
static int
atrtc_gettime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	int s;

	/* Look if we have a RTC present and the time is valid */
	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR)) {
		device_printf(dev, "WARNING: Battery failure indication\n");
		return (EINVAL);
	}

	/* wait for time update to complete */
	/* If RTCSA_TUP is zero, we have at least 244us before next update */
	s = splhigh();
	while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
		splx(s);
		s = splhigh();
	}
	ct.nsec = 0;
	ct.sec = readrtc(RTC_SEC);
	ct.min = readrtc(RTC_MIN);
	ct.hour = readrtc(RTC_HRS);
	ct.day = readrtc(RTC_DAY);
	ct.dow = readrtc(RTC_WDAY) - 1;
	ct.mon = readrtc(RTC_MONTH);
	ct.year = readrtc(RTC_YEAR);
#ifdef USE_RTC_CENTURY
	ct.year += readrtc(RTC_CENTURY) * 100;
#else
	ct.year += 2000;
#endif
	/* Set dow = -1 because some clocks don't set it correctly. */
	ct.dow = -1;
	return (clock_ct_to_ts(&ct, ts));
}