summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2006-01-13 21:41:41 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2006-01-13 21:41:41 +0000
commitdf4d7ff05d43998a97f83bd2fb9b8fa9e8d7f072 (patch)
tree43509814c80fda39e3b220e8f0f3bb98ddf77ccd
parentdc443372d09e7e316d0cc7bd705e0c38417b4448 (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
-rw-r--r--sys/dev/i2c/ds1631.c43
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);
}