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 gettime_old(todr_chip_handle_t tch, struct clock_ymdhms *dt) { u_char h, y; struct clock_ymdhms val; y = FROMBCD(rtc_read(RTC_YR)); if (y >= 69) { dt->dt_year = 1900+y; } else { dt->dt_year = 2000+y; } dt->dt_mon = FROMBCD(rtc_read(RTC_MON)&0x1f); dt->dt_day = FROMBCD(rtc_read(RTC_DATE)&0x3f); dt->dt_wday = FROMBCD(rtc_read(RTC_DAY)&0x7); h = rtc_read(RTC_HRS); if (h & 0x80) { /* time is am/pm format */ dt->dt_hour = FROMBCD(h&0x1f); if (h & 0x20) { /* pm */ if (dt->dt_hour < 12) dt->dt_hour += 12; } else { /* am */ if (dt->dt_hour == 12) dt->dt_hour = 0; } } else { /* time is 24 hour format */ val.dt_hour = FROMBCD(h & 0x3f); } dt->dt_min = FROMBCD(rtc_read(RTC_MIN)&0x7f); dt->dt_sec = FROMBCD(rtc_read(RTC_SEC)&0x7f); return 0; }
static int maxrtc_clock_read(struct maxrtc_softc *sc, struct clock_ymdhms *dt) { u_int8_t bcd[MAX6900_BURST_LEN], cmdbuf[1]; int i; if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "maxrtc_clock_read: failed to acquire I2C bus\n"); return (0); } /* Read each timekeeping register in order. */ for (i = 0; i < MAX6900_BURST_LEN; i++) { cmdbuf[0] = max6900_rtc_offset[i] | MAX6900_CMD_READ; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "maxrtc_clock_read: failed to read rtc " "at 0x%x\n", max6900_rtc_offset[i]); return (0); } } /* Done with I2C */ iic_release_bus(sc->sc_tag, I2C_F_POLL); /* * Convert the MAX6900's register values into something useable */ dt->dt_sec = FROMBCD(bcd[MAX6900_BURST_SECOND] & MAX6900_SECOND_MASK); dt->dt_min = FROMBCD(bcd[MAX6900_BURST_MINUTE] & MAX6900_MINUTE_MASK); if (bcd[MAX6900_BURST_HOUR] & MAX6900_HOUR_12HRS) { dt->dt_hour = FROMBCD(bcd[MAX6900_BURST_HOUR] & MAX6900_HOUR_12MASK); if (bcd[MAX6900_BURST_HOUR] & MAX6900_HOUR_12HRS_PM) dt->dt_hour += 12; } else { dt->dt_hour = FROMBCD(bcd[MAX6900_BURST_HOUR] & MAX6900_HOUR_24MASK); } dt->dt_day = FROMBCD(bcd[MAX6900_BURST_DATE] & MAX6900_DATE_MASK); dt->dt_mon = FROMBCD(bcd[MAX6900_BURST_MONTH] & MAX6900_MONTH_MASK); dt->dt_year = FROMBCD(bcd[MAX6900_BURST_YEAR]); /* century in the burst control slot */ dt->dt_year += (int)FROMBCD(bcd[MAX6900_BURST_CONTROL]) * 100; return (1); }
static int omaprtc_gettime(todr_chip_handle_t tch, struct clock_ymdhms *dt) { struct omaprtc_softc *sc = tch->cookie; int s; /* Wait for RTC_STATUS_REG:BUSY to go low to * guarantee our read is correct. BUSY will * only be high for one 32kHz period (30.5us) * each second, so we'll usually pass right * through. * * Watch RTC_CTRL_REG:STOP_RTC as well so * we don't spin forever if someone disables the RTC. * * Turn interrupts off, because we are only allowed * to read/write the registers for 1/2 of a 32kHz * clock period (= 15us) after detecting that BUSY * is low. */ s = disable_interrupts(I32_bit); while (rtc_is_busy()) { ; } dt->dt_year = FROMBCD(bus_space_read_1(sc->sc_iot, sc->sc_ioh, YEARS_REG)) + BASEYEAR; dt->dt_mon = FROMBCD(bus_space_read_1(sc->sc_iot, sc->sc_ioh, MONTHS_REG)); dt->dt_wday = FROMBCD(bus_space_read_1(sc->sc_iot, sc->sc_ioh, WEEKS_REG) & 0x0f); dt->dt_day = FROMBCD(bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAYS_REG)); dt->dt_sec = FROMBCD(bus_space_read_1(sc->sc_iot, sc->sc_ioh, SECONDS_REG)); dt->dt_hour = FROMBCD(bus_space_read_1(sc->sc_iot, sc->sc_ioh, HOURS_REG)); dt->dt_min = FROMBCD(bus_space_read_1(sc->sc_iot, sc->sc_ioh, MINUTES_REG)); restore_interrupts(s); return 0; }
int tsrtc_match(device_t parent, cfdata_t cf, void *aux) { struct tspld_attach_args *aa = aux; struct tsrtc_softc tsrtc, *tsc; struct mc146818_softc *sc; unsigned int t1, t2; static int found = -1; if (found != -1) return found; tsc = &tsrtc; sc = &tsc->sc_mc; tsc->sc_iot = aa->ta_iot; if (bus_space_map(tsc->sc_iot, TS7XXX_IO8_HWBASE + TS7XXX_RTCIDX, 1, 0, &tsc->sc_idxh)) return (0); if (bus_space_map(tsc->sc_iot, TS7XXX_IO8_HWBASE + TS7XXX_RTCDAT, 1, 0, &tsc->sc_dath)) return (0); /* Read from the seconds counter. */ t1 = FROMBCD(tsrtc_read(sc, MC_SEC)); if (t1 > 59) goto unmap; /* Wait, then look again. */ DELAY(1100000); t2 = FROMBCD(tsrtc_read(sc, MC_SEC)); if (t2 > 59) goto unmap; /* If [1,2) seconds have passed since, call it a clock. */ if ((t1 + 1) % 60 == t2 || (t1 + 2) % 60 == t2) found = 1; unmap: bus_space_unmap(tsc->sc_iot, tsc->sc_idxh, 1); bus_space_unmap(tsc->sc_iot, tsc->sc_dath, 1); return (found); }
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)); }
void sh_rtc_get(void *cookie, time_t base, struct clock_ymdhms *dt) { int retry = 8; /* disable carry interrupt */ _reg_bclr_1(SH_(RCR1), SH_RCR1_CIE); do { uint8_t r = _reg_read_1(SH_(RCR1)); r &= ~SH_RCR1_CF; r |= SH_RCR1_AF; /* don't clear alarm flag */ _reg_write_1(SH_(RCR1), r); if (CPU_IS_SH3) dt->dt_year = FROMBCD(_reg_read_1(SH3_RYRCNT)); else dt->dt_year = FROMBCD(_reg_read_2(SH4_RYRCNT) & 0x00ff); /* read counter */ #define RTCGET(x, y) dt->dt_ ## x = FROMBCD(_reg_read_1(SH_(R ## y ## CNT))) RTCGET(mon, MON); RTCGET(wday, WK); RTCGET(day, DAY); RTCGET(hour, HR); RTCGET(min, MIN); RTCGET(sec, SEC); #undef RTCGET } while ((_reg_read_1(SH_(RCR1)) & SH_RCR1_CF) && --retry > 0); if (retry == 0) { printf("rtc_gettime: couldn't read RTC register.\n"); memset(dt, 0, sizeof(*dt)); return; } dt->dt_year = (dt->dt_year % 100) + 1900; if (dt->dt_year < 1970) dt->dt_year += 100; }
u_long chiptotime(int sec, int min, int hour, int day, int mon, int year) { int days, yr; sec = FROMBCD(sec); min = FROMBCD(min); hour = FROMBCD(hour); day = FROMBCD(day); mon = FROMBCD(mon); year = FROMBCD(year) + YEAR0; if (year < 70) year = 70; /* simple sanity checks */ if (year < 70 || mon < 1 || mon > 12 || day < 1 || day > 31) return (0); days = 0; for (yr = 70; yr < year; yr++) days += LEAPYEAR(yr) ? 366 : 365; days += dayyr[mon - 1] + day - 1; if (LEAPYEAR(yr) && mon > 2) days++; /* now have days since Jan 1, 1970; the rest is easy... */ return days * SECDAY + hour * 3600 + min * 60 + sec; }
static int pcf8563rtc_clock_read(struct pcf8563rtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[PCF8563_NREGS]; uint8_t reg = PCF8563_R_CS1; if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { device_printf(sc->sc_dev, "acquire bus for read failed\n"); return 0; } if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, ®, 1, &bcd[reg], PCF8563_R_YEAR - reg + 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); device_printf(sc->sc_dev, "read failed\n"); return 0; } iic_release_bus(sc->sc_tag, I2C_F_POLL); dt->dt_sec = FROMBCD(bcd[PCF8563_R_SECOND] & PCF8563_M_SECOND); dt->dt_min = FROMBCD(bcd[PCF8563_R_MINUTE] & PCF8563_M_MINUTE); dt->dt_hour = FROMBCD(bcd[PCF8563_R_HOUR] & PCF8563_M_HOUR); dt->dt_day = FROMBCD(bcd[PCF8563_R_DAY] & PCF8563_M_DAY); dt->dt_mon = FROMBCD(bcd[PCF8563_R_MONTH] & PCF8563_M_MONTH); dt->dt_year = FROMBCD(bcd[PCF8563_R_YEAR] & PCF8563_M_YEAR); dt->dt_year += 2000; return 1; }
int ricohrtc_clock_read(struct ricohrtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[RICOHRTC_NRTC_REGS]; uint8_t cmd; iic_acquire_bus(sc->sc_tag, I2C_F_POLL); cmd = (RICOHRTC_SECONDS << 4); if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, &cmd, sizeof cmd, bcd, RICOHRTC_NRTC_REGS, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); printf("%s: ricohrtc_clock_read: failed to read rtc\n", sc->sc_dev.dv_xname); return (0); } iic_release_bus(sc->sc_tag, I2C_F_POLL); /* * Convert the RICOHRTC's register values into something useable */ dt->dt_sec = FROMBCD(bcd[RICOHRTC_SECONDS] & RICOHRTC_SECONDS_MASK); dt->dt_min = FROMBCD(bcd[RICOHRTC_MINUTES] & RICOHRTC_MINUTES_MASK); dt->dt_hour = FROMBCD(bcd[RICOHRTC_HOURS] & RICOHRTC_HOURS_24MASK); dt->dt_day = FROMBCD(bcd[RICOHRTC_DATE] & RICOHRTC_DATE_MASK); dt->dt_mon = FROMBCD(bcd[RICOHRTC_MONTH] & RICOHRTC_MONTH_MASK); dt->dt_year = FROMBCD(bcd[RICOHRTC_YEAR]) + POSIX_BASE_YEAR; return (1); }
static int rs5c372rtc_clock_read(struct rs5c372rtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[RS5C372_NRTC_REGS]; uint8_t cmdbuf[1]; if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "rs5c372rtc_clock_read: failed to acquire I2C bus\n"); return (0); } cmdbuf[0] = (RS5C372_SECONDS << 4); if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, bcd, RS5C372_NRTC_REGS, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "rs5c372rtc_clock_read: failed to read rtc\n"); return (0); } iic_release_bus(sc->sc_tag, I2C_F_POLL); /* * Convert the RS5C372's register values into something useable */ dt->dt_sec = FROMBCD(bcd[RS5C372_SECONDS] & RS5C372_SECONDS_MASK); dt->dt_min = FROMBCD(bcd[RS5C372_MINUTES] & RS5C372_MINUTES_MASK); dt->dt_hour = FROMBCD(bcd[RS5C372_HOURS] & RS5C372_HOURS_24MASK); dt->dt_day = FROMBCD(bcd[RS5C372_DATE] & RS5C372_DATE_MASK); dt->dt_mon = FROMBCD(bcd[RS5C372_MONTH] & RS5C372_MONTH_MASK); dt->dt_year = FROMBCD(bcd[RS5C372_YEAR]) + 2000; return (1); }
static int m41t00_clock_read(struct m41t00_softc *sc, struct clock_ymdhms *dt) { u_int8_t bcd[M41T00_NBYTES], cmdbuf[1]; int i, n; if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "m41t00_clock_read: failed to acquire I2C bus\n"); return 0; } /* Read each timekeeping register in order. */ n = sizeof(m41t00_rtc_offset) / sizeof(m41t00_rtc_offset[0]); for (i = 0; i < n ; i++) { cmdbuf[0] = m41t00_rtc_offset[i]; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "m41t00_clock_read: failed to read rtc " "at 0x%x\n", m41t00_rtc_offset[i]); return 0; } } /* Done with I2C */ iic_release_bus(sc->sc_tag, I2C_F_POLL); /* * Convert the M41T00's register values into something useable */ dt->dt_sec = FROMBCD(bcd[M41T00_SEC] & M41T00_SEC_MASK); dt->dt_min = FROMBCD(bcd[M41T00_MIN] & M41T00_MIN_MASK); dt->dt_hour = FROMBCD(bcd[M41T00_CENHR] & M41T00_HOUR_MASK); dt->dt_day = FROMBCD(bcd[M41T00_DATE] & M41T00_DATE_MASK); dt->dt_wday = FROMBCD(bcd[M41T00_DAY] & M41T00_DAY_MASK); dt->dt_mon = FROMBCD(bcd[M41T00_MONTH] & M41T00_MONTH_MASK); dt->dt_year = FROMBCD(bcd[M41T00_YEAR] & M41T00_YEAR_MASK); /* * Since the m41t00 just stores 00-99, and this is 2003 as I write * this comment, use 2000 as a base year */ dt->dt_year += 2000; return 1; }
static void mcclock_mace_get(struct device *dev, struct clock_ymdhms *dt) { struct mcclock_mace_softc *sc = (struct mcclock_mace_softc *)dev; ds1687_todregs regs; int s; s = splhigh(); DS1687_GETTOD(sc, ®s); splx(s); dt->dt_sec = FROMBCD(regs[DS1687_SOFT_SEC]); dt->dt_min = FROMBCD(regs[DS1687_SOFT_MIN]); dt->dt_hour = FROMBCD(regs[DS1687_SOFT_HOUR]); dt->dt_wday = FROMBCD(regs[DS1687_SOFT_DOW]); dt->dt_day = FROMBCD(regs[DS1687_SOFT_DOM]); dt->dt_mon = FROMBCD(regs[DS1687_SOFT_MONTH]); dt->dt_year = FROMBCD(regs[DS1687_SOFT_YEAR]) + (100 * FROMBCD(regs[DS1687_SOFT_CENTURY])); }
static int mcclock_mace_gettime_ymdhms(todr_chip_handle_t todrch, struct clock_ymdhms *dt) { struct mcclock_mace_softc *sc = todrch->cookie; ds1687_todregs regs; int s; s = splhigh(); DS1687_GETTOD(sc, ®s); splx(s); dt->dt_sec = FROMBCD(regs[DS1687_SOFT_SEC]); dt->dt_min = FROMBCD(regs[DS1687_SOFT_MIN]); dt->dt_hour = FROMBCD(regs[DS1687_SOFT_HOUR]); dt->dt_wday = FROMBCD(regs[DS1687_SOFT_DOW]); dt->dt_day = FROMBCD(regs[DS1687_SOFT_DOM]); dt->dt_mon = FROMBCD(regs[DS1687_SOFT_MONTH]); dt->dt_year = FROMBCD(regs[DS1687_SOFT_YEAR]) + (100 * FROMBCD(regs[DS1687_SOFT_CENTURY])); return 0; }
/* * Get the time of day, based on the clock's value and/or the base value. */ static int dsclock_gettime_ymdhms(struct todr_chip_handle *todrch, struct clock_ymdhms *dt) { struct dsclock_softc *sc = todrch->cookie; ds1286_todregs regs; int s; s = splhigh(); DS1286_GETTOD(sc, ®s) splx(s); dt->dt_sec = FROMBCD(regs[DS1286_SEC]); dt->dt_min = FROMBCD(regs[DS1286_MIN]); if (regs[DS1286_HOUR] & DS1286_HOUR_12MODE) { dt->dt_hour = FROMBCD(regs[DS1286_HOUR] & DS1286_HOUR_12HR_MASK) + ((regs[DS1286_HOUR] & DS1286_HOUR_12HR_PM) ? 12 : 0); /* * In AM/PM mode, hour range is 01-12, so adding in 12 hours * for PM gives us 01-24, whereas we want 00-23, so map hour * 24 to hour 0. */ if (dt->dt_hour == 24) dt->dt_hour = 0; } else { dt->dt_hour = FROMBCD(regs[DS1286_HOUR] & DS1286_HOUR_24HR_MASK); } dt->dt_wday = FROMBCD(regs[DS1286_DOW]); dt->dt_day = FROMBCD(regs[DS1286_DOM]); dt->dt_mon = FROMBCD(regs[DS1286_MONTH] & DS1286_MONTH_MASK); dt->dt_year = FROM_IRIX_YEAR(FROMBCD(regs[DS1286_YEAR])); return 0; }
static int dsrtc_read(todr_chip_handle_t tch, struct clock_ymdhms *dt) { struct dsrtc_softc *sc = tch->cookie; u_char key; key = ds1743_lock(sc, DS_CTL_R); dt->dt_sec = FROMBCD(ds1743_read(sc, DS_SECONDS) & 0x7f); dt->dt_min = FROMBCD(ds1743_read(sc, DS_MINUTES) & 0x7f); dt->dt_hour = FROMBCD(ds1743_read(sc, DS_HOURS) & 0x3f); dt->dt_day = FROMBCD(ds1743_read(sc, DS_DATE) & 0x3f); dt->dt_mon = FROMBCD(ds1743_read(sc, DS_MONTH) & 0x1f); dt->dt_year = FROMBCD(ds1743_read(sc, DS_YEAR)) + FROMBCD(ds1743_read(sc, DS_CENTURY) & ~DS_CTL_RW) * 100; ds1743_unlock(sc, key); return(0); }
/* * Get time-of-day and convert to a `struct timeval' * Return 0 on success; an error number otherwise. */ int mk48txx_gettime_ymdhms(todr_chip_handle_t handle, struct clock_ymdhms *dt) { struct mk48txx_softc *sc; bus_size_t clkoff; int year; uint8_t csr; sc = handle->cookie; clkoff = sc->sc_clkoffset; todr_wenable(handle, 1); /* enable read (stop time) */ csr = (*sc->sc_nvrd)(sc, clkoff + MK48TXX_ICSR); csr |= MK48TXX_CSR_READ; (*sc->sc_nvwr)(sc, clkoff + MK48TXX_ICSR, csr); dt->dt_sec = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_ISEC)); dt->dt_min = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IMIN)); dt->dt_hour = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IHOUR)); dt->dt_day = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IDAY)); dt->dt_wday = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IWDAY)); dt->dt_mon = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IMON)); year = FROMBCD((*sc->sc_nvrd)(sc, clkoff + MK48TXX_IYEAR)); year += sc->sc_year0; if (year < POSIX_BASE_YEAR && (sc->sc_flag & MK48TXX_NO_CENT_ADJUST) == 0) year += 100; dt->dt_year = year; /* time wears on */ csr = (*sc->sc_nvrd)(sc, clkoff + MK48TXX_ICSR); csr &= ~MK48TXX_CSR_READ; (*sc->sc_nvwr)(sc, clkoff + MK48TXX_ICSR, csr); todr_wenable(handle, 0); return 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)); }
/* * 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)); }
static int strtc_clock_read(struct strtc_softc *sc, struct clock_ymdhms *dt) { u_int8_t bcd[M41ST84_REG_DATE_BYTES], cmdbuf[1]; int i; if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { printf("%s: strtc_clock_read: failed to acquire I2C bus\n", sc->sc_dev.dv_xname); return (0); } /* Read each RTC register in order. */ for (i = M41ST84_REG_CSEC; i < M41ST84_REG_DATE_BYTES; i++) { cmdbuf[0] = i; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); printf("%s: strtc_clock_read: failed to read rtc " "at 0x%x\n", sc->sc_dev.dv_xname, i); return (0); } } /* Done with I2C */ iic_release_bus(sc->sc_tag, I2C_F_POLL); /* * Convert the M41ST84's register values into something useable */ dt->dt_sec = FROMBCD(bcd[M41ST84_REG_SEC] & M41ST84_SEC_MASK); dt->dt_min = FROMBCD(bcd[M41ST84_REG_MIN] & M41ST84_MIN_MASK); dt->dt_hour = FROMBCD(bcd[M41ST84_REG_CENHR] & M41ST84_HOUR_MASK); dt->dt_day = FROMBCD(bcd[M41ST84_REG_DATE] & M41ST84_DATE_MASK); dt->dt_mon = FROMBCD(bcd[M41ST84_REG_MONTH] & M41ST84_MONTH_MASK); /* XXX: Should be an MD way to specify EPOCH used by BIOS/Firmware */ dt->dt_year = FROMBCD(bcd[M41ST84_REG_YEAR]) + POSIX_BASE_YEAR; return (1); }
/* * Get time-of-day and convert to a `struct timespec' * Return 0 on success; an error number otherwise. */ int mk48txx_gettime(device_t dev, struct timespec *ts) { struct mk48txx_softc *sc; bus_size_t clkoff; struct clocktime ct; int year; uint8_t csr; sc = device_get_softc(dev); clkoff = sc->sc_clkoffset; mtx_lock(&sc->sc_mtx); /* enable read (stop time) */ csr = (*sc->sc_nvrd)(dev, clkoff + MK48TXX_ICSR); csr |= MK48TXX_CSR_READ; (*sc->sc_nvwr)(dev, clkoff + MK48TXX_ICSR, csr); #define FROMREG(reg, mask) ((*sc->sc_nvrd)(dev, clkoff + (reg)) & (mask)) ct.nsec = 0; ct.sec = FROMBCD(FROMREG(MK48TXX_ISEC, MK48TXX_SEC_MASK)); ct.min = FROMBCD(FROMREG(MK48TXX_IMIN, MK48TXX_MIN_MASK)); ct.hour = FROMBCD(FROMREG(MK48TXX_IHOUR, MK48TXX_HOUR_MASK)); ct.day = FROMBCD(FROMREG(MK48TXX_IDAY, MK48TXX_DAY_MASK)); #if 0 /* Map dow from 1 - 7 to 0 - 6; FROMBCD() isn't necessary here. */ ct.dow = FROMREG(MK48TXX_IWDAY, MK48TXX_WDAY_MASK) - 1; #else /* * Set dow = -1 because some drivers (for example the NetBSD and * OpenBSD mk48txx(4)) don't set it correctly. */ ct.dow = -1; #endif ct.mon = FROMBCD(FROMREG(MK48TXX_IMON, MK48TXX_MON_MASK)); year = FROMBCD(FROMREG(MK48TXX_IYEAR, MK48TXX_YEAR_MASK)); year += sc->sc_year0; if (sc->sc_flag & MK48TXX_NO_CENT_ADJUST) year += (FROMREG(MK48TXX_IWDAY, MK48TXX_WDAY_CB) >> MK48TXX_WDAY_CB_SHIFT) * 100; else if (year < POSIX_BASE_YEAR)
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)); }
static int pcfrtc_clock_read(struct pcfrtc_softc *sc, struct clock_ymdhms *dt, uint8_t *centi) { u_int8_t bcd[10], cmdbuf[1]; int i, err; if ((err = iic_acquire_bus(sc->sc_tag, I2C_F_POLL))) { aprint_error_dev(sc->sc_dev, "pcfrtc_clock_read: failed to acquire I2C bus\n"); return err; } /* Read each timekeeping register in order. */ for (i = 0; i < 10; i++) { cmdbuf[0] = pcf8583_rtc_offset[i]; if ((err = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL))) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "pcfrtc_clock_read: failed to read rtc " "at 0x%x\n", pcf8583_rtc_offset[i]); return err; } } /* Done with I2C */ iic_release_bus(sc->sc_tag, I2C_F_POLL); /* * Convert the PCF8583's register values into something useable */ *centi = FROMBCD(bcd[PCF8583_REG_CENTI]); dt->dt_sec = FROMBCD(bcd[PCF8583_REG_SEC]); dt->dt_min = FROMBCD(bcd[PCF8583_REG_MIN]); dt->dt_hour = FROMBCD(bcd[PCF8583_REG_HOUR] & PCF8583_HOUR_MASK); if (bcd[PCF8583_REG_HOUR] & PCF8583_HOUR_12H) { dt->dt_hour %= 12; /* 12AM -> 0, 12PM -> 12 */ if (bcd[PCF8583_REG_HOUR] & PCF8583_HOUR_PM) dt->dt_hour += 12; } dt->dt_day = FROMBCD(bcd[PCF8583_REG_YEARDATE] & PCF8583_DATE_MASK); dt->dt_mon = FROMBCD(bcd[PCF8583_REG_WKDYMON] & PCF8583_MON_MASK); dt->dt_year = bcd[8] + (bcd[9] * 100); /* Try to notice if the year's rolled over. */ if (bcd[PCF8583_REG_CSR] & PCF8583_CSR_MASK) aprint_error_dev(sc->sc_dev, "cannot check year in mask mode\n"); else { while (dt->dt_year % 4 != (bcd[PCF8583_REG_YEARDATE] & PCF8583_YEAR_MASK) >> PCF8583_YEAR_SHIFT) dt->dt_year++; } return 0; }
int mkclock_isa_match(struct device *parent, struct cfdata *match, void *aux) { struct isa_attach_args *ia = aux; bus_space_handle_t ioh; uint8_t csr, ocsr; unsigned int t1, t2; int found; found = 0; if (ia->ia_nio < 1 || (ia->ia_io[0].ir_addr != ISACF_PORT_DEFAULT && ia->ia_io[0].ir_addr != 0x74)) return (0); if (ia->ia_niomem > 0 && (ia->ia_iomem[0].ir_addr != ISACF_IOMEM_DEFAULT)) return (0); if (ia->ia_nirq > 0 && (ia->ia_irq[0].ir_irq != ISACF_IRQ_DEFAULT)) return (0); if (ia->ia_ndrq > 0 && (ia->ia_drq[0].ir_drq != ISACF_DRQ_DEFAULT)) return (0); if (res->VitalProductData.NvramSize != MK48T18_CLKSZ) return (0); /* * Map I/O space, then try to determine if it's really there. */ if (bus_space_map(ia->ia_iot, 0x74, MKCLOCK_NPORTS, 0, &ioh)) return (0); /* Supposedly no control bits are set after POST; check for this. */ ocsr = mkclock_isa_nvrd(ia->ia_iot, ioh, MK48T18_CLKOFF + MK48TXX_ICSR); if (ocsr != 0) goto unmap; /* Set clock data to read mode, prohibiting updates from clock. */ csr = ocsr | MK48TXX_CSR_READ; mkclock_isa_nvwr(ia->ia_iot, ioh, MK48T18_CLKOFF + MK48TXX_ICSR, csr); /* Compare. */ if (mkclock_isa_nvrd(ia->ia_iot, ioh, MK48T18_CLKOFF + MK48TXX_ICSR) != csr) goto restore; /* Read from the seconds counter. */ t1 = FROMBCD(mkclock_isa_nvrd(ia->ia_iot, ioh, MK48T18_CLKOFF + MK48TXX_ISEC)); if (t1 > 59) goto restore; /* Make it tick again, wait, then look again. */ mkclock_isa_nvwr(ia->ia_iot, ioh, MK48T18_CLKOFF + MK48TXX_ICSR, ocsr); DELAY(1100000); mkclock_isa_nvwr(ia->ia_iot, ioh, MK48T18_CLKOFF + MK48TXX_ICSR, csr); t2 = FROMBCD(mkclock_isa_nvrd(ia->ia_iot, ioh, MK48T18_CLKOFF + MK48TXX_ISEC)); if (t2 > 59) goto restore; #ifdef DEBUG printf("mkclock_isa_match: t1 %02d, t2 %02d\n", t1, t2); #endif /* If [1,2) seconds have passed since, call it a clock. */ if ((t1 + 1) % 60 == t2 || (t1 + 2) % 60 == t2) found = 1; restore: mkclock_isa_nvwr(ia->ia_iot, ioh, MK48T18_CLKOFF + MK48TXX_ICSR, ocsr); unmap: bus_space_unmap(ia->ia_iot, ioh, MKCLOCK_NPORTS); if (found) { ia->ia_nio = 1; ia->ia_io[0].ir_addr = 0x74; ia->ia_io[0].ir_size = MKCLOCK_NPORTS; ia->ia_niomem = 0; ia->ia_nirq = 0; ia->ia_ndrq = 0; } return (found); }
static int strtc_clock_read(struct strtc_softc *sc, struct clock_ymdhms *dt) { u_int8_t bcd[M41ST84_REG_DATE_BYTES], cmdbuf[1]; int i; if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "strtc_clock_read: failed to acquire I2C bus\n"); return (0); } /* * Check for the HT bit -- if set, then clock lost power & stopped * If that happened, then clear the bit so that the clock will have * a chance to run again. */ cmdbuf[0] = M41ST84_REG_AL_HOUR; if (iic_exec(sc->sc_tag, I2C_OP_READ, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "strtc_clock_read: failed to read HT\n"); return (0); } if (cmdbuf[1] & M41ST84_AL_HOUR_HT) { cmdbuf[1] &= ~M41ST84_AL_HOUR_HT; if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "strtc_clock_read: failed to reset HT\n"); return (0); } } /* Read each RTC register in order. */ for (i = M41ST84_REG_CSEC; i < M41ST84_REG_DATE_BYTES; i++) { cmdbuf[0] = i; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "strtc_clock_read: failed to read rtc " "at 0x%x\n", i); return (0); } } /* Done with I2C */ iic_release_bus(sc->sc_tag, I2C_F_POLL); /* * Convert the M41ST84's register values into something useable */ dt->dt_sec = FROMBCD(bcd[M41ST84_REG_SEC] & M41ST84_SEC_MASK); dt->dt_min = FROMBCD(bcd[M41ST84_REG_MIN] & M41ST84_MIN_MASK); dt->dt_hour = FROMBCD(bcd[M41ST84_REG_CENHR] & M41ST84_HOUR_MASK); dt->dt_day = FROMBCD(bcd[M41ST84_REG_DATE] & M41ST84_DATE_MASK); dt->dt_mon = FROMBCD(bcd[M41ST84_REG_MONTH] & M41ST84_MONTH_MASK); /* XXX: Should be an MD way to specify EPOCH used by BIOS/Firmware */ dt->dt_year = FROMBCD(bcd[M41ST84_REG_YEAR]) + POSIX_BASE_YEAR; return (1); }
static int m41t00_clock_write(struct m41t00_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[M41T00_DATE_BYTES], cmdbuf[2]; uint8_t init_seconds, final_seconds; int i; /* * Convert our time representation into something the MAX6900 * can understand. */ bcd[M41T00_SEC] = TOBCD(dt->dt_sec); bcd[M41T00_MIN] = TOBCD(dt->dt_min); bcd[M41T00_CENHR] = TOBCD(dt->dt_hour); bcd[M41T00_DATE] = TOBCD(dt->dt_day); bcd[M41T00_DAY] = TOBCD(dt->dt_wday); bcd[M41T00_MONTH] = TOBCD(dt->dt_mon); bcd[M41T00_YEAR] = TOBCD(dt->dt_year % 100); if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "m41t00_clock_write: failed to acquire I2C bus\n"); return 0; } /* * The MAX6900 RTC manual recommends ensuring "atomicity" of * a non-burst write by: * * - writing SECONDS * - reading back SECONDS, remembering it as "initial seconds" * - write the remaing RTC registers * - read back SECONDS as "final seconds" * - if "initial seconds" == 59, ensure "final seconds" == 59 * - else, ensure "final seconds" is no more than one second * beyond "initial seconds". * * This sounds reasonable for the M41T00, too. */ again: cmdbuf[0] = M41T00_SEC; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[M41T00_SEC], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "m41t00_clock_write: failed to write SECONDS\n"); return 0; } cmdbuf[0] = M41T00_SEC; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &init_seconds, 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "m41t00_clock_write: failed to read " "INITIAL SECONDS\n"); return 0; } init_seconds = FROMBCD(init_seconds & M41T00_SEC_MASK); for (i = 1; i < M41T00_DATE_BYTES; i++) { cmdbuf[0] = m41t00_rtc_offset[i]; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address, cmdbuf, 1, &bcd[i], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "m41t00_clock_write: failed to write rtc " " at 0x%x\n", m41t00_rtc_offset[i]); return 0; } } cmdbuf[0] = M41T00_SEC; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, &final_seconds, 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "m41t00_clock_write: failed to read " "FINAL SECONDS\n"); return 0; } final_seconds = FROMBCD(final_seconds & M41T00_SEC_MASK); if ((init_seconds != final_seconds) && (((init_seconds + 1) % 60) != final_seconds)) { #if 1 printf("%s: m41t00_clock_write: init %d, final %d, try again\n", device_xname(sc->sc_dev), init_seconds, final_seconds); #endif goto again; } iic_release_bus(sc->sc_tag, I2C_F_POLL); return 1; }