summaryrefslogtreecommitdiffstats
path: root/sys/dev/iicbus/ds1672.c
diff options
context:
space:
mode:
authorstas <stas@FreeBSD.org>2009-04-20 15:47:06 +0000
committerstas <stas@FreeBSD.org>2009-04-20 15:47:06 +0000
commitc07d8be27a1524f2a97721591588d69603218eab (patch)
tree9e3a369c9ced705e6ff6c85f22b93f90564601ad /sys/dev/iicbus/ds1672.c
parentdfdb0873974045d6d058ecc28453a6c8091472d9 (diff)
downloadFreeBSD-src-c07d8be27a1524f2a97721591588d69603218eab.zip
FreeBSD-src-c07d8be27a1524f2a97721591588d69603218eab.tar.gz
- Give a warning and start the oscillator if it was not previously
runned. - Rename ds1672 -> rtc to follow the other drivers. - Refactor/simplify the code a bit. MFC after: 2 weeks
Diffstat (limited to 'sys/dev/iicbus/ds1672.c')
-rw-r--r--sys/dev/iicbus/ds1672.c85
1 files changed, 66 insertions, 19 deletions
diff --git a/sys/dev/iicbus/ds1672.c b/sys/dev/iicbus/ds1672.c
index 1169271..6cc1524 100644
--- a/sys/dev/iicbus/ds1672.c
+++ b/sys/dev/iicbus/ds1672.c
@@ -50,8 +50,12 @@ __FBSDID("$FreeBSD$");
#define DS1672_CTRL 4 /* control (1 byte) */
#define DS1672_TRICKLE 5 /* trickle charger (1 byte) */
+#define DS1672_CTRL_EOSC (1 << 7) /* Stop/start flag. */
+
#define NANOSEC 1000000000
+#define MAX_IIC_DATA_SIZE 4
+
struct ds1672_softc {
device_t sc_dev;
};
@@ -65,12 +69,64 @@ ds1672_probe(device_t dev)
}
static int
+ds1672_read(device_t dev, uint8_t addr, uint8_t *data, uint8_t size)
+{
+ struct iic_msg msgs[2] = {
+ { DS1672_ADDR, IIC_M_WR, 1, &addr },
+ { DS1672_ADDR, IIC_M_RD, size, data }
+ };
+
+ return (iicbus_transfer(dev, msgs, 2));
+}
+
+static int
+ds1672_write(device_t dev, uint8_t addr, uint8_t *data, uint8_t size)
+{
+ uint8_t buffer[MAX_IIC_DATA_SIZE + 1];
+ struct iic_msg msgs[1] = {
+ { DS1672_ADDR, IIC_M_WR, size + 1, buffer },
+ };
+
+ if (size > MAX_IIC_DATA_SIZE)
+ return (ENOMEM);
+ /* NB: register pointer precedes actual data */
+ buffer[0] = addr;
+ memcpy(buffer + 1, data, size);
+ return (iicbus_transfer(dev, msgs, 1));
+}
+
+static int
+ds1672_init(device_t dev)
+{
+ uint8_t ctrl;
+ int error;
+
+ error = ds1672_read(dev, DS1672_CTRL, &ctrl, 1);
+ if (error)
+ return (error);
+
+ /*
+ * Check if oscialltor is not runned.
+ */
+ if (ctrl & DS1672_CTRL_EOSC) {
+ device_printf(dev, "RTC oscillator was stopped. Check system"
+ " time and RTC battery.\n");
+ ctrl &= ~DS1672_CTRL_EOSC; /* Start oscillator. */
+ error = ds1672_write(dev, DS1672_CTRL, &ctrl, 1);
+ }
+ return (error);
+}
+
+static int
ds1672_attach(device_t dev)
{
struct ds1672_softc *sc = device_get_softc(dev);
+ int error;
sc->sc_dev = dev;
-
+ error = ds1672_init(dev);
+ if (error)
+ return (error);
clock_register(dev, 1000);
return (0);
}
@@ -78,39 +134,30 @@ ds1672_attach(device_t dev)
static int
ds1672_gettime(device_t dev, struct timespec *ts)
{
- uint8_t addr[1] = { DS1672_COUNTER };
uint8_t secs[4];
- struct iic_msg msgs[2] = {
- { DS1672_ADDR, IIC_M_WR, 1, addr },
- { DS1672_ADDR, IIC_M_RD, 4, secs },
- };
int error;
- error = iicbus_transfer(dev, msgs, 2);
+ error = ds1672_read(dev, DS1672_COUNTER, secs, 4);
if (error == 0) {
/* counter has seconds since epoch */
ts->tv_sec = (secs[3] << 24) | (secs[2] << 16)
| (secs[1] << 8) | (secs[0] << 0);
ts->tv_nsec = NANOSEC / 2;
}
- return error;
+ return (error);
}
static int
ds1672_settime(device_t dev, struct timespec *ts)
{
- /* NB: register pointer precedes actual data */
- uint8_t data[5] = { DS1672_COUNTER };
- struct iic_msg msgs[1] = {
- { DS1672_ADDR, IIC_M_WR, 5, data },
- };
+ uint8_t data[4];
- data[1] = (ts->tv_sec >> 0) & 0xff;
- data[2] = (ts->tv_sec >> 8) & 0xff;
- data[3] = (ts->tv_sec >> 16) & 0xff;
- data[4] = (ts->tv_sec >> 24) & 0xff;
+ data[0] = (ts->tv_sec >> 0) & 0xff;
+ data[1] = (ts->tv_sec >> 8) & 0xff;
+ data[2] = (ts->tv_sec >> 16) & 0xff;
+ data[3] = (ts->tv_sec >> 24) & 0xff;
- return iicbus_transfer(dev, msgs, 1);
+ return (ds1672_write(dev, DS1672_COUNTER, data, 4));
}
static device_method_t ds1672_methods[] = {
@@ -124,7 +171,7 @@ static device_method_t ds1672_methods[] = {
};
static driver_t ds1672_driver = {
- "ds1672",
+ "rtc",
ds1672_methods,
sizeof(struct ds1672_softc),
};
OpenPOWER on IntegriCloud