Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/i2c Rework this driver to support other dsrtc than j...
details: https://anonhg.NetBSD.org/src/rev/a218c3ae0958
branches: trunk
changeset: 777574:a218c3ae0958
user: matt <matt%NetBSD.org@localhost>
date: Thu Feb 23 20:59:19 2012 +0000
description:
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).
diffstat:
sys/dev/i2c/ds1307.c | 371 ++++++++++++++++++++++++++++++++++++++---------
sys/dev/i2c/ds1307reg.h | 71 ++++++--
2 files changed, 346 insertions(+), 96 deletions(-)
diffs (truncated from 658 to 300 lines):
diff -r 63f35d53b58d -r a218c3ae0958 sys/dev/i2c/ds1307.c
--- a/sys/dev/i2c/ds1307.c Thu Feb 23 20:49:46 2012 +0000
+++ b/sys/dev/i2c/ds1307.c Thu Feb 23 20:59:19 2012 +0000
@@ -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 @@
#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 @@
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 @@
} 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 @@
{
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 @@
return ENXIO;
/* XXX: Locking */
-
if (sc->sc_open)
return EBUSY;
- sc->sc_open = 1;
+ sc->sc_open = true;
return 0;
}
@@ -149,7 +220,7 @@
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 @@
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 @@
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 @@
}
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 @@
*/
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 @@
}
/* 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,
Home |
Main Index |
Thread Index |
Old Index