void sh_rtc_set(void *cookie, struct clock_ymdhms *dt) { uint8_t r; /* stop clock */ r = _reg_read_1(SH_(RCR2)); r |= SH_RCR2_RESET; r &= ~SH_RCR2_START; _reg_write_1(SH_(RCR2), r); /* set time */ if (CPU_IS_SH3) _reg_write_1(SH3_RYRCNT, TOBCD(dt->dt_year % 100)); else _reg_write_2(SH4_RYRCNT, TOBCD(dt->dt_year % 100)); #define RTCSET(x, y) _reg_write_1(SH_(R ## x ## CNT), TOBCD(dt->dt_ ## y)) RTCSET(MON, mon); RTCSET(WK, wday); RTCSET(DAY, day); RTCSET(HR, hour); RTCSET(MIN, min); RTCSET(SEC, sec); #undef RTCSET /* start clock */ _reg_write_1(SH_(RCR2), r | SH_RCR2_START); }
static int pcfrtc_clock_write(struct pcfrtc_softc *sc, struct clock_ymdhms *dt, uint8_t centi) { uint8_t bcd[10], cmdbuf[2]; int i, err; /* * Convert our time representation into something the PCF8583 * can understand. */ bcd[PCF8583_REG_CENTI] = centi; bcd[PCF8583_REG_SEC] = TOBCD(dt->dt_sec); bcd[PCF8583_REG_MIN] = TOBCD(dt->dt_min); bcd[PCF8583_REG_HOUR] = TOBCD(dt->dt_hour) & PCF8583_HOUR_MASK; bcd[PCF8583_REG_YEARDATE] = TOBCD(dt->dt_day) | ((dt->dt_year % 4) << PCF8583_YEAR_SHIFT); bcd[PCF8583_REG_WKDYMON] = TOBCD(dt->dt_mon) | ((dt->dt_wday % 4) << PCF8583_WKDY_SHIFT); bcd[8] = dt->dt_year % 100; bcd[9] = dt->dt_year / 100; if ((err = iic_acquire_bus(sc->sc_tag, I2C_F_POLL))) { aprint_error_dev(sc->sc_dev, "pcfrtc_clock_write: failed to acquire I2C bus\n"); return err; } for (i = 1; i < 10; i++) { cmdbuf[0] = pcf8583_rtc_offset[i]; if ((err = iic_exec(sc->sc_tag, i != 9 ? 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, "pcfrtc_clock_write: failed to write rtc " " at 0x%x\n", pcf8583_rtc_offset[i]); return err; } } iic_release_bus(sc->sc_tag, I2C_F_POLL); return 0; }
static int mv_rtc_settime(device_t dev, struct timespec *ts) { struct clocktime ct; struct mv_rtc_softc *sc; uint32_t val; sc = device_get_softc(dev); /* Resolution: 1 sec */ if (ts->tv_nsec >= 500000000) ts->tv_sec++; ts->tv_nsec = 0; clock_ts_to_ct(ts, &ct); val = TOBCD(ct.sec) | (TOBCD(ct.min) << 8) | (TOBCD(ct.hour) << 16) | (TOBCD( ct.dow + 1) << 24); mv_rtc_reg_write(sc, MV_RTC_TIME_REG, val); val = TOBCD(ct.day) | (TOBCD(ct.mon) << 8) | (TOBCD(ct.year - YEAR_BASE) << 16); mv_rtc_reg_write(sc, MV_RTC_DATE_REG, val); return (0); }
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, TOBCD(dt->dt_year - BASEYEAR)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, MONTHS_REG, TOBCD(dt->dt_mon)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, WEEKS_REG, TOBCD(dt->dt_wday & 0x0f)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAYS_REG, TOBCD(dt->dt_day)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, SECONDS_REG, TOBCD(dt->dt_sec)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, HOURS_REG, TOBCD(dt->dt_hour)); bus_space_write_1(sc->sc_iot, sc->sc_ioh, MINUTES_REG, TOBCD(dt->dt_min)); restore_interrupts(s); 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; bcd[PCF8563_R_SECOND] = TOBCD(dt->dt_sec); bcd[PCF8563_R_MINUTE] = TOBCD(dt->dt_min); bcd[PCF8563_R_HOUR] = TOBCD(dt->dt_hour); bcd[PCF8563_R_DAY] = TOBCD(dt->dt_day); bcd[PCF8563_R_WEEKDAY] = TOBCD(dt->dt_wday); bcd[PCF8563_R_MONTH] = TOBCD(dt->dt_mon); bcd[PCF8563_R_YEAR] = TOBCD(dt->dt_year % 100); if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { 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, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); device_printf(sc->sc_dev, "write failed\n"); return 0; } iic_release_bus(sc->sc_tag, I2C_F_POLL); return 1; }
int ricohrtc_clock_write(struct ricohrtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[RICOHRTC_NRTC_REGS]; uint8_t cmd; /* * Convert our time representation into something the RICOHRTC * can understand. */ bcd[RICOHRTC_SECONDS] = TOBCD(dt->dt_sec); bcd[RICOHRTC_MINUTES] = TOBCD(dt->dt_min); bcd[RICOHRTC_HOURS] = TOBCD(dt->dt_hour); bcd[RICOHRTC_DATE] = TOBCD(dt->dt_day); bcd[RICOHRTC_DAY] = TOBCD(dt->dt_wday); bcd[RICOHRTC_MONTH] = TOBCD(dt->dt_mon); bcd[RICOHRTC_YEAR] = TOBCD(dt->dt_year - POSIX_BASE_YEAR); iic_acquire_bus(sc->sc_tag, I2C_F_POLL); cmd = (RICOHRTC_SECONDS << 4); if (iic_exec(sc->sc_tag, I2C_OP_WRITE_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_write: failed to write rtc\n", sc->sc_dev.dv_xname); return (0); } iic_release_bus(sc->sc_tag, I2C_F_POLL); return (1); }
/* * Reset the TODR based on the time value. */ static int dsclock_settime_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); regs[DS1286_SUBSEC] = 0; regs[DS1286_SEC] = TOBCD(dt->dt_sec); regs[DS1286_MIN] = TOBCD(dt->dt_min); regs[DS1286_HOUR] = TOBCD(dt->dt_hour) & DS1286_HOUR_24HR_MASK; regs[DS1286_DOW] = TOBCD(dt->dt_wday); regs[DS1286_DOM] = TOBCD(dt->dt_day); /* Leave wave-generator bits as set originally */ regs[DS1286_MONTH] &= ~DS1286_MONTH_MASK; regs[DS1286_MONTH] |= TOBCD(dt->dt_mon) & DS1286_MONTH_MASK; regs[DS1286_YEAR] = TOBCD(TO_IRIX_YEAR(dt->dt_year)); s = splhigh(); DS1286_PUTTOD(sc, ®s); splx(s); return 0; }
static int rs5c313_todr_settime_ymdhms(todr_chip_handle_t todr, struct clock_ymdhms *dt) { struct rs5c313_softc *sc = todr->cookie; int retry; int t; int s; s = splhigh(); rtc_begin(sc); for (retry = 10; retry > 0; --retry) { rtc_ce(sc, 1); rs5c313_write_reg(sc, RS5C313_CTRL, sc->sc_ctrl[0]); if ((rs5c313_read_reg(sc, RS5C313_CTRL) & CTRL_BSY) == 0) break; rtc_ce(sc, 0); delay(1); } if (retry == 0) { splx(s); return EIO; } #define RTCSET(x, y) \ do { \ t = TOBCD(dt->dt_ ## y) & 0xff; \ rs5c313_write_reg(sc, RS5C313_ ## x ## 1, t & 0x0f); \ rs5c313_write_reg(sc, RS5C313_ ## x ## 10, (t >> 4) & 0x0f); \ } while (/* CONSTCOND */0) RTCSET(SEC, sec); RTCSET(MIN, min); RTCSET(HOUR, hour); RTCSET(DAY, day); RTCSET(MON, mon); #undef RTCSET t = dt->dt_year % 100; t = TOBCD(t); rs5c313_write_reg(sc, RS5C313_YEAR1, t & 0x0f); rs5c313_write_reg(sc, RS5C313_YEAR10, (t >> 4) & 0x0f); rs5c313_write_reg(sc, RS5C313_WDAY, dt->dt_wday); rtc_ce(sc, 0); splx(s); sc->sc_valid = 1; return 0; }
static int ds1307_settime(device_t dev, struct timespec *ts) { int error; struct clocktime ct; struct ds1307_softc *sc; uint8_t data[8]; sc = device_get_softc(dev); /* Accuracy is only one second. */ if (ts->tv_nsec >= 500000000) ts->tv_sec++; ts->tv_nsec = 0; clock_ts_to_ct(ts, &ct); memset(data, 0, sizeof(data)); data[0] = DS1307_SECS; data[DS1307_SECS + 1] = TOBCD(ct.sec); data[DS1307_MINS + 1] = TOBCD(ct.min); data[DS1307_HOUR + 1] = TOBCD(ct.hour); data[DS1307_DATE + 1] = TOBCD(ct.day); data[DS1307_WEEKDAY + 1] = ct.dow; data[DS1307_MONTH + 1] = TOBCD(ct.mon); data[DS1307_YEAR + 1] = TOBCD(ct.year % 100); /* Write the time back to RTC. */ error = ds1307_write(dev, sc->sc_addr, data, sizeof(data)); if (error != 0) device_printf(dev, "cannot write to RTC.\n"); return (error); }
static int pcf2123_rtc_settime(device_t dev, struct timespec *ts) { struct clocktime ct; struct pcf2123_rtc_softc *sc; struct spi_command cmd; unsigned char rxTimedate[8]; unsigned char txTimedate[8]; int err; sc = device_get_softc(dev); /* Resolution: 1 sec */ if (ts->tv_nsec >= 500000000) ts->tv_sec++; ts->tv_nsec = 0; clock_ts_to_ct(ts, &ct); memset(&cmd, 0, sizeof(cmd)); memset(rxTimedate, 0, sizeof(rxTimedate)); memset(txTimedate, 0, sizeof(txTimedate)); /* Start reading from seconds */ cmd.rx_cmd = rxTimedate; cmd.tx_cmd = txTimedate; cmd.rx_cmd_sz = sizeof(rxTimedate); cmd.tx_cmd_sz = sizeof(txTimedate); /* * Counter is stopped when access to time registers is in progress * So there is no need to stop/start counter */ txTimedate[0] = PCF2123_WRITE(PCF2123_REG_SECONDS); txTimedate[1] = TOBCD(ct.sec); txTimedate[2] = TOBCD(ct.min); txTimedate[3] = TOBCD(ct.hour); txTimedate[4] = TOBCD(ct.day); txTimedate[5] = TOBCD(ct.dow); txTimedate[6] = TOBCD(ct.mon); txTimedate[7] = TOBCD(ct.year - YEAR_BASE); err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd); DELAY(PCF2123_DELAY); return (err); }
/* * Set the time of day clock based on the value of the struct timespec arg. * Return 0 on success, an error number otherwise. */ int ds1553_settime(device_t dev, struct timespec *ts) { struct clocktime ct; struct ds1553_softc *sc; uint8_t control; sc = device_get_softc(dev); bzero(&ct, sizeof(struct clocktime)); /* Accuracy is only one second. */ if (ts->tv_nsec >= 500000000) ts->tv_sec++; ts->tv_nsec = 0; clock_ts_to_ct(ts, &ct); ct.year -= sc->year_offset; mtx_lock_spin(&sc->sc_mtx); /* Halt updates to external registers */ control = (*sc->sc_read)(dev, DS1553_OFF_CONTROL) | DS1553_BIT_WRITE; (*sc->sc_write)(dev, DS1553_OFF_CONTROL, control); (*sc->sc_write)(dev, DS1553_OFF_SECONDS, TOBCD(ct.sec) & DS1553_MASK_SECONDS); (*sc->sc_write)(dev, DS1553_OFF_MINUTES, TOBCD(ct.min) & DS1553_MASK_MINUTES); (*sc->sc_write)(dev, DS1553_OFF_HOURS, TOBCD(ct.hour) & DS1553_MASK_HOUR); (*sc->sc_write)(dev, DS1553_OFF_DAYOFWEEK, TOBCD(ct.dow + 1) & DS1553_MASK_DAYOFWEEK); (*sc->sc_write)(dev, DS1553_OFF_DATE, TOBCD(ct.day) & DS1553_MASK_DATE); (*sc->sc_write)(dev, DS1553_OFF_MONTH, TOBCD(ct.mon) & DS1553_MASK_MONTH); (*sc->sc_write)(dev, DS1553_OFF_YEAR, TOBCD(ct.year)); /* Resume updates to external registers */ control &= ~DS1553_BIT_WRITE; (*sc->sc_write)(dev, DS1553_OFF_CONTROL, control); mtx_unlock_spin(&sc->sc_mtx); return (0); }
static void mcclock_mace_set(struct device *dev, struct clock_ymdhms *dt) { struct mcclock_mace_softc *sc = (struct mcclock_mace_softc *)dev; ds1687_todregs regs; int s; memset(®s, 0, sizeof(regs)); regs[DS1687_SOFT_SEC] = TOBCD(dt->dt_sec); regs[DS1687_SOFT_MIN] = TOBCD(dt->dt_min); regs[DS1687_SOFT_HOUR] = TOBCD(dt->dt_hour); regs[DS1687_SOFT_DOW] = TOBCD(dt->dt_wday); regs[DS1687_SOFT_DOM] = TOBCD(dt->dt_day); regs[DS1687_SOFT_MONTH] = TOBCD(dt->dt_mon); regs[DS1687_SOFT_YEAR] = TOBCD(dt->dt_year % 100); regs[DS1687_SOFT_CENTURY] = TOBCD(dt->dt_year / 100); s = splhigh(); DS1687_PUTTOD(sc, ®s); splx(s); }
static int mcclock_mace_settime_ymdhms(todr_chip_handle_t todrch, struct clock_ymdhms *dt) { struct mcclock_mace_softc *sc = todrch->cookie; ds1687_todregs regs; int s; memset(®s, 0, sizeof(regs)); regs[DS1687_SOFT_SEC] = TOBCD(dt->dt_sec); regs[DS1687_SOFT_MIN] = TOBCD(dt->dt_min); regs[DS1687_SOFT_HOUR] = TOBCD(dt->dt_hour); regs[DS1687_SOFT_DOW] = TOBCD(dt->dt_wday); regs[DS1687_SOFT_DOM] = TOBCD(dt->dt_day); regs[DS1687_SOFT_MONTH] = TOBCD(dt->dt_mon); regs[DS1687_SOFT_YEAR] = TOBCD(dt->dt_year % 100); regs[DS1687_SOFT_CENTURY] = TOBCD(dt->dt_year / 100); s = splhigh(); DS1687_PUTTOD(sc, ®s); splx(s); return 0; }
static int dsrtc_write(todr_chip_handle_t tch, struct clock_ymdhms *dt) { struct dsrtc_softc *sc = tch->cookie; u_char key; key = ds1743_lock(sc, DS_CTL_W); ds1743_write(sc, DS_SECONDS, TOBCD(dt->dt_sec) & 0x7f); ds1743_write(sc, DS_MINUTES, TOBCD(dt->dt_min) & 0x7f); ds1743_write(sc, DS_HOURS, TOBCD(dt->dt_hour) & 0x3f); ds1743_write(sc, DS_DATE, TOBCD(dt->dt_day) & 0x3f); ds1743_write(sc, DS_MONTH, TOBCD(dt->dt_mon) & 0x1f); ds1743_write(sc, DS_YEAR, TOBCD(dt->dt_year % 100)); ds1743_write(sc, DS_CENTURY, ((ds1743_read(sc, DS_CENTURY) & DS_CTL_RW) | TOBCD(dt->dt_year / 100))); ds1743_unlock(sc, key); return(0); }
/* * Set the time-of-day clock based on the value of the `struct timeval' arg. * Return 0 on success; an error number otherwise. */ int mk48txx_settime_ymdhms(todr_chip_handle_t handle, struct clock_ymdhms *dt) { struct mk48txx_softc *sc; bus_size_t clkoff; uint8_t csr; int year; sc = handle->cookie; clkoff = sc->sc_clkoffset; year = dt->dt_year - sc->sc_year0; if (year > 99 && (sc->sc_flag & MK48TXX_NO_CENT_ADJUST) == 0) year -= 100; todr_wenable(handle, 1); /* enable write */ csr = (*sc->sc_nvrd)(sc, clkoff + MK48TXX_ICSR); csr |= MK48TXX_CSR_WRITE; (*sc->sc_nvwr)(sc, clkoff + MK48TXX_ICSR, csr); (*sc->sc_nvwr)(sc, clkoff + MK48TXX_ISEC, TOBCD(dt->dt_sec)); (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IMIN, TOBCD(dt->dt_min)); (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IHOUR, TOBCD(dt->dt_hour)); (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IWDAY, TOBCD(dt->dt_wday)); (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IDAY, TOBCD(dt->dt_day)); (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IMON, TOBCD(dt->dt_mon)); (*sc->sc_nvwr)(sc, clkoff + MK48TXX_IYEAR, TOBCD(year)); /* load them up */ csr = (*sc->sc_nvrd)(sc, clkoff + MK48TXX_ICSR); csr &= ~MK48TXX_CSR_WRITE; (*sc->sc_nvwr)(sc, clkoff + MK48TXX_ICSR, csr); todr_wenable(handle, 0); return 0; }
static int rs5c372rtc_clock_write(struct rs5c372rtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[RS5C372_NRTC_REGS]; uint8_t cmdbuf[1]; /* * Convert our time representation into something the RS5C372 * can understand. */ bcd[RS5C372_SECONDS] = TOBCD(dt->dt_sec); bcd[RS5C372_MINUTES] = TOBCD(dt->dt_min); bcd[RS5C372_HOURS] = TOBCD(dt->dt_hour); bcd[RS5C372_DATE] = TOBCD(dt->dt_day); bcd[RS5C372_DAY] = TOBCD(dt->dt_wday); bcd[RS5C372_MONTH] = TOBCD(dt->dt_mon); bcd[RS5C372_YEAR] = TOBCD(dt->dt_year % 100); if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "rs5c372rtc_clock_write: failed to " "acquire I2C bus\n"); return (0); } cmdbuf[0] = (RS5C372_SECONDS << 4); if (iic_exec(sc->sc_tag, I2C_OP_WRITE_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_write: failed to write rtc\n"); return (0); } iic_release_bus(sc->sc_tag, I2C_F_POLL); return (1); }
static int s3c2xx0_rtc_settime(device_t dev, struct timespec *ts) { struct s3c2xx0_rtc_softc *sc; struct clocktime ct; sc = device_get_softc(dev); /* Resolution: 1 sec */ if (ts->tv_nsec >= 500000000) ts->tv_sec++; ts->tv_nsec = 0; clock_ts_to_ct(ts, &ct); bus_write_1(sc->mem_res, RTC_BCDSEC, TOBCD(ct.sec)); bus_write_1(sc->mem_res, RTC_BCDMIN, TOBCD(ct.min)); bus_write_1(sc->mem_res, RTC_BCDHOUR, TOBCD(ct.hour)); bus_write_1(sc->mem_res, RTC_BCDDATE, TOBCD(ct.day)); bus_write_1(sc->mem_res, RTC_BCDDAY, TOBCD(ct.dow)); bus_write_1(sc->mem_res, RTC_BCDMON, TOBCD(ct.mon)); bus_write_1(sc->mem_res, RTC_BCDYEAR, TOBCD(ct.year - YEAR_BASE)); return (0); }
static int pcf8563_settime(device_t dev, struct timespec *ts) { struct clocktime ct; uint8_t val[PCF8563_NCLOCKREGS]; struct iic_msg msgs[] = { { 0, IIC_M_WR, PCF8563_NCLOCKREGS - 1, &val[PCF8563_R_CS2] } }; struct pcf8563_softc *sc; int error; sc = device_get_softc(dev); val[PCF8563_R_CS2] = PCF8563_R_SECOND; /* abuse */ /* Accuracy is only one second. */ if (ts->tv_nsec >= 500000000) ts->tv_sec++; ts->tv_nsec = 0; clock_ts_to_ct(ts, &ct); val[PCF8563_R_SECOND] = TOBCD(ct.sec); val[PCF8563_R_MINUTE] = TOBCD(ct.min); val[PCF8563_R_HOUR] = TOBCD(ct.hour); val[PCF8563_R_DAY] = TOBCD(ct.day); val[PCF8563_R_WEEKDAY] = ct.dow; val[PCF8563_R_MONTH] = TOBCD(ct.mon); val[PCF8563_R_YEAR] = TOBCD(ct.year % 100); if ((sc->sc_flags & PCF8563_CPOL) != 0) { if (ct.year >= 100 + sc->sc_year0) val[PCF8563_R_MONTH] |= PCF8563_R_MONTH_C; } else if (ct.year < 100 + sc->sc_year0) val[PCF8563_R_MONTH] |= PCF8563_R_MONTH_C; msgs[0].slave = sc->sc_addr; error = iicbus_transfer(dev, msgs, nitems(msgs)); if (error != 0) device_printf(dev, "%s: cannot write RTC\n", __func__); return (error); }
int __ll_settime(struct tm *tm2) { DPMI_REGS regs; int v = tm2->tm_year; if (v > 170) v -= 100; regs.b.dh = TOBCD(tm2->tm_sec) ; regs.b.cl = TOBCD(tm2->tm_min) ; regs.b.ch = TOBCD(tm2->tm_hour) ; regs.b.ah = 3; __realint(0x1a,®s); regs.b.dl = TOBCD(tm2->tm_mday); regs.b.dh = TOBCD(tm2->tm_mon+1); regs.b.cl = TOBCD(v); if (tm2->tm_year < 71) tm2->tm_year += 100; regs.b.ah = 5; __realint(0x1a,®s); return 0; }
static int strtc_clock_write(struct strtc_softc *sc, struct clock_ymdhms *dt) { uint8_t bcd[M41ST84_REG_DATE_BYTES], cmdbuf[2]; int i; /* * Convert our time representation into something the M41ST84 * can understand. */ bcd[M41ST84_REG_CSEC] = TOBCD(0); /* must always write as 0 */ bcd[M41ST84_REG_SEC] = TOBCD(dt->dt_sec); bcd[M41ST84_REG_MIN] = TOBCD(dt->dt_min); bcd[M41ST84_REG_CENHR] = TOBCD(dt->dt_hour); bcd[M41ST84_REG_DATE] = TOBCD(dt->dt_day); bcd[M41ST84_REG_DAY] = TOBCD(dt->dt_wday); bcd[M41ST84_REG_MONTH] = TOBCD(dt->dt_mon); bcd[M41ST84_REG_YEAR] = TOBCD((dt->dt_year - POSIX_BASE_YEAR) % 100); if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, "strtc_clock_write: failed to acquire I2C bus\n"); return (0); } /* Stop the clock */ cmdbuf[0] = M41ST84_REG_SEC; cmdbuf[1] = M41ST84_SEC_ST; 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_write: failed to Hold Clock\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_write: 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_write: failed to reset HT\n"); return (0); } } /* * Write registers in reverse order. The last write (to the Seconds * register) will undo the Clock Hold, above. */ for (i = M41ST84_REG_DATE_BYTES - 1; i >= 0; i--) { cmdbuf[0] = i; if (iic_exec(sc->sc_tag, i ? 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, "strtc_clock_write: failed to write rtc " " at 0x%x\n", i); /* XXX: Clock Hold is likely still asserted! */ return (0); } } iic_release_bus(sc->sc_tag, I2C_F_POLL); return (1); }
int settime_old(todr_chip_handle_t tcr, struct clock_ymdhms *dt) { u_char h; /* Stop the clock */ rtc_write(RTC_CONTROL,rtc_read(RTC_CONTROL) & ~RTC_START); #ifdef RTC_DEBUG printf("Setting RTC to 0x%08x. Regs before:\n",secs); rtc_print(); #endif rtc_write(RTC_SEC,TOBCD(dt->dt_sec)); rtc_write(RTC_MIN,TOBCD(dt->dt_min)); h = rtc_read(RTC_HRS); if (h & 0x80) { /* time is am/pm format */ if (dt->dt_hour == 0) { rtc_write(RTC_HRS,TOBCD(12)|0x80); } else if (dt->dt_hour < 12) { /* am */ rtc_write(RTC_HRS,TOBCD(dt->dt_hour)|0x80); } else if (dt->dt_hour == 12) { rtc_write(RTC_HRS,TOBCD(12)|0x80|0x20); } else /* pm */ rtc_write(RTC_HRS,TOBCD(dt->dt_hour-12)|0x80|0x20); } else { /* time is 24 hour format */ rtc_write(RTC_HRS,TOBCD(dt->dt_hour)); } rtc_write(RTC_DAY,TOBCD(dt->dt_wday)); rtc_write(RTC_DATE,TOBCD(dt->dt_day)); rtc_write(RTC_MON,TOBCD(dt->dt_mon)); rtc_write(RTC_YR,TOBCD(dt->dt_year%100)); #ifdef RTC_DEBUG printf("Regs after:\n",secs); rtc_print(); #endif /* restart the clock */ rtc_write(RTC_CONTROL,rtc_read(RTC_CONTROL) | RTC_START); return 0; }
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] = TOBCD(dt->dt_sec); bcd[MAX6900_BURST_MINUTE] = TOBCD(dt->dt_min); bcd[MAX6900_BURST_HOUR] = TOBCD(dt->dt_hour) & MAX6900_HOUR_24MASK; bcd[MAX6900_BURST_DATE] = TOBCD(dt->dt_day); bcd[MAX6900_BURST_WDAY] = TOBCD(dt->dt_wday); bcd[MAX6900_BURST_MONTH] = TOBCD(dt->dt_mon); bcd[MAX6900_BURST_YEAR] = TOBCD(dt->dt_year % 100); /* century in control slot */ bcd[MAX6900_BURST_CONTROL] = TOBCD(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); }
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; }