diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2006-01-13 21:41:41 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2006-01-13 21:41:41 +0000 |
commit | df4d7ff05d43998a97f83bd2fb9b8fa9e8d7f072 (patch) | |
tree | 43509814c80fda39e3b220e8f0f3bb98ddf77ccd /sys/dev | |
parent | dc443372d09e7e316d0cc7bd705e0c38417b4448 (diff) |
handle all 3 types of chips correctly. go into continuous mode, and
start the chips right (two kinds of start sequences). then get the
temperature readings correctly, including negative temperatures.
done with grange.
pity the poor russian with only the lowest of the low end i2c chips
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/i2c/ds1631.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/sys/dev/i2c/ds1631.c b/sys/dev/i2c/ds1631.c index 703e063a8c7..13bcc30d9e8 100644 --- a/sys/dev/i2c/ds1631.c +++ b/sys/dev/i2c/ds1631.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ds1631.c,v 1.3 2006/01/13 00:13:01 deraadt Exp $ */ +/* $OpenBSD: ds1631.c,v 1.4 2006/01/13 21:41:40 deraadt Exp $ */ /* * Copyright (c) 2005 Theo de Raadt @@ -24,7 +24,12 @@ #include <dev/i2c/i2cvar.h> /* Maxim ds 1631 registers */ +#define DS1631_START 0x51 +#define DS1624_START 0xee #define DS1631_TEMP 0xaa +#define DS1631_CONTROL 0xac +#define DS1631_CONTROL_DONE 0x80 +#define DS1631_CONTROL_1SHOT 0x01 /* Sensors */ #define MAXDS_TEMP 0 @@ -67,11 +72,45 @@ maxds_attach(struct device *parent, struct device *self, void *aux) { struct maxds_softc *sc = (struct maxds_softc *)self; struct i2c_attach_args *ia = aux; + u_int8_t cmd, data; int i; + printf(": %s", ia->ia_name); + sc->sc_tag = ia->ia_tag; sc->sc_addr = ia->ia_addr; + iic_acquire_bus(sc->sc_tag, 0); + + cmd = DS1631_CONTROL; + if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, + sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) { + if (data & DS1631_CONTROL_1SHOT) { + /* + * 1-Shot mode would require us to write every refresh + * which is stupid. Put us into continuous mode. + */ + data &= ~DS1631_CONTROL_1SHOT; + + (void) iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, + sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0); + //delay(10 * 1000); + printf(", continuous"); + goto dostart; + } + if (data & DS1631_CONTROL_DONE) { +dostart: + cmd = DS1631_START; + if (strcmp(ia->ia_name, "ds1624") == 0) + cmd = DS1624_START; + (void) iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, + sc->sc_addr, &cmd, sizeof cmd, NULL, 0, 0); + printf(", starting"); + } + } + + iic_release_bus(sc->sc_tag, 0); + /* Initialize sensor data. */ for (i = 0; i < MAXDS_NUM_SENSORS; i++) strlcpy(sc->sc_sensor[i].device, sc->sc_dev.dv_xname, @@ -104,7 +143,7 @@ maxds_refresh(void *arg) if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) sc->sc_sensor[MAXDS_TEMP].value = 273150000 + - 1000000 * data[1] + 1000000 * data[0] / 256; + ((int)((u_int16_t)data[0] << 8 | data[1])) / 8 * 31250; iic_release_bus(sc->sc_tag, 0); } |