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)); }
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)); }
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)); }
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)); }
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); }
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)); }
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)); }
/* * 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(®, 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; }
/* * 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)); }
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)); }
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)); }
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), ® }, { 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)); }
/* * 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)); }
/* * 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)); }