Ejemplo n.º 1
0
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));
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
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));
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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, &reg, 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;
}
Ejemplo n.º 10
0
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);
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
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 = 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;
}
Ejemplo n.º 13
0
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, &regs);
	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]));
}
Ejemplo n.º 14
0
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, &regs);
	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;
}
Ejemplo n.º 15
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, &regs)
	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;
}
Ejemplo n.º 16
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);
}
Ejemplo n.º 17
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;
}
Ejemplo n.º 18
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));
}
Ejemplo n.º 19
0
/*
 * 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));
}
Ejemplo n.º 20
0
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);
}
Ejemplo n.º 21
0
/*
 * 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)
Ejemplo n.º 22
0
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), &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));
}
Ejemplo n.º 23
0
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;
}
Ejemplo n.º 24
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);
}
Ejemplo n.º 25
0
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);
}
Ejemplo n.º 26
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] = 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;
}