diff options
-rw-r--r-- | sys/arm/conf/AVILA.hints | 4 | ||||
-rw-r--r-- | sys/arm/conf/BWCT.hints | 4 | ||||
-rw-r--r-- | sys/arm/conf/CAMBRIA.hints | 4 | ||||
-rw-r--r-- | sys/dev/iicbus/ds1672.c | 85 |
4 files changed, 72 insertions, 25 deletions
diff --git a/sys/arm/conf/AVILA.hints b/sys/arm/conf/AVILA.hints index 2d6d4dc..f5a829f 100644 --- a/sys/arm/conf/AVILA.hints +++ b/sys/arm/conf/AVILA.hints @@ -44,5 +44,5 @@ hint.ad7418.0.at="iicbus0" hint.ad7418.0.addr=0x50 # Dallas Semiconductor DS1672 RTC -hint.ds1672.0.at="iicbus0" -hint.ds1672.0.addr=0xd0 +hint.rtc.0.at="iicbus0" +hint.rtc.0.addr=0xd0 diff --git a/sys/arm/conf/BWCT.hints b/sys/arm/conf/BWCT.hints index d127778..ee55030 100644 --- a/sys/arm/conf/BWCT.hints +++ b/sys/arm/conf/BWCT.hints @@ -1,8 +1,8 @@ # $FreeBSD$ # Dallas Semiconductor DS1672 RTC sitting on the I2C bus -hint.ds1672.0.at="iicbus0" -hint.ds1672.0.addr=0xd0 +hint.rtc.0.at="iicbus0" +hint.rtc.0.addr=0xd0 # NAtional Semiconductor LM75 temperature sensor sitting on the I2C bus hint.lm75.0.at="iicbus0" diff --git a/sys/arm/conf/CAMBRIA.hints b/sys/arm/conf/CAMBRIA.hints index a01093a..07db189 100644 --- a/sys/arm/conf/CAMBRIA.hints +++ b/sys/arm/conf/CAMBRIA.hints @@ -46,8 +46,8 @@ hint.ad7418.0.at="iicbus0" hint.ad7418.0.addr=0x50 # Dallas Semiconductor DS1672 RTC -hint.ds1672.0.at="iicbus0" -hint.ds1672.0.addr=0xd0 +hint.rtc.0.at="iicbus0" +hint.rtc.0.addr=0xd0 # USB is part of the chip hint.ehci.0.at="ixp0" 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), }; |