summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2005-12-23 04:09:57 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2005-12-23 04:09:57 +0000
commit5d7952b1d73c9a0ea0083b2e72ec731372ac7927 (patch)
tree4475ed3c0e4e8242aa1381b8a1c90afee00d1d7b /sys
parente5246807895d8b8f74ca667243a07c9bfe183ac7 (diff)
work in progress towards "identifying" various devices on the i2c bus.
this will later on hopefully be table driven, but first I have to read the 100 or so data sheets and start coding up detection rules..... bleah
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/i2c/i2c_scan.c174
1 files changed, 128 insertions, 46 deletions
diff --git a/sys/dev/i2c/i2c_scan.c b/sys/dev/i2c/i2c_scan.c
index 28f58603467..44b5d0694d6 100644
--- a/sys/dev/i2c/i2c_scan.c
+++ b/sys/dev/i2c/i2c_scan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i2c_scan.c,v 1.3 2005/12/23 03:04:39 pedro Exp $ */
+/* $OpenBSD: i2c_scan.c,v 1.4 2005/12/23 04:09:56 deraadt Exp $ */
/*
* Copyright (c) 2005 Alexander Yurchenko <grange@openbsd.org>
@@ -27,46 +27,38 @@
#define _I2C_PRIVATE
#include <dev/i2c/i2cvar.h>
-/*
-some basic devices...
-
- 0x7 == 0x0001 national lm92
- 0x3e == 0x01 national product
- 0x3f == 0x73 lm93
- 0x3e == 0x02
- 0x3f == 0x06 lm87
- 0xfe == 0x01 national product
- 0xff == 0x33 lm90
- 0xff == 0x49 0x52 lm99 lm89
- 0xff == 0x17 lm86
- 0xff == ?? lm83?
- cannot identify lm81 lm80
- 0xfe == 0x4d maxim (6659/6658/6659) == lm90
- no 0x7 register?? maxim (6633/6634/6635) lm92
-
-XXX remove this block of text later
-0x00 National (on LM84)
-0x01 National
-0x12C3 Asus (at 0x4F)
-0x23 Analog Devices
-0x41 Analog Devices (also at 0x16)
-0x49 TI
-0x4D Maxim
-0x54 On Semi
-0x5C SMSC
-0x5D SMSC
-0x55 SMSC
-0x5CA3 Winbond (at 0x4F)
-0x90 ITE (at 0x58)
-0xA1 Philips (at 0x05 too)
-0xA3 Winbond (at 0x4F)
-0xAC Myson (at 0x58)
-0xC3 Asus (at 0x4F)
-0xDA Dallas
-0x54 Microchip (at 0x7)
+void iic_probe(struct device *, struct i2cbus_attach_args *, u_int8_t);
+/*
+ * some basic rules for finding devices...
+ *
+ * 0x7 == 0x0001 national lm92
+ * 0xfe == 0x4d maxim (6659/6658/6659) == lm90
+ * no 0x7 register?? maxim (6633/6634/6635) lm92
+ *
+ * XXX remove this block of text later
+ * 0x00 National (on LM84)
+ * 0x01 National
+ * 0x12C3 Asus (at 0x4F)
+ * 0x23 Analog Devices
+ * 0x41 Analog Devices (also at 0x16)
+ * 0x49 TI
+ * 0x4D Maxim
+ * 0x54 On Semi
+ * 0x5C SMSC
+ * 0x5D SMSC
+ * 0x55 SMSC
+ * 0x5CA3 Winbond (at 0x4F)
+ * 0x90 ITE (at 0x58)
+ * 0xA1 Philips (at 0x05 too)
+ * 0xA3 Winbond (at 0x4F)
+ * 0xAC Myson (at 0x58)
+ * 0xC3 Asus (at 0x4F)
+ * 0xDA Dallas
+ * 0x54 Microchip (at 0x7)
*/
+/* ports to probe for sensors */
struct {
u_int8_t start, end;
} probe_paddrs[] = {
@@ -75,7 +67,97 @@ struct {
{ 0xad, 0xad }
};
-u_int8_t probe[] = { 0x3e, 0x3f, 0xfe, 0xff, 0x4f, 0x58, 0x07 };
+u_int8_t probereg[] = { 0x3e, 0x3f, 0xfe, 0xff, 0x07, 0x4d, 0x4e, 0x4f, 0x58, 0x3d };
+#define P_3e 0
+#define P_3f 1
+#define P_fe 2
+#define P_ff 3
+#define P_07 4
+#define P_4d 5
+#define P_4e 6
+#define P_4f 7
+#define P_58 8
+#define P_3d 9
+u_int8_t probeval[sizeof(probereg)];
+
+void
+iic_probe(struct device *self, struct i2cbus_attach_args *iba, u_int8_t addr)
+{
+ struct i2c_attach_args ia;
+ char *name = NULL;
+ int i;
+
+ if (probeval[P_3e] == 0x41) {
+ /*
+ * Analog Devices adt/adm product code at 0x3e == 0x41
+ * probe newer to older. newer chips have a valid 0x3d
+ * product number, while older ones encoded the product
+ * into the upper half of the step at 0x3f
+ */
+ if (probeval[P_3d] == 0x03 || probeval[P_3d] == 0x08 ||
+ probeval[P_3d] == 0x07)
+ name = "adt7516"; /* adt7517, adt7519 */
+ if (probeval[P_3d] == 0x76)
+ name = "adt7476";
+ else if (probeval[P_3d] == 0x70)
+ name = "adt7470";
+ else if (probeval[P_3d] == 0x27)
+ name = "adt7460"; /* adt746x */
+ else if (probeval[P_3d] == 0x33)
+ name = "adm1033";
+ else if (probeval[P_3d] == 0x30)
+ name = "adm1030";
+ else if ((probeval[P_3f] & 0xf0) == 0x20)
+ name = "adm1025";
+ else if ((probeval[P_ff] & 0xf0) == 0x10)
+ name = "adm1024";
+ else if ((probeval[P_ff] & 0xf0) == 0x30)
+ name = "adm1023";
+ else if ((probeval[P_ff] & 0xf0) == 0x90)
+ name = "adm1022";
+ else
+ name = "adm1021";
+ } else if (probeval[P_3e] == 0xa1) {
+ /* Philips vendor code 0xa1 at 0x3e */
+ if ((probeval[P_3f] & 0xf0) == 0x20)
+ name = "ne1619"; /* adm1025 compat */
+ } else if (probeval[P_3e] == 0x01) {
+ /*
+ * Most newer National products use a vendor code at
+ * 0x3e of 0x01, and then 0x3f contains a product code
+ */
+ if (probeval[P_3f] == 0x49)
+ name = "lm99";
+ else if (probeval[P_3f] == 0x73)
+ name = "lm93";
+ else if (probeval[P_3f] == 0x33)
+ name = "lm90";
+ else if (probeval[P_3f] == 0x52)
+ name = "lm89";
+ else if (probeval[P_3f] == 0x17)
+ name = "lm86";
+ else if (probeval[P_3f] == 0x03) /* and higher? */
+ name = "lm81";
+ } else if (probeval[P_3e] == 0x02 && probeval[P_3f] == 0x6)
+ name = "lm87";
+
+ printf("addr 0x%x at %s:", addr, self->dv_xname);
+ for (i = 0; i < sizeof(probeval); i++)
+ if (probeval[i] != 0xff)
+ printf(" %02x=%02x", probereg[i], probeval[i]);
+ if (name)
+ printf(": %s", name);
+ printf("\n");
+
+ if (name) {
+ ia.ia_tag = iba->iba_tag;
+ ia.ia_addr = addr;
+ ia.ia_size = 1;
+ ia.ia_name = name;
+ ia.ia_compat = NULL;
+ config_found(self, &ia, iic_print);
+ }
+}
void
iic_scan(struct device *self, struct i2cbus_attach_args *iba)
@@ -91,16 +173,16 @@ iic_scan(struct device *self, struct i2cbus_attach_args *iba)
ic->ic_acquire_bus(ic->ic_cookie, I2C_F_POLL);
if (ic->ic_exec(ic->ic_cookie, I2C_OP_READ_WITH_STOP, addr,
&cmd, 1, NULL, 0, I2C_F_POLL) == 0) {
- printf("addr 0x%x at %s: ", addr, self->dv_xname);
- for (i = 0; i < sizeof(probe); i++) {
- cmd = probe[i];
+
+ for (i = 0; i < sizeof(probereg); i++) {
+ cmd = probereg[i];
+ probeval[i] = 0xff;
if (ic->ic_exec(ic->ic_cookie,
I2C_OP_READ_WITH_STOP, addr,
- &cmd, 1, &data, 1, I2C_F_POLL) == 0 &&
- data != 0xff)
- printf(" %02x=%02x", cmd, data);
+ &cmd, 1, &data, 1, I2C_F_POLL) == 0)
+ probeval[i] = data;
}
- printf("\n");
+ iic_probe(self, iba, addr);
}
ic->ic_release_bus(ic->ic_cookie, I2C_F_POLL);
}