Module Name: src Committed By: matt Date: Thu Feb 23 20:59:19 UTC 2012
Modified Files: src/sys/dev/i2c: ds1307.c ds1307reg.h Log Message: Rework this driver to support other dsrtc than just the DS1307. Support both BCD and 32-bit binary type RTCs. Supports DS1339, DS1672, and DS3232. To select variant, put the module # in flags in the the config file. dsrtc at iic0 addr 0x69 flags 1339 If the flags is not supplied, a 1307 is assumed (compatible). To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/sys/dev/i2c/ds1307.c cvs rdiff -u -r1.3 -r1.4 src/sys/dev/i2c/ds1307reg.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/i2c/ds1307.c diff -u src/sys/dev/i2c/ds1307.c:1.14 src/sys/dev/i2c/ds1307.c:1.15 --- src/sys/dev/i2c/ds1307.c:1.14 Sat Jan 7 15:03:11 2012 +++ src/sys/dev/i2c/ds1307.c Thu Feb 23 20:59:19 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: ds1307.c,v 1.14 2012/01/07 15:03:11 phx Exp $ */ +/* $NetBSD: ds1307.c,v 1.15 2012/02/23 20:59:19 matt Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ds1307.c,v 1.14 2012/01/07 15:03:11 phx Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ds1307.c,v 1.15 2012/02/23 20:59:19 matt Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -52,11 +52,55 @@ __KERNEL_RCSID(0, "$NetBSD: ds1307.c,v 1 #include <dev/i2c/i2cvar.h> #include <dev/i2c/ds1307reg.h> +struct dsrtc_model { + uint16_t dm_model; + uint8_t dm_ch_reg; + uint8_t dm_ch_value; + uint8_t dm_rtc_start; + uint8_t dm_rtc_size; + uint8_t dm_nvram_start; + uint8_t dm_nvram_size; + uint8_t dm_flags; +#define DSRTC_FLAG_CLOCK_HOLD 1 +#define DSRTC_FLAG_BCD 2 +}; + +static const struct dsrtc_model dsrtc_models[] = { + { + .dm_model = 1307, + .dm_ch_reg = DSXXXX_SECONDS, + .dm_ch_value = DS1307_SECONDS_CH, + .dm_rtc_start = DS1307_RTC_START, + .dm_rtc_size = DS1307_RTC_SIZE, + .dm_nvram_start = DS1307_NVRAM_START, + .dm_nvram_size = DS1307_NVRAM_SIZE, + .dm_flags = DSRTC_FLAG_BCD | DSRTC_FLAG_CLOCK_HOLD, + }, { + .dm_model = 1339, + .dm_rtc_start = DS1339_RTC_START, + .dm_rtc_size = DS1339_RTC_SIZE, + .dm_flags = DSRTC_FLAG_BCD, + }, { + .dm_model = 1672, + .dm_rtc_start = DS1672_RTC_START, + .dm_rtc_size = DS1672_RTC_SIZE, + .dm_flags = 0, + }, { + .dm_model = 3232, + .dm_rtc_start = DS3232_RTC_START, + .dm_rtc_size = DS3232_RTC_SIZE, + .dm_nvram_start = DS3232_NVRAM_START, + .dm_nvram_size = DS3232_NVRAM_SIZE, + .dm_flags = DSRTC_FLAG_BCD, + }, +}; + struct dsrtc_softc { device_t sc_dev; i2c_tag_t sc_tag; - int sc_address; - int sc_open; + uint8_t sc_address; + bool sc_open; + struct dsrtc_model sc_model; struct todr_chip_handle sc_todr; }; @@ -77,10 +121,30 @@ const struct cdevsw dsrtc_cdevsw = { nostop, notty, nopoll, nommap, nokqfilter, D_OTHER }; -static int dsrtc_clock_read(struct dsrtc_softc *, struct clock_ymdhms *); -static int dsrtc_clock_write(struct dsrtc_softc *, struct clock_ymdhms *); -static int dsrtc_gettime(struct todr_chip_handle *, struct clock_ymdhms *); -static int dsrtc_settime(struct todr_chip_handle *, struct clock_ymdhms *); +static int dsrtc_gettime_ymdhms(struct todr_chip_handle *, struct clock_ymdhms *); +static int dsrtc_settime_ymdhms(struct todr_chip_handle *, struct clock_ymdhms *); +static int dsrtc_clock_read_ymdhms(struct dsrtc_softc *, struct clock_ymdhms *); +static int dsrtc_clock_write_ymdhms(struct dsrtc_softc *, struct clock_ymdhms *); + +static int dsrtc_gettime_timeval(struct todr_chip_handle *, struct timeval *); +static int dsrtc_settime_timeval(struct todr_chip_handle *, struct timeval *); +static int dsrtc_clock_read_timeval(struct dsrtc_softc *, time_t *); +static int dsrtc_clock_write_timeval(struct dsrtc_softc *, time_t); + +static const struct dsrtc_model * +dsrtc_model(u_int model) +{ + /* no model given, assume it's a DS1307 (the first one) */ + if (model == 0) + return &dsrtc_models[0]; + + for (const struct dsrtc_model *dm = dsrtc_models; + dm < dsrtc_models + __arraycount(dsrtc_models); dm++) { + if (dm->dm_model == model) + return dm; + } + return NULL; +} static int dsrtc_match(device_t parent, cfdata_t cf, void *arg) @@ -94,7 +158,7 @@ dsrtc_match(device_t parent, cfdata_t cf } else { /* indirect config - check typical address */ if (ia->ia_addr == DS1307_ADDR) - return 1; + return dsrtc_model(cf->cf_flags & 0xffff) != NULL; } return 0; } @@ -104,19 +168,27 @@ dsrtc_attach(device_t parent, device_t s { struct dsrtc_softc *sc = device_private(self); struct i2c_attach_args *ia = arg; + const struct dsrtc_model * const dm = + dsrtc_model(device_cfdata(self)->cf_flags); - aprint_naive(": Real-time Clock/NVRAM\n"); - aprint_normal(": DS1307 Real-time Clock/NVRAM\n"); + aprint_naive(": Real-time Clock%s\n", + dm->dm_nvram_size > 0 ? "/NVRAM" : ""); + aprint_normal(": DS%u Real-time Clock%s\n", dm->dm_model, + dm->dm_nvram_size > 0 ? "/NVRAM" : ""); sc->sc_tag = ia->ia_tag; sc->sc_address = ia->ia_addr; + sc->sc_model = *dm; sc->sc_dev = self; sc->sc_open = 0; sc->sc_todr.cookie = sc; - sc->sc_todr.todr_gettime = NULL; - sc->sc_todr.todr_settime = NULL; - sc->sc_todr.todr_gettime_ymdhms = dsrtc_gettime; - sc->sc_todr.todr_settime_ymdhms = dsrtc_settime; + if (dm->dm_flags & DSRTC_FLAG_BCD) { + sc->sc_todr.todr_gettime_ymdhms = dsrtc_gettime_ymdhms; + sc->sc_todr.todr_settime_ymdhms = dsrtc_settime_ymdhms; + } else { + sc->sc_todr.todr_gettime = dsrtc_gettime_timeval; + sc->sc_todr.todr_settime = dsrtc_settime_timeval; + } sc->sc_todr.todr_setwen = NULL; todr_attach(&sc->sc_todr); @@ -132,11 +204,10 @@ dsrtc_open(dev_t dev, int flag, int fmt, return ENXIO; /* XXX: Locking */ - if (sc->sc_open) return EBUSY; - sc->sc_open = 1; + sc->sc_open = true; return 0; } @@ -149,7 +220,7 @@ dsrtc_close(dev_t dev, int flag, int fmt if ((sc = device_lookup_private(&dsrtc_cd, minor(dev))) == NULL) return ENXIO; - sc->sc_open = 0; + sc->sc_open = false; return 0; } @@ -158,24 +229,26 @@ int dsrtc_read(dev_t dev, struct uio *uio, int flags) { struct dsrtc_softc *sc; - u_int8_t ch, cmdbuf[1]; - int a, error; + int error; if ((sc = device_lookup_private(&dsrtc_cd, minor(dev))) == NULL) return ENXIO; - if (uio->uio_offset >= DS1307_NVRAM_SIZE) + const struct dsrtc_model * const dm = &sc->sc_model; + if (uio->uio_offset >= dm->dm_nvram_size) return EINVAL; if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) return error; - while (uio->uio_resid && uio->uio_offset < DS1307_NVRAM_SIZE) { - a = (int)uio->uio_offset; - cmdbuf[0] = a + DS1307_NVRAM_START; - if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, - sc->sc_address, cmdbuf, 1, - &ch, 1, 0)) != 0) { + KASSERT(uio->uio_offset >= 0); + while (uio->uio_resid && uio->uio_offset < dm->dm_nvram_size) { + uint8_t ch, cmd; + const u_int a = uio->uio_offset; + cmd = a + dm->dm_nvram_start; + if ((error = iic_exec(sc->sc_tag, + uio->uio_resid > 1 ? I2C_OP_READ : I2C_OP_READ_WITH_STOP, + sc->sc_address, &cmd, 1, &ch, 1, 0)) != 0) { iic_release_bus(sc->sc_tag, 0); aprint_error_dev(sc->sc_dev, "dsrtc_read: read failed at 0x%x\n", a); @@ -197,21 +270,22 @@ int dsrtc_write(dev_t dev, struct uio *uio, int flags) { struct dsrtc_softc *sc; - u_int8_t cmdbuf[2]; - int a, error; + int error; if ((sc = device_lookup_private(&dsrtc_cd, minor(dev))) == NULL) return ENXIO; - if (uio->uio_offset >= DS1307_NVRAM_SIZE) + const struct dsrtc_model * const dm = &sc->sc_model; + if (uio->uio_offset >= dm->dm_nvram_size) return EINVAL; if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) return error; - while (uio->uio_resid && uio->uio_offset < DS1307_NVRAM_SIZE) { - a = (int)uio->uio_offset; - cmdbuf[0] = a + DS1307_NVRAM_START; + while (uio->uio_resid && uio->uio_offset < dm->dm_nvram_size) { + uint8_t cmdbuf[2]; + const u_int a = (int)uio->uio_offset; + cmdbuf[0] = a + dm->dm_nvram_start; if ((error = uiomove(&cmdbuf[1], 1, uio)) != 0) break; @@ -230,7 +304,7 @@ dsrtc_write(dev_t dev, struct uio *uio, } static int -dsrtc_gettime(struct todr_chip_handle *ch, struct clock_ymdhms *dt) +dsrtc_gettime_ymdhms(struct todr_chip_handle *ch, struct clock_ymdhms *dt) { struct dsrtc_softc *sc = ch->cookie; struct clock_ymdhms check; @@ -245,29 +319,31 @@ dsrtc_gettime(struct todr_chip_handle *c */ retries = 5; do { - dsrtc_clock_read(sc, dt); - dsrtc_clock_read(sc, &check); + dsrtc_clock_read_ymdhms(sc, dt); + dsrtc_clock_read_ymdhms(sc, &check); } while (memcmp(dt, &check, sizeof(check)) != 0 && --retries); return 0; } static int -dsrtc_settime(struct todr_chip_handle *ch, struct clock_ymdhms *dt) +dsrtc_settime_ymdhms(struct todr_chip_handle *ch, struct clock_ymdhms *dt) { struct dsrtc_softc *sc = ch->cookie; - if (dsrtc_clock_write(sc, dt) == 0) + if (dsrtc_clock_write_ymdhms(sc, dt) == 0) return -1; return 0; } static int -dsrtc_clock_read(struct dsrtc_softc *sc, struct clock_ymdhms *dt) +dsrtc_clock_read_ymdhms(struct dsrtc_softc *sc, struct clock_ymdhms *dt) { - u_int8_t bcd[DS1307_NRTC_REGS], cmdbuf[1]; - int i; + struct dsrtc_model * const dm = &sc->sc_model; + uint8_t bcd[DSXXXX_RTC_SIZE], cmdbuf[1]; + + KASSERT(DSXXXX_RTC_SIZE >= dm->dm_rtc_size); if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, @@ -276,8 +352,8 @@ dsrtc_clock_read(struct dsrtc_softc *sc, } /* Read each RTC register in order. */ - for (i = DS1307_SECONDS; i < DS1307_NRTC_REGS; i++) { - cmdbuf[0] = i; + for (u_int i = 0; i < dm->dm_rtc_size; i++) { + cmdbuf[0] = dm->dm_rtc_start + i; if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, cmdbuf, 1, @@ -294,46 +370,52 @@ dsrtc_clock_read(struct dsrtc_softc *sc, iic_release_bus(sc->sc_tag, I2C_F_POLL); /* - * Convert the DS1307's register values into something useable + * Convert the RTC's register values into something useable */ - dt->dt_sec = FROMBCD(bcd[DS1307_SECONDS] & DS1307_SECONDS_MASK); - dt->dt_min = FROMBCD(bcd[DS1307_MINUTES] & DS1307_MINUTES_MASK); + dt->dt_sec = FROMBCD(bcd[DSXXXX_SECONDS] & DSXXXX_SECONDS_MASK); + dt->dt_min = FROMBCD(bcd[DSXXXX_MINUTES] & DSXXXX_MINUTES_MASK); - if ((bcd[DS1307_HOURS] & DS1307_HOURS_12HRS_MODE) != 0) { - dt->dt_hour = FROMBCD(bcd[DS1307_HOURS] & - DS1307_HOURS_12MASK) % 12; /* 12AM -> 0, 12PM -> 12 */ - if (bcd[DS1307_HOURS] & DS1307_HOURS_12HRS_PM) + if ((bcd[DSXXXX_HOURS] & DSXXXX_HOURS_12HRS_MODE) != 0) { + dt->dt_hour = FROMBCD(bcd[DSXXXX_HOURS] & + DSXXXX_HOURS_12MASK) % 12; /* 12AM -> 0, 12PM -> 12 */ + if (bcd[DSXXXX_HOURS] & DSXXXX_HOURS_12HRS_PM) dt->dt_hour += 12; } else - dt->dt_hour = FROMBCD(bcd[DS1307_HOURS] & - DS1307_HOURS_24MASK); + dt->dt_hour = FROMBCD(bcd[DSXXXX_HOURS] & + DSXXXX_HOURS_24MASK); - dt->dt_day = FROMBCD(bcd[DS1307_DATE] & DS1307_DATE_MASK); - dt->dt_mon = FROMBCD(bcd[DS1307_MONTH] & DS1307_MONTH_MASK); + dt->dt_day = FROMBCD(bcd[DSXXXX_DATE] & DSXXXX_DATE_MASK); + dt->dt_mon = FROMBCD(bcd[DSXXXX_MONTH] & DSXXXX_MONTH_MASK); /* XXX: Should be an MD way to specify EPOCH used by BIOS/Firmware */ - dt->dt_year = FROMBCD(bcd[DS1307_YEAR]) + POSIX_BASE_YEAR; + dt->dt_year = FROMBCD(bcd[DSXXXX_YEAR]) + POSIX_BASE_YEAR; + if (bcd[DSXXXX_MONTH] & DSXXXX_MONTH_CENTURY) + dt->dt_year += 100; return 1; } static int -dsrtc_clock_write(struct dsrtc_softc *sc, struct clock_ymdhms *dt) +dsrtc_clock_write_ymdhms(struct dsrtc_softc *sc, struct clock_ymdhms *dt) { - uint8_t bcd[DS1307_NRTC_REGS], cmdbuf[2]; - int i; + struct dsrtc_model * const dm = &sc->sc_model; + uint8_t bcd[DSXXXX_RTC_SIZE], cmdbuf[2]; + + KASSERT(DSXXXX_RTC_SIZE >= dm->dm_rtc_size); /* - * Convert our time representation into something the DS1307 + * Convert our time representation into something the DSXXXX * can understand. */ - bcd[DS1307_SECONDS] = TOBCD(dt->dt_sec); - bcd[DS1307_MINUTES] = TOBCD(dt->dt_min); - bcd[DS1307_HOURS] = TOBCD(dt->dt_hour); /* DS1307_HOURS_12HRS_MODE=0 */ - bcd[DS1307_DATE] = TOBCD(dt->dt_day); - bcd[DS1307_DAY] = TOBCD(dt->dt_wday); - bcd[DS1307_MONTH] = TOBCD(dt->dt_mon); - bcd[DS1307_YEAR] = TOBCD((dt->dt_year - POSIX_BASE_YEAR) % 100); + bcd[DSXXXX_SECONDS] = TOBCD(dt->dt_sec); + bcd[DSXXXX_MINUTES] = TOBCD(dt->dt_min); + bcd[DSXXXX_HOURS] = TOBCD(dt->dt_hour); /* DSXXXX_HOURS_12HRS_MODE=0 */ + bcd[DSXXXX_DATE] = TOBCD(dt->dt_day); + bcd[DSXXXX_DAY] = TOBCD(dt->dt_wday); + bcd[DSXXXX_MONTH] = TOBCD(dt->dt_mon); + bcd[DSXXXX_YEAR] = TOBCD((dt->dt_year - POSIX_BASE_YEAR) % 100); + if (dt->dt_year - POSIX_BASE_YEAR >= 100) + bcd[DSXXXX_MONTH] |= DSXXXX_MONTH_CENTURY; if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { aprint_error_dev(sc->sc_dev, @@ -342,14 +424,23 @@ dsrtc_clock_write(struct dsrtc_softc *sc } /* Stop the clock */ - cmdbuf[0] = DS1307_SECONDS; - cmdbuf[1] = DS1307_SECONDS_CH; + cmdbuf[0] = dm->dm_ch_reg; + + 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, + "dsrtc_clock_write: failed to read Hold Clock\n"); + return 0; + } + + cmdbuf[1] |= dm->dm_ch_value; if (iic_exec(sc->sc_tag, I2C_OP_WRITE, sc->sc_address, - cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { + cmdbuf, 1, &cmdbuf[1], 1, I2C_F_POLL)) { iic_release_bus(sc->sc_tag, I2C_F_POLL); aprint_error_dev(sc->sc_dev, - "dsrtc_clock_write: failed to Hold Clock\n"); + "dsrtc_clock_write: failed to write Hold Clock\n"); return 0; } @@ -357,12 +448,14 @@ dsrtc_clock_write(struct dsrtc_softc *sc * Write registers in reverse order. The last write (to the Seconds * register) will undo the Clock Hold, above. */ - for (i = DS1307_NRTC_REGS - 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)) { + uint8_t op = I2C_OP_WRITE; + for (signed int i = dm->dm_rtc_size - 1; i >= 0; i--) { + cmdbuf[0] = dm->dm_rtc_start + i; + if (dm->dm_rtc_start + i == dm->dm_ch_reg) { + op = I2C_OP_WRITE_WITH_STOP; + } + if (iic_exec(sc->sc_tag, op, 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, "dsrtc_clock_write: failed to write rtc " @@ -371,8 +464,134 @@ dsrtc_clock_write(struct dsrtc_softc *sc return 0; } } + /* + * If the clock hold register isn't the same register as seconds, + * we need to reeanble the clock. + */ + if (op != I2C_OP_WRITE_WITH_STOP) { + cmdbuf[0] = dm->dm_ch_reg; + cmdbuf[1] &= ~dm->dm_ch_value; + + 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, + "dsrtc_clock_write: failed to Hold Clock\n"); + return 0; + } + } iic_release_bus(sc->sc_tag, I2C_F_POLL); return 1; } + +static int +dsrtc_gettime_timeval(struct todr_chip_handle *ch, struct timeval *tv) +{ + struct dsrtc_softc *sc = ch->cookie; + struct timeval check; + int retries; + + memset(tv, 0, sizeof(*tv)); + memset(&check, 0, sizeof(check)); + + /* + * Since we don't support Burst Read, we have to read the clock twice + * until we get two consecutive identical results. + */ + retries = 5; + do { + dsrtc_clock_read_timeval(sc, &tv->tv_sec); + dsrtc_clock_read_timeval(sc, &check.tv_sec); + } while (memcmp(tv, &check, sizeof(check)) != 0 && --retries); + + return 0; +} + +static int +dsrtc_settime_timeval(struct todr_chip_handle *ch, struct timeval *tv) +{ + struct dsrtc_softc *sc = ch->cookie; + + if (dsrtc_clock_write_timeval(sc, tv->tv_sec) == 0) + return -1; + + return 0; +} + +/* + * The RTC probably has a nice Clock Burst Read/Write command, but we can't use + * it, since some I2C controllers don't support anything other than single-byte + * transfers. + */ +static int +dsrtc_clock_read_timeval(struct dsrtc_softc *sc, time_t *tp) +{ + const struct dsrtc_model * const dm = &sc->sc_model; + uint8_t buf[4]; + + if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { + aprint_error_dev(sc->sc_dev, "%s: failed to acquire I2C bus\n", + __func__); + return (0); + } + + /* read all registers: */ + uint8_t reg = dm->dm_rtc_start; + if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address, ®, 1, + buf, 4, I2C_F_POLL)) { + iic_release_bus(sc->sc_tag, I2C_F_POLL); + aprint_error_dev(sc->sc_dev, "%s: failed to read rtc\n", + __func__); + return (0); + } + + /* Done with I2C */ + iic_release_bus(sc->sc_tag, I2C_F_POLL); + + uint32_t v = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + *tp = v; + + aprint_debug_dev(sc->sc_dev, "%s: cntr=0x%08"PRIx32"\n", + __func__, v); + + return (1); +} + +static int +dsrtc_clock_write_timeval(struct dsrtc_softc *sc, time_t t) +{ + const struct dsrtc_model * const dm = &sc->sc_model; + size_t buflen = dm->dm_rtc_size + 2; + uint8_t buf[buflen]; + + KASSERT((dm->dm_flags & DSRTC_FLAG_CLOCK_HOLD) == 0); + KASSERT(dm->dm_ch_reg == dm->dm_rtc_start + 4); + + buf[0] = dm->dm_rtc_start; + buf[1] = (t >> 0) & 0xff; + buf[2] = (t >> 8) & 0xff; + buf[3] = (t >> 16) & 0xff; + buf[4] = (t >> 24) & 0xff; + buf[5] = 0; + + if (iic_acquire_bus(sc->sc_tag, I2C_F_POLL)) { + aprint_error_dev(sc->sc_dev, "%s: failed to acquire I2C bus\n", + __func__); + return (0); + } + + /* send data */ + if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_address, + &buf, buflen, NULL, 0, I2C_F_POLL)) { + iic_release_bus(sc->sc_tag, I2C_F_POLL); + aprint_error_dev(sc->sc_dev, "%s: failed to set time\n", + __func__); + return (0); + } + + iic_release_bus(sc->sc_tag, I2C_F_POLL); + + return (1); +} Index: src/sys/dev/i2c/ds1307reg.h diff -u src/sys/dev/i2c/ds1307reg.h:1.3 src/sys/dev/i2c/ds1307reg.h:1.4 --- src/sys/dev/i2c/ds1307reg.h:1.3 Sat Jan 7 15:03:11 2012 +++ src/sys/dev/i2c/ds1307reg.h Thu Feb 23 20:59:19 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: ds1307reg.h,v 1.3 2012/01/07 15:03:11 phx Exp $ */ +/* $NetBSD: ds1307reg.h,v 1.4 2012/02/23 20:59:19 matt Exp $ */ /* * Copyright (c) 2003 Wasabi Systems, Inc. @@ -44,33 +44,62 @@ #define DS1307_ADDR 0x68 /* Fixed I2C Slave Address */ -#define DS1307_SECONDS 0x00 -#define DS1307_MINUTES 0x01 -#define DS1307_HOURS 0x02 -#define DS1307_DAY 0x03 -#define DS1307_DATE 0x04 -#define DS1307_MONTH 0x05 -#define DS1307_YEAR 0x06 +#define DSXXXX_SECONDS 0x00 +#define DSXXXX_MINUTES 0x01 +#define DSXXXX_HOURS 0x02 +#define DSXXXX_DAY 0x03 +#define DSXXXX_DATE 0x04 +#define DSXXXX_MONTH 0x05 +#define DSXXXX_YEAR 0x06 +#define DSXXXX_RTC_SIZE 7 + #define DS1307_CONTROL 0x07 +#define DS1307_RTC_START 0 +#define DS1307_RTC_SIZE DSXXXX_RTC_SIZE #define DS1307_NVRAM_START 0x08 -#define DS1307_NVRAM_END 0x3f +#define DS1307_NVRAM_SIZE 0x38 + +#define DS1339_CONTROL 0x0e +#define DS1339_RTC_START 0 +#define DS1339_RTC_SIZE DSXXXX_RTC_SIZE +#define DS1339_NVRAM_START 0 +#define DS1339_NVRAM_SIZE 0 + +#define DS1672_CNTR1 0x00 +#define DS1672_CNTR2 0x01 +#define DS1672_CNTR3 0x02 +#define DS1672_CNTR4 0x03 +#define DS1672_CONTROL 0x04 +#define DS1672_TRICKLE 0x05 + +#define DS1672_RTC_START 0 +#define DS1672_RTC_SIZE 4 +#define DS1672_NVRAM_START 0 +#define DS1672_NVRAM_SIZE 0 + +#define DS3232_CONTROL 0x0e +#define DS3232_CSR 0x0f +#define DS3232_RTC_START 0 +#define DS3232_RTC_SIZE DSXXXX_RTC_SIZE +#define DS3232_NVRAM_START 0x14 +#define DS3232_NVRAM_SIZE 0xec -#define DS1307_NRTC_REGS 7 -#define DS1307_NVRAM_SIZE ((DS1307_NVRAM_END - DS1307_NVRAM_START) + 1) /* * Bit definitions. */ +#define DSXXXX_SECONDS_MASK 0x7f +#define DSXXXX_MINUTES_MASK 0x7f +#define DSXXXX_HOURS_12HRS_MODE (1u << 6) /* Set for 12 hour mode */ +#define DSXXXX_HOURS_12HRS_PM (1u << 5) /* If 12 hr mode, set = PM */ +#define DSXXXX_HOURS_12MASK 0x1f +#define DSXXXX_HOURS_24MASK 0x3f +#define DSXXXX_DAY_MASK 0x07 +#define DSXXXX_DATE_MASK 0x3f +#define DSXXXX_MONTH_MASK 0x1f +#define DSXXXX_MONTH_CENTURY 0x80 + #define DS1307_SECONDS_CH (1u << 7) /* Clock Hold */ -#define DS1307_SECONDS_MASK 0x7f -#define DS1307_MINUTES_MASK 0x7f -#define DS1307_HOURS_12HRS_MODE (1u << 6) /* Set for 12 hour mode */ -#define DS1307_HOURS_12HRS_PM (1u << 5) /* If 12 hr mode, set = PM */ -#define DS1307_HOURS_12MASK 0x1f -#define DS1307_HOURS_24MASK 0x3f -#define DS1307_DAY_MASK 0x07 -#define DS1307_DATE_MASK 0x3f -#define DS1307_MONTH_MASK 0x1f #define DS1307_CONTROL_OUT (1u << 7) /* OSC/OUT pin value */ #define DS1307_CONTROL_SQWE (1u << 4) /* Enable square wave output */ #define DS1307_CONTROL_1HZ 0 @@ -78,4 +107,6 @@ #define DS1307_CONTROL_8192HZ 2 #define DS1307_CONTROL_32768HZ 3 +#define DSXXXX_CONTROL_DOSC (1u << 7) /* Disable Oscillator */ + #endif /* _DEV_I2C_DS1307REG_H_ */