Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #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 = 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);
}
Beispiel #4
0
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;
}
Beispiel #7
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;
}
Beispiel #8
0
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, &reg, 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;
}
Beispiel #9
0
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);
}
Beispiel #10
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;
}
Beispiel #11
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;
}