Esempio n. 1
0
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);
}
Esempio n. 2
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, &reg, 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;
}
Esempio n. 4
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;
}
Esempio n. 5
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);
}
Esempio n. 6
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;
}
Esempio n. 7
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] = 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);
}