satime_t getsecs(void) { volatile uint8_t *mkclock; u_int t; mkclock = RTC_MK48T18_ADDR; t = bcdtobin(*(mkclock + 4)); t += bcdtobin(*(mkclock + 8)) * 60; t += bcdtobin(*(mkclock + 12)) * 60 * 60; return (satime_t)t; }
static int ac100_rtc_gettime(todr_chip_handle_t tch, struct clock_ymdhms *dt) { struct ac100_softc *sc = tch->cookie; uint16_t sec, min, hou, wee, day, mon, yea; iic_acquire_bus(sc->sc_i2c, 0); ac100_read(sc, AC100_RTC_SEC_REG, &sec); ac100_read(sc, AC100_RTC_MIN_REG, &min); ac100_read(sc, AC100_RTC_HOU_REG, &hou); ac100_read(sc, AC100_RTC_WEE_REG, &wee); ac100_read(sc, AC100_RTC_DAY_REG, &day); ac100_read(sc, AC100_RTC_MON_REG, &mon); ac100_read(sc, AC100_RTC_YEA_REG, &yea); iic_release_bus(sc->sc_i2c, 0); dt->dt_year = POSIX_BASE_YEAR + bcdtobin(yea & 0xff); dt->dt_mon = bcdtobin(mon & 0x1f); dt->dt_day = bcdtobin(day & 0x3f); dt->dt_wday = bcdtobin(wee & 0x7); dt->dt_hour = bcdtobin(hou & 0x3f); dt->dt_min = bcdtobin(min & 0x7f); dt->dt_sec = bcdtobin(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 = bcdtobin(bcd[MAX6900_BURST_SECOND] & MAX6900_SECOND_MASK); dt->dt_min = bcdtobin(bcd[MAX6900_BURST_MINUTE] & MAX6900_MINUTE_MASK); if (bcd[MAX6900_BURST_HOUR] & MAX6900_HOUR_12HRS) { dt->dt_hour = bcdtobin(bcd[MAX6900_BURST_HOUR] & MAX6900_HOUR_12MASK); if (bcd[MAX6900_BURST_HOUR] & MAX6900_HOUR_12HRS_PM) dt->dt_hour += 12; } else { dt->dt_hour = bcdtobin(bcd[MAX6900_BURST_HOUR] & MAX6900_HOUR_24MASK); } dt->dt_day = bcdtobin(bcd[MAX6900_BURST_DATE] & MAX6900_DATE_MASK); dt->dt_mon = bcdtobin(bcd[MAX6900_BURST_MONTH] & MAX6900_MONTH_MASK); dt->dt_year = bcdtobin(bcd[MAX6900_BURST_YEAR]); /* century in the burst control slot */ dt->dt_year += (int)bcdtobin(bcd[MAX6900_BURST_CONTROL]) * 100; return (1); }
static int xirtc_gettime(todr_chip_handle_t handle, struct clock_ymdhms *ymdhms) { struct rtc_softc *sc = handle->cookie; uint8_t hour, year, y2k; uint8_t status; time_smbus_init(sc->sc_smbus_chan); ymdhms->dt_day = bcdtobin(READRTC(sc, X1241REG_DT)); ymdhms->dt_mon = bcdtobin(READRTC(sc, X1241REG_MO)); year = READRTC(sc, X1241REG_YR); y2k = READRTC(sc, X1241REG_Y2K); ymdhms->dt_year = bcdtobin(y2k) * 100 + bcdtobin(year); ymdhms->dt_sec = bcdtobin(READRTC(sc, X1241REG_SC)); ymdhms->dt_min = bcdtobin(READRTC(sc, X1241REG_MN)); hour = READRTC(sc, X1241REG_HR); ymdhms->dt_hour = bcdtobin(hour & ~X1241REG_HR_MIL); status = READRTC(sc, X1241REG_SR); if (status & X1241REG_SR_RTCF) { printf("%s: battery has failed, clock setting is not accurate\n", device_xname(sc->sc_dev)); return (EIO); } return (0); }
satime_t getsecs(void) { volatile uint8_t *mcclock_reg, *mcclock_data; u_int sec; mcclock_reg = (void *)MIPS_PHYS_TO_KSEG1(MCCLOCK_BASE + MCCLOCK_REG); mcclock_data = (void *)MIPS_PHYS_TO_KSEG1(MCCLOCK_BASE + MCCLOCK_DATA); *mcclock_reg = MC_SEC; sec = bcdtobin(*mcclock_data); *mcclock_reg = MC_MIN; sec += bcdtobin(*mcclock_data) * 60; *mcclock_reg = MC_HOUR; sec += bcdtobin(*mcclock_data) * 60 * 60; return (satime_t)sec; }
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 = bcdtobin(bus_space_read_1(sc->sc_iot, sc->sc_ioh, YEARS_REG)) + BASEYEAR; dt->dt_mon = bcdtobin(bus_space_read_1(sc->sc_iot, sc->sc_ioh, MONTHS_REG)); dt->dt_wday = bcdtobin(bus_space_read_1(sc->sc_iot, sc->sc_ioh, WEEKS_REG) & 0x0f); dt->dt_day = bcdtobin(bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAYS_REG)); dt->dt_sec = bcdtobin(bus_space_read_1(sc->sc_iot, sc->sc_ioh, SECONDS_REG)); dt->dt_hour = bcdtobin(bus_space_read_1(sc->sc_iot, sc->sc_ioh, HOURS_REG)); dt->dt_min = bcdtobin(bus_space_read_1(sc->sc_iot, sc->sc_ioh, MINUTES_REG)); restore_interrupts(s); return 0; }
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 = bcdtobin(bcd[M41T00_SEC] & M41T00_SEC_MASK); dt->dt_min = bcdtobin(bcd[M41T00_MIN] & M41T00_MIN_MASK); dt->dt_hour = bcdtobin(bcd[M41T00_CENHR] & M41T00_HOUR_MASK); dt->dt_day = bcdtobin(bcd[M41T00_DATE] & M41T00_DATE_MASK); dt->dt_wday = bcdtobin(bcd[M41T00_DAY] & M41T00_DAY_MASK); dt->dt_mon = bcdtobin(bcd[M41T00_MONTH] & M41T00_MONTH_MASK); dt->dt_year = bcdtobin(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 int pcf8563rtc_clock_read(struct pcf8563rtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[PCF8563_NREGS]; uint8_t reg = PCF8563_R_SECOND; const int flags = cold ? I2C_F_POLL : 0; if (iic_acquire_bus(sc->sc_tag, flags)) { 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, flags)) { iic_release_bus(sc->sc_tag, flags); device_printf(sc->sc_dev, "read failed\n"); return 0; } iic_release_bus(sc->sc_tag, flags); if (bcd[PCF8563_R_SECOND] & PCF8563_M_VL) return 0; dt->dt_sec = bcdtobin(bcd[PCF8563_R_SECOND] & PCF8563_M_SECOND); dt->dt_min = bcdtobin(bcd[PCF8563_R_MINUTE] & PCF8563_M_MINUTE); dt->dt_hour = bcdtobin(bcd[PCF8563_R_HOUR] & PCF8563_M_HOUR); dt->dt_day = bcdtobin(bcd[PCF8563_R_DAY] & PCF8563_M_DAY); dt->dt_wday = bcdtobin(bcd[PCF8563_R_WEEKDAY] & PCF8563_M_WEEKDAY); dt->dt_mon = bcdtobin(bcd[PCF8563_R_MONTH] & PCF8563_M_MONTH); dt->dt_year = 1900 + (bcdtobin(bcd[PCF8563_R_YEAR] & PCF8563_M_YEAR) % 100); if ((bcd[PCF8563_R_MONTH] & PCF8563_M_CENTURY) == 0) dt->dt_year += 100; return 1; }
static int strtc_gettime(todr_chip_handle_t handle, struct clock_ymdhms *ymdhms) { struct rtc_softc *sc = handle->cookie; uint8_t hour; time_smbus_init(sc->sc_smbus_chan); ymdhms->dt_sec = bcdtobin(READRTC(sc, M41T81_SEC)); ymdhms->dt_min = bcdtobin(READRTC(sc, M41T81_MIN)); hour = READRTC(sc, M41T81_HOUR & M41T81_HOUR_MASK); ymdhms->dt_hour = bcdtobin(hour & M41T81_HOUR_MASK); ymdhms->dt_day = bcdtobin(READRTC(sc, M41T81_DATE)); ymdhms->dt_mon = bcdtobin(READRTC(sc, M41T81_MON)); ymdhms->dt_year = 1900 + bcdtobin(READRTC(sc, M41T81_YEAR)); if (hour & M41T81_HOUR_CB) ymdhms->dt_year += 100; return (0); }
/* * Return current RTC time. Note that due to waiting for the update cycle to * complete, this call may take some time. */ static uint64_t rtc_gettimeofday(void) { struct bmk_clock_ymdhms dt; interrupts_disable(); /* * If RTC_UIP is down, we have at least 244us to obtain a * consistent reading before an update can occur. */ while (rtc_read(RTC_STATUS_A) & RTC_UIP) continue; dt.dt_sec = bcdtobin(rtc_read(RTC_SEC)); dt.dt_min = bcdtobin(rtc_read(RTC_MIN)); dt.dt_hour = bcdtobin(rtc_read(RTC_HOUR)); dt.dt_day = bcdtobin(rtc_read(RTC_DAY)); dt.dt_mon = bcdtobin(rtc_read(RTC_MONTH)); dt.dt_year = bcdtobin(rtc_read(RTC_YEAR)) + 2000; interrupts_enable(); return clock_ymdhms_to_secs(&dt) * NSEC_PER_SEC; }
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] = bintobcd(dt->dt_sec); bcd[M41T00_MIN] = bintobcd(dt->dt_min); bcd[M41T00_CENHR] = bintobcd(dt->dt_hour); bcd[M41T00_DATE] = bintobcd(dt->dt_day); bcd[M41T00_DAY] = bintobcd(dt->dt_wday); bcd[M41T00_MONTH] = bintobcd(dt->dt_mon); bcd[M41T00_YEAR] = bintobcd(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 = bcdtobin(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 = bcdtobin(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; }