static int xirtc_settime(todr_chip_handle_t handle, struct clock_ymdhms *ymdhms) { struct rtc_softc *sc = handle->cookie; uint8_t year, y2k; time_smbus_init(sc->sc_smbus_chan); /* unlock writes to the CCR */ WRITERTC(sc, X1241REG_SR, X1241REG_SR_WEL); WRITERTC(sc, X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); /* set the time */ WRITERTC(sc, X1241REG_HR, bintobcd(ymdhms->dt_hour) | X1241REG_HR_MIL); WRITERTC(sc, X1241REG_MN, bintobcd(ymdhms->dt_min)); WRITERTC(sc, X1241REG_SC, bintobcd(ymdhms->dt_sec)); /* set the date */ y2k = (ymdhms->dt_year >= 2000) ? 0x20 : 0x19; year = ymdhms->dt_year % 100; WRITERTC(sc, X1241REG_MO, bintobcd(ymdhms->dt_mon)); WRITERTC(sc, X1241REG_DT, bintobcd(ymdhms->dt_day)); WRITERTC(sc, X1241REG_YR, bintobcd(year)); WRITERTC(sc, X1241REG_Y2K, bintobcd(y2k)); /* lock writes again */ WRITERTC(sc, X1241REG_SR, 0); return (0); }
static int pcf8563rtc_clock_write(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; bcd[PCF8563_R_SECOND] = bintobcd(dt->dt_sec); bcd[PCF8563_R_MINUTE] = bintobcd(dt->dt_min); bcd[PCF8563_R_HOUR] = bintobcd(dt->dt_hour); bcd[PCF8563_R_DAY] = bintobcd(dt->dt_day); bcd[PCF8563_R_WEEKDAY] = bintobcd(dt->dt_wday); bcd[PCF8563_R_MONTH] = bintobcd(dt->dt_mon); bcd[PCF8563_R_YEAR] = bintobcd(dt->dt_year % 100); if (dt->dt_year < 2000) bcd[PCF8563_R_MONTH] |= PCF8563_M_CENTURY; if (iic_acquire_bus(sc->sc_tag, flags)) { device_printf(sc->sc_dev, "acquire bus for write failed\n"); return 0; } if (iic_exec(sc->sc_tag, I2C_OP_WRITE_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, "write failed\n"); return 0; } iic_release_bus(sc->sc_tag, flags); return 1; }
static int omaprtc_settime(todr_chip_handle_t tch, struct clock_ymdhms *dt) { struct omaprtc_softc *sc = tch->cookie; int s; s = disable_interrupts(I32_bit); while (rtc_is_busy()) { ; } /* It's ok to write these without stopping the * RTC, because the BUSY mechanism lets us guarantee * that we're not in the middle of, e.g., rolling * seconds into minutes. */ bus_space_write_1(sc->sc_iot, sc->sc_ioh, YEARS_REG, bintobcd(dt->dt_year - BASEYEAR)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, MONTHS_REG, bintobcd(dt->dt_mon)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, WEEKS_REG, bintobcd(dt->dt_wday & 0x0f)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAYS_REG, bintobcd(dt->dt_day)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, SECONDS_REG, bintobcd(dt->dt_sec)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, HOURS_REG, bintobcd(dt->dt_hour)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, MINUTES_REG, bintobcd(dt->dt_min)); restore_interrupts(s); return 0; }
static int ac100_rtc_settime(todr_chip_handle_t tch, struct clock_ymdhms *dt) { struct ac100_softc *sc = tch->cookie; iic_acquire_bus(sc->sc_i2c, 0); ac100_write(sc, AC100_RTC_SEC_REG, bintobcd(dt->dt_sec) & 0x7f); ac100_write(sc, AC100_RTC_MIN_REG, bintobcd(dt->dt_min) & 0x7f); ac100_write(sc, AC100_RTC_HOU_REG, bintobcd(dt->dt_hour) & 0x3f); ac100_write(sc, AC100_RTC_WEE_REG, bintobcd(dt->dt_wday) & 0x7); ac100_write(sc, AC100_RTC_DAY_REG, bintobcd(dt->dt_day) & 0x3f); ac100_write(sc, AC100_RTC_MON_REG, bintobcd(dt->dt_mon) & 0x1f); ac100_write(sc, AC100_RTC_YEA_REG, bintobcd(dt->dt_year - POSIX_BASE_YEAR) & 0xff); ac100_write(sc, AC100_RTC_UPD_TRIG_REG, AC100_RTC_UPD_TRIG_WRITE); iic_release_bus(sc->sc_i2c, 0); return 0; }
static int strtc_settime(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); hour = bintobcd(ymdhms->dt_hour); if (ymdhms->dt_year >= 2000) /* Should be always true! */ hour |= M41T81_HOUR_CB | M41T81_HOUR_CEB; /* set the time */ WRITERTC(sc, M41T81_SEC, bintobcd(ymdhms->dt_sec)); WRITERTC(sc, M41T81_MIN, bintobcd(ymdhms->dt_min)); WRITERTC(sc, M41T81_HOUR, hour); /* set the date */ WRITERTC(sc, M41T81_DATE, bintobcd(ymdhms->dt_day)); WRITERTC(sc, M41T81_MON, bintobcd(ymdhms->dt_mon)); WRITERTC(sc, M41T81_YEAR, bintobcd(ymdhms->dt_year % 100)); return (0); }
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; }
static int maxrtc_clock_write(struct maxrtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[MAX6900_BURST_LEN], cmdbuf[2]; uint8_t init_seconds, final_seconds; int i; /* * Convert our time representation into something the MAX6900 * can understand. */ bcd[MAX6900_BURST_SECOND] = bintobcd(dt->dt_sec); bcd[MAX6900_BURST_MINUTE] = bintobcd(dt->dt_min); bcd[MAX6900_BURST_HOUR] = bintobcd(dt->dt_hour) & MAX6900_HOUR_24MASK; bcd[MAX6900_BURST_DATE] = bintobcd(dt->dt_day); bcd[MAX6900_BURST_WDAY] = bintobcd(dt->dt_wday); bcd[MAX6900_BURST_MONTH] = bintobcd(dt->dt_mon); bcd[MAX6900_BURST_YEAR] = bintobcd(dt->dt_year % 100); /* century in control slot */ bcd[MAX6900_BURST_CONTROL] = bintobcd(dt->dt_year / 100); if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "maxrtc_clock_write: failed to acquire I2C bus\n"); return (0); } /* Start by clearing the control register's write-protect bit. */ cmdbuf[0] = MAX6900_REG_CONTROL | MAX6900_CMD_WRITE; cmdbuf[1] = 0; 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, "maxrtc_clock_write: failed to clear WP bit\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". */ again: cmdbuf[0] = MAX6900_REG_SECOND | MAX6900_CMD_WRITE; if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, cmdbuf, 1, &bcd[MAX6900_BURST_SECOND], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, "maxrtc_clock_write: failed to write SECONDS\n"); return (0); } cmdbuf[0] = MAX6900_REG_SECOND | MAX6900_CMD_READ; if (iic_exec(sc->sc_tag, I2C_OP_READ, 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, "maxrtc_clock_write: failed to read " "INITIAL SECONDS\n"); return (0); } for (i = 1; i < MAX6900_BURST_LEN; i++) { cmdbuf[0] = max6900_rtc_offset[i] | MAX6900_CMD_WRITE; if (iic_exec(sc->sc_tag, i != MAX6900_BURST_LEN - 1 ? I2C_OP_WRITE : 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, "maxrtc_clock_write: failed to write rtc " " at 0x%x\n", max6900_rtc_offset[i]); return (0); } } cmdbuf[0] = MAX6900_REG_SECOND | MAX6900_CMD_READ; 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, "maxrtc_clock_write: failed to read " "FINAL SECONDS\n"); return (0); } if ((init_seconds == 59 && final_seconds != 59) || (init_seconds != 59 && final_seconds != init_seconds + 1)) { #if 1 printf("%s: maxrtc_clock_write: init %d, final %d, try again\n", device_xname(sc->sc_dev), init_seconds, final_seconds); #endif goto again; } /* Finish by setting the control register's write-protect bit. */ cmdbuf[0] = MAX6900_REG_CONTROL | MAX6900_CMD_WRITE; cmdbuf[1] = MAX6900_CONTROL_WP; if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 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, "maxrtc_clock_write: failed to set WP bit\n"); return (0); } iic_release_bus(sc->sc_tag, I2C_F_POLL); return (1); }