/* $OpenBSD: i2c_scan.c,v 1.146 2019/12/16 19:17:04 claudio Exp $ */ /* * Copyright (c) 2005 Theo de Raadt * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * I2C bus scanning. We apologize in advance for the massive overuse of 0x. */ #include "ipmi.h" #include #include #include #define _I2C_PRIVATE #include #undef I2C_DEBUG #define I2C_VERBOSE #define MAX_IGNORE 8 u_int8_t ignore_addrs[MAX_IGNORE]; struct iicprobelist { u_int8_t start, end; }; /* * Addresses at which to probe for sensors. Skip address 0x4f, since * probing it seems to crash at least one Sony VAIO laptop. Only a * few chips can actually sit at that address, and vendors seem to * place those at other addresses, so this isn't a big loss. */ struct iicprobelist probe_addrs_sensor[] = { { 0x18, 0x1f }, { 0x20, 0x2f }, { 0x48, 0x4e }, { 0, 0 } }; /* * Addresses at which to probe for eeprom devices. */ struct iicprobelist probe_addrs_eeprom[] = { { 0x50, 0x57 }, { 0, 0 } }; char *iic_probe_sensor(struct device *, u_int8_t); char *iic_probe_eeprom(struct device *, u_int8_t); #define PFLAG_SENSOR 1 static struct { struct iicprobelist *pl; char *(*probe)(struct device *, u_int8_t); int flags; } probes[] = { { probe_addrs_sensor, iic_probe_sensor, PFLAG_SENSOR }, { probe_addrs_eeprom, iic_probe_eeprom, 0 }, { NULL, NULL } }; /* * Some Maxim 1617 clones MAY NOT even read cmd 0xfc! When it is * read, they will power-on-reset. Their default condition * (control register bit 0x80) therefore will be that they assert * /ALERT for the 5 potential errors that may occur. One of those * errors is that the external temperature diode is missing. This * is unfortunately a common choice of system designers, except * suddenly now we get a /ALERT, which may on some chipsets cause * us to receive an entirely unexpected SMI .. and then an NMI. * * As we probe each device, if we hit something which looks suspiciously * like it may potentially be a 1617 or clone, we immediately set this * variable to avoid reading that register offset. */ int skip_fc; static i2c_tag_t probe_ic; static u_int8_t probe_addr; static u_int8_t probe_val[256]; void iicprobeinit(struct i2cbus_attach_args *, u_int8_t); u_int8_t iicprobenc(u_int8_t); u_int8_t iicprobe(u_int8_t); u_int16_t iicprobew(u_int8_t); char *lm75probe(void); char *adm1032cloneprobe(u_int8_t); void iic_dump(struct device *, u_int8_t, char *); void iicprobeinit(struct i2cbus_attach_args *iba, u_int8_t addr) { probe_ic = iba->iba_tag; probe_addr = addr; memset(probe_val, 0xff, sizeof probe_val); } u_int8_t iicprobenc(u_int8_t cmd) { u_int8_t data; /* * If we think we are talking to an evil Maxim 1617 or clone, * avoid accessing this register because it is death. */ if (skip_fc && cmd == 0xfc) return (0xff); iic_acquire_bus(probe_ic, 0); if (iic_exec(probe_ic, I2C_OP_READ_WITH_STOP, probe_addr, &cmd, sizeof cmd, &data, sizeof data, 0) != 0) data = 0xff; iic_release_bus(probe_ic, 0); return (data); } u_int16_t iicprobew(u_int8_t cmd) { u_int16_t data; /* * If we think we are talking to an evil Maxim 1617 or clone, * avoid accessing this register because it is death. */ if (skip_fc && cmd == 0xfc) return (0xffff); iic_acquire_bus(probe_ic, 0); if (iic_exec(probe_ic, I2C_OP_READ_WITH_STOP, probe_addr, &cmd, sizeof cmd, &data, sizeof data, 0) != 0) data = 0xffff; iic_release_bus(probe_ic, 0); return betoh16(data); } u_int8_t iicprobe(u_int8_t cmd) { if (probe_val[cmd] != 0xff) return probe_val[cmd]; probe_val[cmd] = iicprobenc(cmd); return (probe_val[cmd]); } #define LM75TEMP 0x00 #define LM75CONF 0x01 #define LM75Thyst 0x02 #define LM75Tos 0x03 #define LM77Tlow 0x04 #define LM77Thigh 0x05 #define LM75TMASK 0xff80 /* 9 bits in temperature registers */ #define LM77TMASK 0xfff8 /* 13 bits in temperature registers */ /* * The LM75/LM75A/LM77 family are very hard to detect. Thus, we check * for all other possible chips first. These chips do not have an * ID register. They do have a few quirks though: * - on the LM75 and LM77, registers 0x06 and 0x07 return whatever * value was read before * - the LM75 lacks registers 0x04 and 0x05, so those act as above * - the LM75A returns 0xffff for registers 0x04, 0x05, 0x06 and 0x07 * - the chip registers loop every 8 registers * The downside is that we must read almost every register to guess * if this is an LM75, LM75A or LM77. */ char * lm75probe(void) { u_int16_t temp, thyst, tos, tlow, thigh, mask = LM75TMASK; u_int8_t conf; int i, echocount, ffffcount, score; int echoreg67, echoreg45, ffffreg67, ffffreg45; temp = iicprobew(LM75TEMP); /* * Sometimes the other probes can upset the chip, if we get 0xffff * the first time, try it once more. */ if (temp == 0xffff) temp = iicprobew(LM75TEMP); conf = iicprobenc(LM75CONF); thyst = iicprobew(LM75Thyst); tos = iicprobew(LM75Tos); /* totally bogus data */ if (conf == 0xff && temp == 0xffff && thyst == 0xffff) return (NULL); temp &= mask; thyst &= mask; tos &= mask; /* All values the same? Very unlikely */ if (temp == thyst && thyst == tos) return (NULL); #if notsure /* more register aliasing effects that indicate not a lm75 */ if ((temp >> 8) == conf) return (NULL); #endif /* * LM77/LM75 registers 6, 7 * echo whatever was read just before them from reg 0, 1, or 2 * * LM75A doesn't appear to do this, but does appear to reliably * return 0xffff */ for (i = 6, echocount = 2, ffffcount = 0; i <= 7; i++) { if ((iicprobew(LM75TEMP) & mask) != (iicprobew(i) & mask) || (iicprobew(LM75Thyst) & mask) != (iicprobew(i) & mask) || (iicprobew(LM75Tos) & mask) != (iicprobew(i) & mask)) echocount--; if (iicprobew(i) == 0xffff) ffffcount++; } /* Make sure either both registers echo, or neither does */ if (echocount == 1 || ffffcount == 1) return (NULL); echoreg67 = (echocount == 0) ? 0 : 1; ffffreg67 = (ffffcount == 0) ? 0 : 1; /* * LM75 has no registers 4 or 5, and they will act as echos too * * LM75A doesn't appear to do this either, but does appear to * reliably return 0xffff */ for (i = 4, echocount = 2, ffffcount = 0; i <= 5; i++) { if ((iicprobew(LM75TEMP) & mask) != (iicprobew(i) & mask) || (iicprobew(LM75Thyst) & mask) != (iicprobew(i) & mask) || (iicprobew(LM75Tos) & mask) != (iicprobew(i) & mask)) echocount--; if (iicprobew(i) == 0xffff) ffffcount++; } /* Make sure either both registers echo, or neither does */ if (echocount == 1 || ffffcount == 1) return (NULL); echoreg45 = (echocount == 0) ? 0 : 1; ffffreg45 = (ffffcount == 0) ? 0 : 1; /* * If we find that 4 and 5 are not echos, and don't return 0xffff * then based on whether the echo test of registers 6 and 7 * succeeded or not, we may have an LM77 */ if (echoreg45 == 0 && ffffreg45 == 0 && echoreg67 == 1) { mask = LM77TMASK; /* mask size changed, must re-read for the next checks */ thyst = iicprobew(LM75Thyst) & mask; tos = iicprobew(LM75Tos) & mask; tlow = iicprobew(LM77Tlow) & mask; thigh = iicprobew(LM77Thigh) & mask; } /* a real LM75/LM75A/LM77 repeats its registers.... */ for (i = 0x08; i <= 0xf8; i += 8) { if (conf != iicprobenc(LM75CONF + i) || thyst != (iicprobew(LM75Thyst + i) & mask) || tos != (iicprobew(LM75Tos + i) & mask)) return (NULL); /* * Check that the repeated registers 0x06 and 0x07 still * either echo or return 0xffff */ if (echoreg67 == 1) { tos = iicprobew(LM75Tos) & mask; if (tos != (iicprobew(0x06 + i) & mask) || tos != (iicprobew(0x07 + i) & mask)) return (NULL); } else if (ffffreg67 == 1) if (iicprobew(0x06 + i) != 0xffff || iicprobew(0x07 + i) != 0xffff) return (NULL); /* * Check that the repeated registers 0x04 and 0x05 still * either echo or return 0xffff. If they do neither, and * registers 0x06 and 0x07 echo, then we will be probing * for an LM77, so make sure those still repeat */ if (echoreg45 == 1) { tos = iicprobew(LM75Tos) & mask; if (tos != (iicprobew(LM77Tlow + i) & mask) || tos != (iicprobew(LM77Thigh + i) & mask)) return (NULL); } else if (ffffreg45 == 1) { if (iicprobew(LM77Tlow + i) != 0xffff || iicprobew(LM77Thigh + i) != 0xffff) return (NULL); } else if (echoreg67 == 1) if (tlow != (iicprobew(LM77Tlow + i) & mask) || thigh != (iicprobew(LM77Thigh + i) & mask)) return (NULL); } /* * Given that we now know how the first eight registers behave and * that this behaviour is consistently repeated, we can now use * the following table: * * echoreg67 | echoreg45 | ffffreg67 | ffffreg45 | chip * ----------+-----------+-----------+-----------+------ * 1 | 1 | 0 | 0 | LM75 * 1 | 0 | 0 | 0 | LM77 * 0 | 0 | 1 | 1 | LM75A */ /* Convert the various flags into a single score */ score = (echoreg67 << 3) + (echoreg45 << 2) + (ffffreg67 << 1) + ffffreg45; switch (score) { case 12: return ("lm75"); case 8: return ("lm77"); case 3: return ("lm75a"); default: #if defined(I2C_DEBUG) printf("lm75probe: unknown chip, scored %d\n", score); #endif /* defined(I2C_DEBUG) */ return (NULL); } } char * adm1032cloneprobe(u_int8_t addr) { if (addr == 0x18 || addr == 0x1a || addr == 0x29 || addr == 0x2b || addr == 0x4c || addr == 0x4e) { u_int8_t reg, val; int zero = 0, copy = 0; val = iicprobe(0x00); for (reg = 0x00; reg < 0x09; reg++) { if (iicprobe(reg) == 0xff) return (NULL); if (iicprobe(reg) == 0x00) zero++; if (val == iicprobe(reg)) copy++; } if (zero > 6 || copy > 6) return (NULL); val = iicprobe(0x09); for (reg = 0x0a; reg < 0xfc; reg++) { if (iicprobe(reg) != val) return (NULL); } /* 0xfe may be Maxim, or some other vendor */ if (iicprobe(0xfe) == 0x4d) return ("max1617"); /* * "xeontemp" is the name we choose for clone chips * which have all sorts of buggy bus interactions, such * as those we just probed. Why? * Intel is partly to blame for this situation. */ return ("xeontemp"); } return (NULL); } void iic_ignore_addr(u_int8_t addr) { int i; for (i = 0; i < sizeof(ignore_addrs); i++) if (ignore_addrs[i] == 0) { ignore_addrs[i] = addr; return; } } #ifdef I2C_VERBOSE void iic_dump(struct device *dv, u_int8_t addr, char *name) { static u_int8_t iicvalcnt[256]; u_int8_t val, val2, max; int i, cnt = 0; /* * Don't bother printing the most often repeated register * value, since it is often weird devices that respond * incorrectly, busted controller driver, or in the worst * case, it in mosts cases, the value 0xff. */ bzero(iicvalcnt, sizeof iicvalcnt); val = iicprobe(0); iicvalcnt[val]++; for (i = 1; i <= 0xff; i++) { val2 = iicprobe(i); iicvalcnt[val2]++; if (val == val2) cnt++; } for (val = max = i = 0; i <= 0xff; i++) if (max < iicvalcnt[i]) { max = iicvalcnt[i]; val = i; } if (cnt == 255) return; printf("%s: addr 0x%x", dv->dv_xname, addr); for (i = 0; i <= 0xff; i++) { if (iicprobe(i) != val) printf(" %02x=%02x", i, iicprobe(i)); } printf(" words"); for (i = 0; i < 8; i++) printf(" %02x=%04x", i, iicprobew(i)); if (name) printf(": %s", name); printf("\n"); } #endif /* I2C_VERBOSE */ char * iic_probe_sensor(struct device *self, u_int8_t addr) { char *name = NULL; skip_fc = 0; /* * Many I2C/SMBus devices use register 0x3e as a vendor ID * register. */ switch (iicprobe(0x3e)) { case 0x01: /* National Semiconductor */ /* * Some newer National products use a vendor code at * 0x3e of 0x01, and then 0x3f contains a product code * But some older products are missing a product code, * and contain who knows what in that register. We assume * that some employee was smart enough to keep the numbers * unique. */ if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && (iicprobe(0x3f) == 0x73 || iicprobe(0x3f) == 0x72) && iicprobe(0x00) == 0x00) name = "lm93"; /* product 0x72 is the prototype */ else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && iicprobe(0x3f) == 0x68) name = "lm96000"; /* adt7460 compat? */ else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && (iicprobe(0x3f) == 0x60 || iicprobe(0x3f) == 0x62)) name = "lm85"; /* lm85C/B == adt7460 compat */ else if ((addr & 0x7c) == 0x2c && /* addr 0b01011xx */ iicprobe(0x48) == addr && (iicprobe(0x3f) == 0x03 || iicprobe(0x3f) == 0x04) && (iicprobe(0x40) & 0x80) == 0x00) name = "lm81"; break; case 0x02: /* National Semiconductor? */ if ((iicprobe(0x3f) & 0xfc) == 0x04) name = "lm87"; /* complete check */ break; case 0x23: /* Analog Devices? */ if (iicprobe(0x48) == addr && (iicprobe(0x40) & 0x80) == 0x00 && (addr & 0x7c) == 0x2c) name = "adm9240"; /* lm87 clone */ break; case 0x41: /* Analog Devices */ /* * Newer chips have a valid 0x3d product number, while * older ones sometimes encoded the product into the * upper half of the "step register" at 0x3f. */ if ((addr == 0x2c || addr == 0x2e || addr == 0x2f) && iicprobe(0x3d) == 0x70) name = "adt7470"; else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && iicprobe(0x3d) == 0x76) name = "adt7476"; /* or adt7476a */ else if (addr == 0x2e && iicprobe(0x3d) == 0x75) name = "adt7475"; else if (iicprobe(0x3d) == 0x27 && (iicprobe(0x3f) == 0x60 || iicprobe(0x3f) == 0x6a)) name = "adm1027"; /* or adt7463 */ else if (iicprobe(0x3d) == 0x27 && (iicprobe(0x3f) == 0x62 || iicprobe(0x3f) == 0x6a)) name = "adt7460"; /* complete check */ else if ((addr == 0x2c || addr == 0x2e) && iicprobe(0x3d) == 0x62 && iicprobe(0x3f) == 0x04) name = "adt7462"; else if (addr == 0x4c && iicprobe(0x3d) == 0x66 && iicprobe(0x3f) == 0x02) name = "adt7466"; else if (addr == 0x2e && iicprobe(0x3d) == 0x68 && (iicprobe(0x3f) & 0xf0) == 0x70) name = "adt7467"; /* or adt7468 */ else if (iicprobe(0x3d) == 0x33 && iicprobe(0x3f) == 0x02) name = "adm1033"; else if (iicprobe(0x3d) == 0x34 && iicprobe(0x3f) == 0x02) name = "adm1034"; else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && iicprobe(0x3d) == 0x30 && (iicprobe(0x01) & 0x80) == 0x00 && (iicprobe(0x0d) & 0x70) == 0x00 && (iicprobe(0x0e) & 0x70) == 0x00) /* * Revision 3 seems to be an adm1031 with * remote diode 2 shorted. Therefore we * cannot assume the reserved/unused bits of * register 0x03 and 0x06 are set to zero. */ name = "adm1030"; /* complete check */ else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && iicprobe(0x3d) == 0x31 && (iicprobe(0x01) & 0x80) == 0x00 && (iicprobe(0x0d) & 0x70) == 0x00 && (iicprobe(0x0e) & 0x70) == 0x00 && (iicprobe(0x0f) & 0x70) == 0x00) name = "adm1031"; /* complete check */ else if ((addr & 0x7c) == 0x2c && /* addr 0b01011xx */ (iicprobe(0x3f) & 0xf0) == 0x20 && (iicprobe(0x40) & 0x80) == 0x00 && (iicprobe(0x41) & 0xc0) == 0x00 && (iicprobe(0x42) & 0xbc) == 0x00) name = "adm1025"; /* complete check */ else if ((addr & 0x7c) == 0x2c && /* addr 0b01011xx */ (iicprobe(0x3f) & 0xf0) == 0x10 && (iicprobe(0x40) & 0x80) == 0x00) name = "adm1024"; /* complete check */ else if ((iicprobe(0xff) & 0xf0) == 0x30) name = "adm1023"; else if (addr == 0x2e && (iicprobe(0x3f) & 0xf0) == 0xd0 && (iicprobe(0x40) & 0x80) == 0x00) name = "adm1028"; /* adm1022 clone? */ else if ((addr == 0x2c || addr == 0x2e || addr == 0x2f) && (iicprobe(0x3f) & 0xf0) == 0xc0 && (iicprobe(0x40) & 0x80) == 0x00) name = "adm1022"; break; case 0x49: /* Texas Instruments */ if ((addr == 0x2c || addr == 0x2e || addr == 0x2f) && (iicprobe(0x3f) & 0xf0) == 0xc0 && (iicprobe(0x40) & 0x80) == 0x00) name = "thmc50"; /* adm1022 clone */ break; case 0x55: /* SMSC */ if ((addr & 0x7c) == 0x2c && /* addr 0b01011xx */ iicprobe(0x3f) == 0x20 && (iicprobe(0x47) & 0x70) == 0x00 && (iicprobe(0x49) & 0xfe) == 0x80) name = "47m192"; /* adm1025 compat */ break; case 0x5c: /* SMSC */ if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && (iicprobe(0x3f) == 0x69)) name = "sch5027"; else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && (iicprobe(0x3f) & 0xf0) == 0x60) name = "emc6d100"; /* emc6d101, emc6d102, emc6d103 */ else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && (iicprobe(0x3f) & 0xf0) == 0x80) name = "sch5017"; else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && (iicprobe(0x3f) & 0xf0) == 0xb0) name = "emc6w201"; break; case 0x61: /* Andigilog */ if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && iicprobe(0x3f) == 0x69 && iicprobe(0x22) >= 0xaf && /* Vdd */ (iicprobe(0x09) & 0xbf) == 0x00 && iicprobe(0x0f) == 0x00 && (iicprobe(0x40) & 0xf0) == 0x00) name = "asc7611"; else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && iicprobe(0x3f) == 0x6c && iicprobe(0x22) >= 0xae) /* Vdd */ name = "asc7621"; break; case 0xa1: /* Philips */ if ((iicprobe(0x3f) & 0xf0) == 0x20 && (iicprobe(0x40) & 0x80) == 0x00 && (iicprobe(0x41) & 0xc0) == 0x00 && (iicprobe(0x42) & 0xbc) == 0x00) name = "ne1619"; /* adm1025 compat */ break; case 0xda: /* Dallas Semiconductor */ if (iicprobe(0x3f) == 0x01 && iicprobe(0x48) == addr && (iicprobe(0x40) & 0x80) == 0x00) name = "ds1780"; /* lm87 clones */ break; } switch (iicprobe(0x4e)) { case 0x41: /* Analog Devices */ if ((addr == 0x48 || addr == 0x4a || addr == 0x4b) && (iicprobe(0x4d) == 0x03 || iicprobe(0x4d) == 0x08 || iicprobe(0x4d) == 0x07)) name = "adt7516"; /* adt7517, adt7519 */ break; } switch (iicprobe(0xfe)) { case 0x01: /* National Semiconductor */ if (addr == 0x4c && iicprobe(0xff) == 0x41 && (iicprobe(0x03) & 0x18) == 0 && iicprobe(0x04) <= 0x0f && (iicprobe(0xbf) & 0xf8) == 0) name = "lm63"; else if (addr == 0x4c && iicprobe(0xff) == 0x11 && (iicprobe(0x03) & 0x2a) == 0 && iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0) name = "lm86"; else if (addr == 0x4c && iicprobe(0xff) == 0x31 && (iicprobe(0x03) & 0x2a) == 0 && iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0) name = "lm89"; /* or lm99 */ else if (addr == 0x4d && iicprobe(0xff) == 0x34 && (iicprobe(0x03) & 0x2a) == 0 && iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0) name = "lm89-1"; /* or lm99-1 */ else if (addr == 0x4c && iicprobe(0xff) == 0x21 && (iicprobe(0x03) & 0x2a) == 0 && iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0) name = "lm90"; break; case 0x23: /* Genesys Logic? */ if ((addr == 0x4c) && (iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x08) /* * Genesys Logic doesn't make the datasheet * for the GL523SM publically available, so * the checks above are nothing more than a * (conservative) educated guess. */ name = "gl523sm"; break; case 0x41: /* Analog Devices */ if ((addr == 0x4c || addr == 0x4d) && iicprobe(0xff) == 0x51 && (iicprobe(0x03) & 0x1f) == 0x04 && iicprobe(0x04) <= 0x0a) { /* If not in adm1032 compatibility mode. */ name = "adt7461"; } else if ((addr == 0x18 || addr == 0x19 || addr == 0x1a || addr == 0x29 || addr == 0x2a || addr == 0x2b || addr == 0x4c || addr == 0x4d || addr == 0x4e) && (iicprobe(0xff) & 0xf0) == 0x00 && (iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x07) { name = "adm1021"; skip_fc = 1; } else if ((addr == 0x18 || addr == 0x19 || addr == 0x1a || addr == 0x29 || addr == 0x2a || addr == 0x2b || addr == 0x4c || addr == 0x4d || addr == 0x4e) && (iicprobe(0xff) & 0xf0) == 0x30 && (iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x07) { name = "adm1023"; /* or adm1021a */ skip_fc = 1; } else if ((addr == 0x4c || addr == 0x4d || addr == 0x4e) && (iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x0a) { name = "adm1032"; /* or adm1020 */ skip_fc = 1; } break; case 0x47: /* Global Mixed-mode Technology */ if (addr == 0x4c && iicprobe(0xff) == 0x01 && (iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x08) name = "g781"; if (addr == 0x4d && iicprobe(0xff) == 0x03 && (iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x08) name = "g781-1"; break; case 0x4d: /* Maxim */ if ((addr == 0x18 || addr == 0x19 || addr == 0x1a || addr == 0x29 || addr == 0x2a || addr == 0x2b || addr == 0x4c || addr == 0x4d || addr == 0x4e) && iicprobe(0xff) == 0x08 && (iicprobe(0x02) & 0x03) == 0 && (iicprobe(0x03) & 0x07) == 0 && iicprobe(0x04) <= 0x08) name = "max6690"; else if ((addr == 0x4c || addr == 0x4d || addr == 0x4e) && iicprobe(0xff) == 0x59 && (iicprobe(0x03) & 0x1f) == 0 && iicprobe(0x04) <= 0x07) name = "max6646"; /* max6647/8/9, max6692 */ else if ((addr == 0x4c || addr == 0x4d || addr == 0x4e) && (iicprobe(0x02) & 0x2b) == 0 && (iicprobe(0x03) & 0x0f) == 0 && iicprobe(0x04) <= 0x09) { name = "max6657"; /* max6658, max6659 */ skip_fc = 1; } else if ((addr >= 0x48 && addr <= 0x4f) && (iicprobe(0x02) & 0x2b) == 0 && (iicprobe(0x03) & 0x0f) == 0) name = "max6642"; break; case 0x55: /* Texas Instruments */ if (addr == 0x4c && iicprobe(0xff) == 0x11 && (iicprobe(0x03) & 0x1b) == 0x00 && (iicprobe(0x04) & 0xf0) == 0x00 && (iicprobe(0x10) & 0x0f) == 0x00 && (iicprobe(0x13) & 0x0f) == 0x00 && (iicprobe(0x14) & 0x0f) == 0x00 && (iicprobe(0x15) & 0x0f) == 0x00 && (iicprobe(0x16) & 0x0f) == 0x00 && (iicprobe(0x17) & 0x0f) == 0x00) name = "tmp401"; break; case 0xa1: if ((addr >= 0x48 && addr <= 0x4f) && iicprobe(0xff) == 0x00 && (iicprobe(0x03) & 0xf8) == 0x00 && iicprobe(0x04) <= 0x09) { name = "sa56004x"; /* NXP sa56004x */ skip_fc = 1; } break; } if (addr == iicprobe(0x48) && ((iicprobe(0x4f) == 0x5c && (iicprobe(0x4e) & 0x80)) || (iicprobe(0x4f) == 0xa3 && !(iicprobe(0x4e) & 0x80)))) { /* * We could toggle 0x4e bit 0x80, then re-read 0x4f to * see if the value changes to 0xa3 (indicating Winbond). * But we are trying to avoid writes. */ if ((iicprobe(0x4e) & 0x07) == 0) { switch (iicprobe(0x58)) { case 0x10: case 0x11: /* rev 2? */ name = "w83781d"; break; case 0x21: name = "w83627hf"; break; case 0x30: name = "w83782d"; break; case 0x31: name = "as99127f"; /* rev 2 */ break; case 0x40: name = "w83783s"; break; case 0x71: name = "w83791d"; break; case 0x72: name = "w83791sd"; break; case 0x7a: name = "w83792d"; break; case 0xc1: name = "w83627dhg"; break; } } else { /* * The BIOS left the chip in a non-zero * register bank. Assume it's a W83781D and * let lm(4) sort out the real model. */ name = "w83781d"; } } else if (addr == (iicprobe(0xfc) & 0x7f) && iicprobe(0xfe) == 0x79 && iicprobe(0xfb) == 0x51 && ((iicprobe(0xfd) == 0x5c && (iicprobe(0x00) & 0x80)) || (iicprobe(0xfd) == 0xa3 && !(iicprobe(0x00) & 0x80)))) { /* * We could toggle 0x00 bit 0x80, then re-read 0xfd to * see if the value changes to 0xa3 (indicating Nuvoton). * But we are trying to avoid writes. */ name = "w83795g"; } else if (addr == iicprobe(0x4a) && iicprobe(0x4e) == 0x50 && iicprobe(0x4c) == 0xa3 && iicprobe(0x4d) == 0x5c) { name = "w83l784r"; } else if (addr == 0x2d && iicprobe(0x4e) == 0x60 && iicprobe(0x4c) == 0xa3 && iicprobe(0x4d) == 0x5c) { name = "w83l785r"; } else if (addr == 0x2e && iicprobe(0x4e) == 0x70 && iicprobe(0x4c) == 0xa3 && iicprobe(0x4d) == 0x5c) { name = "w83l785ts-l"; } else if (addr >= 0x2c && addr <= 0x2f && ((iicprobe(0x00) & 0x07) != 0x0 || ((iicprobe(0x00) & 0x07) == 0x0 && addr * 2 == iicprobe(0x0b) && (iicprobe(0x0c) & 0x40) && !(iicprobe(0x0c) & 0x04))) && iicprobe(0x0e) == 0x7b && (iicprobe(0x0f) & 0xf0) == 0x10 && ((iicprobe(0x0d) == 0x5c && (iicprobe(0x00) & 0x80)) || (iicprobe(0x0d) == 0xa3 && !(iicprobe(0x00) & 0x80)))) { name = "w83793g"; } else if (addr >= 0x28 && addr <= 0x2f && iicprobe(0x4f) == 0x12 && (iicprobe(0x4e) & 0x80)) { /* * We could toggle 0x4e bit 0x80, then re-read 0x4f to * see if the value changes to 0xc3 (indicating ASUS). * But we are trying to avoid writes. */ if (iicprobe(0x58) == 0x31) name = "as99127f"; /* rev 1 */ } else if ((addr == 0x2d || addr == 0x2e) && addr * 2 == iicprobe(0x04) && iicprobe(0x5d) == 0x19 && iicprobe(0x5e) == 0x34 && iicprobe(0x5a) == 0x03 && iicprobe(0x5b) == 0x06) { name = "f75375"; /* Fintek */ } else if (addr == 0x2d && ((iicprobe(0x4f) == 0x06 && (iicprobe(0x4e) & 0x80)) || (iicprobe(0x4f) == 0x94 && !(iicprobe(0x4e) & 0x80)))) { /* * We could toggle 0x4e bit 0x80, then re-read 0x4f to * see if the value changes to 0x94 (indicating ASUS). * But we are trying to avoid writes. * * NB. we won't match if the BIOS has selected a non-zero * register bank (set via 0x4e). We could select bank 0 so * we see the right registers, but that would require a * write. In general though, we bet no BIOS would leave us * in the wrong state. */ if ((iicprobe(0x58) & 0x7f) == 0x31 && (iicprobe(0x4e) & 0xf) == 0x00) name = "asb100"; } else if ((addr == 0x2c || addr == 0x2d) && iicprobe(0x00) == 0x80 && (iicprobe(0x01) == 0x00 || iicprobe(0x01) == 0x80) && iicprobe(0x02) == 0x00 && (iicprobe(0x03) & 0x83) == 0x00 && (iicprobe(0x0f) & 0x07) == 0x00 && (iicprobe(0x11) & 0x80) == 0x00 && (iicprobe(0x12) & 0x80) == 0x00) { /* * The GL518SM is really crappy. It has both byte and * word registers, and reading a word register with a * byte read command will make the device crap out and * hang the bus. This has nasty consequences on some * machines, like preventing warm reboots. The word * registers are 0x07 through 0x0c, so make sure the * checks above don't access those registers. We * don't want to do this check right up front though * since this chip is somewhat hard to detect (which * is why we check for every single fixed bit it has). */ name = "gl518sm"; } else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) && iicprobe(0x16) == 0x41 && ((iicprobe(0x17) & 0xf0) == 0x40)) { name = "adm1026"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1131 && (iicprobew(0x07) & 0xfffc) == 0xa200) { name = "se97"; /* or se97b */ } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1131 && (iicprobew(0x07) & 0xfffc) == 0xa100 && (iicprobew(0x00) & 0xfff0) == 0x0010) { name = "se98"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x004d && iicprobew(0x07) == 0x3e00 && (iicprobew(0x00) & 0xffe0) == 0x0000) { name = "max6604"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 && (iicprobew(0x07) & 0xfffc) == 0x0200 && (iicprobew(0x00) & 0xffe0) == 0x0000) { name = "mcp9804"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 && (iicprobew(0x07) & 0xff00) == 0x0000 && (iicprobew(0x00) & 0xffe0) == 0x0000) { name = "mcp9805"; /* or mcp9843 */ } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 && (iicprobew(0x07) & 0xfffc) == 0x2000 && (iicprobew(0x00) & 0xffe0) == 0x0000) { name = "mcp98242"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 && (iicprobew(0x07) & 0xff00) == 0x2100 && (iicprobew(0x00) & 0xff00) == 0x0000) { name = "mcp98243"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 && (iicprobew(0x07) & 0xfffc) == 0x2200 && (iicprobew(0x00) & 0xff00) == 0x0000) { name = "mcp98244"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x11d4 && iicprobew(0x07) == 0x0800 && iicprobew(0x00) == 0x001d) { name = "adt7408"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a && (iicprobew(0x07) & 0xfffe) == 0x0000 && (iicprobew(0x00) == 0x002d || iicprobew(0x00) == 0x002f)) { name = "stts424e02"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a && (iicprobew(0x07) & 0xfffe) == 0x0300 && (iicprobew(0x00) == 0x006f)) { name = "stts2002"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a && (iicprobew(0x07) & 0xffff) == 0x2201 && (iicprobew(0x00) == 0x00ef)) { name = "stts2004"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a && (iicprobew(0x07) & 0xffff) == 0x0200 && (iicprobew(0x00) == 0x006f)) { name = "stts3000"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a && (iicprobew(0x07) & 0xffff) == 0x0101 && (iicprobew(0x00) == 0x002d || iicprobew(0x00) == 0x002f)) { name = "stts424"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1b09 && (iicprobew(0x07) & 0xffe0) == 0x0800 && (iicprobew(0x00) & 0x001f) == 0x001f) { name = "cat34ts02"; /* or cat6095, prod 0x0813 */ } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1b09 && (iicprobew(0x07) & 0xffff) == 0x0a00 && (iicprobew(0x00) & 0x001f) == 0x001f) { name = "cat34ts02c"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1b09 && (iicprobew(0x07) & 0xffff) == 0x2200 && (iicprobew(0x00) == 0x007f)) { name = "cat34ts04"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 && (iicprobew(0x07) & 0xffff) == 0x2903 && (iicprobew(0x00) == 0x004f)) { name = "ts3000b3"; /* or tse2002b3 */ } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 && (iicprobew(0x07) & 0xffff) == 0x2912 && (iicprobew(0x00) == 0x006f)) { name = "ts3000gb2"; /* or tse2002gb2 */ } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 && (iicprobew(0x07) & 0xffff) == 0x2913 && (iicprobew(0x00) == 0x0077)) { name = "ts3000gb0"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 && (iicprobew(0x07) & 0xffff) == 0x3001 && (iicprobew(0x00) == 0x006f)) { name = "ts3001gb2"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 && (iicprobew(0x07) & 0xffff) == 0x2214 && (iicprobew(0x00) == 0x00ff)) { name = "tse2004gb2"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x001f && (iicprobew(0x07) & 0xffff) == 0x8201 && (iicprobew(0x00) & 0xff00) == 0x0000) { name = "at30ts00"; /* or at30tse002 */ } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1114 && (iicprobew(0x07) & 0xffff) == 0x2200 && (iicprobew(0x00) & 0xff00) == 0x0000) { name = "at30tse004"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1c68 && (iicprobew(0x07) & 0xffff) == 0x2201 && (iicprobew(0x00) & 0xff00) == 0x0000) { name = "gt30ts00"; } else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x132d && (iicprobew(0x07) & 0xffff) == 0x3300 && (iicprobew(0x00) & 0x001f) == 0x001f) { name = "gt34ts02"; } else if ((addr & 0x7e) == 0x1c && iicprobe(0x0f) == 0x3b && (iicprobe(0x21) & 0x60) == 0x00 && iicprobe(0x0f) == iicprobe(0x8f) && /* registers address is 7 bits */ iicprobe(0x20) == iicprobe(0xa0) && iicprobe(0x21) == iicprobe(0xa1) && iicprobe(0x22) == iicprobe(0xa2) && iicprobe(0x07) == 0x00) { /* 0x00 to 0x0e are reserved */ name = "lis331dl"; } else if (name == NULL && (addr & 0x78) == 0x48) { /* addr 0b1001xxx */ name = lm75probe(); } #if 0 /* * XXX This probe needs to be improved; the driver does some * dangerous writes. */ if (name == NULL && (addr & 0x7c) == 0x48 && /* addr 0b1001xxx */ (iicprobew(0xaa) & 0x0007) == 0x0000 && (iicprobew(0xa1) & 0x0007) == 0x0000 && (iicprobew(0xa2) & 0x0007) == 0x0000 && (iicprobe(0xac) & 0x10) == 0x00) { if ((iicprobe(0xac) & 0x7e) == 0x0a && iicprobe(0xab) == 0x00 && iicprobe(0xa8) == 0x00) name = "ds1624"; else if ((iicprobe(0xac) & 0x7e) == 0x0c) name = "ds1631"; /* terrible probe */ else if ((iicprobe(0xac) & 0x2e) == 0x2e) name = "ds1721"; /* terrible probe */ } #endif if (name == NULL && (addr & 0xf8) == 0x28 && iicprobe(0x48) == addr && (iicprobe(0x00) & 0x90) == 0x10 && iicprobe(0x58) == 0x90) { if (iicprobe(0x5b) == 0x12) name = "it8712"; else if (iicprobe(0x5b) == 0x00) name = "it8712f-a"; /* sis950 too */ } if (name == NULL && iicprobe(0x48) == addr && (iicprobe(0x40) & 0x80) == 0x00 && iicprobe(0x58) == 0xac) name = "mtp008"; if (name == NULL) { name = adm1032cloneprobe(addr); if (name) skip_fc = 1; } return (name); } char * iic_probe_eeprom(struct device *self, u_int8_t addr) { u_int8_t type; char *name = NULL; type = iicprobe(0x02); /* limit to SPD types seen in the wild */ if (type < 4 || type > 16) return (name); /* more matching in driver(s) */ name = "eeprom"; return (name); } void iic_scan(struct device *self, struct i2cbus_attach_args *iba) { i2c_tag_t ic = iba->iba_tag; struct i2c_attach_args ia; struct iicprobelist *pl; u_int8_t cmd = 0, addr; char *name; int i, j, k; bzero(ignore_addrs, sizeof(ignore_addrs)); for (i = 0; probes[i].probe; i++) { #if NIPMI > 0 extern int ipmi_enabled; if ((probes[i].flags & PFLAG_SENSOR) && ipmi_enabled) { printf("%s: skipping sensors to avoid ipmi0 interactions\n", self->dv_xname); continue; } #endif pl = probes[i].pl; for (j = 0; pl[j].start && pl[j].end; j++) { for (addr = pl[j].start; addr <= pl[j].end; addr++) { for (k = 0; k < sizeof(ignore_addrs); k++) if (ignore_addrs[k] == addr) break; if (k < sizeof(ignore_addrs)) continue; /* Perform RECEIVE BYTE command */ iic_acquire_bus(ic, 0); if (iic_exec(ic, I2C_OP_READ_WITH_STOP, addr, &cmd, sizeof cmd, NULL, 0, 0) == 0) { iic_release_bus(ic, 0); /* Some device exists */ iicprobeinit(iba, addr); name = (*probes[i].probe)(self, addr); #ifndef I2C_VERBOSE if (name == NULL) name = "unknown"; #endif /* !I2C_VERBOSE */ if (name) { memset(&ia, 0, sizeof(ia)); ia.ia_tag = iba->iba_tag; ia.ia_addr = addr; ia.ia_size = 1; ia.ia_name = name; if (config_found(self, &ia, iic_print)) continue; } #ifdef I2C_VERBOSE if ((probes[i].flags & PFLAG_SENSOR)) iic_dump(self, addr, name); #endif /* I2C_VERBOSE */ } else iic_release_bus(ic, 0); } } } }