xref: /openbsd-src/sys/dev/i2c/i2c_scan.c (revision 9593dc34da13a12012033a17061c846c208061c2)
1*9593dc34Smglocker /*	$OpenBSD: i2c_scan.c,v 1.147 2024/09/04 07:54:52 mglocker Exp $	*/
21165b4a3Sgrange 
31165b4a3Sgrange /*
44de9e267Sderaadt  * Copyright (c) 2005 Theo de Raadt <deraadt@openbsd.org>
51165b4a3Sgrange  *
61165b4a3Sgrange  * Permission to use, copy, modify, and distribute this software for any
71165b4a3Sgrange  * purpose with or without fee is hereby granted, provided that the above
81165b4a3Sgrange  * copyright notice and this permission notice appear in all copies.
91165b4a3Sgrange  *
101165b4a3Sgrange  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
111165b4a3Sgrange  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
121165b4a3Sgrange  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
131165b4a3Sgrange  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
141165b4a3Sgrange  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
151165b4a3Sgrange  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
161165b4a3Sgrange  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
171165b4a3Sgrange  */
181165b4a3Sgrange 
191165b4a3Sgrange /*
20a031840aSderaadt  * I2C bus scanning.  We apologize in advance for the massive overuse of 0x.
211165b4a3Sgrange  */
221165b4a3Sgrange 
232349585bSderaadt #include "ipmi.h"
242349585bSderaadt 
251165b4a3Sgrange #include <sys/param.h>
261165b4a3Sgrange #include <sys/systm.h>
27941c1a56Sderaadt #include <sys/device.h>
281165b4a3Sgrange 
291165b4a3Sgrange #define _I2C_PRIVATE
301165b4a3Sgrange #include <dev/i2c/i2cvar.h>
311165b4a3Sgrange 
32ad90345aSderaadt #undef I2C_DEBUG
33f5940ae5Sjsg #define I2C_VERBOSE
3400cbb269Sderaadt 
3522ef5474Sderaadt #define MAX_IGNORE 8
3622ef5474Sderaadt u_int8_t ignore_addrs[MAX_IGNORE];
3722ef5474Sderaadt 
3822ef5474Sderaadt struct iicprobelist {
3922ef5474Sderaadt 	u_int8_t start, end;
4022ef5474Sderaadt };
4147098ca3Sderaadt 
42cb54b910Skettenis /*
43cb54b910Skettenis  * Addresses at which to probe for sensors.  Skip address 0x4f, since
44cb54b910Skettenis  * probing it seems to crash at least one Sony VAIO laptop.  Only a
45cb54b910Skettenis  * few chips can actually sit at that address, and vendors seem to
46cb54b910Skettenis  * place those at other addresses, so this isn't a big loss.
47cb54b910Skettenis  */
4822ef5474Sderaadt struct iicprobelist probe_addrs_sensor[] = {
49a7a203e0Sderaadt 	{ 0x18, 0x1f },
50941c1a56Sderaadt 	{ 0x20, 0x2f },
5122ef5474Sderaadt 	{ 0x48, 0x4e },
5222ef5474Sderaadt 	{ 0, 0 }
531165b4a3Sgrange };
541165b4a3Sgrange 
5522ef5474Sderaadt /*
5622ef5474Sderaadt  * Addresses at which to probe for eeprom devices.
5722ef5474Sderaadt  */
5822ef5474Sderaadt struct iicprobelist probe_addrs_eeprom[] = {
5922ef5474Sderaadt 	{ 0x50, 0x57 },
6022ef5474Sderaadt 	{ 0, 0 }
6122ef5474Sderaadt };
6222ef5474Sderaadt 
631c658e45Scnst char 	*iic_probe_sensor(struct device *, u_int8_t);
641c658e45Scnst char	*iic_probe_eeprom(struct device *, u_int8_t);
6522ef5474Sderaadt 
662349585bSderaadt #define PFLAG_SENSOR	1
6722ef5474Sderaadt static struct {
6822ef5474Sderaadt 	struct iicprobelist *pl;
691c658e45Scnst 	char	*(*probe)(struct device *, u_int8_t);
702349585bSderaadt 	int	flags;
7122ef5474Sderaadt } probes[] = {
722349585bSderaadt 	{ probe_addrs_sensor, iic_probe_sensor, PFLAG_SENSOR },
732349585bSderaadt 	{ probe_addrs_eeprom, iic_probe_eeprom, 0 },
7422ef5474Sderaadt 	{ NULL, NULL }
7522ef5474Sderaadt };
76b8fabd7dSderaadt 
77e616dcecSderaadt /*
78e616dcecSderaadt  * Some Maxim 1617 clones MAY NOT even read cmd 0xfc!  When it is
79e616dcecSderaadt  * read, they will power-on-reset.  Their default condition
80e616dcecSderaadt  * (control register bit 0x80) therefore will be that they assert
81e616dcecSderaadt  * /ALERT for the 5 potential errors that may occur.  One of those
82e616dcecSderaadt  * errors is that the external temperature diode is missing.  This
83e616dcecSderaadt  * is unfortunately a common choice of system designers, except
84e616dcecSderaadt  * suddenly now we get a /ALERT, which may on some chipsets cause
85e616dcecSderaadt  * us to receive an entirely unexpected SMI .. and then an NMI.
86e616dcecSderaadt  *
87e616dcecSderaadt  * As we probe each device, if we hit something which looks suspiciously
88e616dcecSderaadt  * like it may potentially be a 1617 or clone, we immediately set this
89e616dcecSderaadt  * variable to avoid reading that register offset.
90e616dcecSderaadt  */
91e616dcecSderaadt int	skip_fc;
92e616dcecSderaadt 
933a561bd4Sderaadt static i2c_tag_t probe_ic;
943a561bd4Sderaadt static u_int8_t probe_addr;
953a561bd4Sderaadt static u_int8_t probe_val[256];
963a561bd4Sderaadt 
9724b22cd5Sderaadt void		iicprobeinit(struct i2cbus_attach_args *, u_int8_t);
9824b22cd5Sderaadt u_int8_t	iicprobenc(u_int8_t);
9924b22cd5Sderaadt u_int8_t	iicprobe(u_int8_t);
10024b22cd5Sderaadt u_int16_t	iicprobew(u_int8_t);
101010c3e6aSderaadt char		*lm75probe(void);
1025f31ae5bSkettenis char		*adm1032cloneprobe(u_int8_t);
103ad90345aSderaadt void		iic_dump(struct device *, u_int8_t, char *);
1043a561bd4Sderaadt 
10524b22cd5Sderaadt void
10624b22cd5Sderaadt iicprobeinit(struct i2cbus_attach_args *iba, u_int8_t addr)
1073a561bd4Sderaadt {
1083a561bd4Sderaadt 	probe_ic = iba->iba_tag;
1093a561bd4Sderaadt 	probe_addr = addr;
1103a561bd4Sderaadt 	memset(probe_val, 0xff, sizeof probe_val);
1113a561bd4Sderaadt }
1123a561bd4Sderaadt 
11324b22cd5Sderaadt u_int8_t
11424b22cd5Sderaadt iicprobenc(u_int8_t cmd)
1153a561bd4Sderaadt {
1163a561bd4Sderaadt 	u_int8_t data;
1173a561bd4Sderaadt 
118e616dcecSderaadt 	/*
119e616dcecSderaadt 	 * If we think we are talking to an evil Maxim 1617 or clone,
120e616dcecSderaadt 	 * avoid accessing this register because it is death.
121e616dcecSderaadt 	 */
122e616dcecSderaadt 	if (skip_fc && cmd == 0xfc)
123e616dcecSderaadt 		return (0xff);
124a5d919cdSgrange 	iic_acquire_bus(probe_ic, 0);
125643d52faSgrange 	if (iic_exec(probe_ic, I2C_OP_READ_WITH_STOP,
12691eacc75Sderaadt 	    probe_addr, &cmd, sizeof cmd, &data, sizeof data, 0) != 0)
1273a561bd4Sderaadt 		data = 0xff;
128a5d919cdSgrange 	iic_release_bus(probe_ic, 0);
1293a561bd4Sderaadt 	return (data);
1303a561bd4Sderaadt }
1313a561bd4Sderaadt 
13224b22cd5Sderaadt u_int16_t
13324b22cd5Sderaadt iicprobew(u_int8_t cmd)
134fe4ffc8aSderaadt {
13591eacc75Sderaadt 	u_int16_t data;
136fe4ffc8aSderaadt 
137e616dcecSderaadt 	/*
138e616dcecSderaadt 	 * If we think we are talking to an evil Maxim 1617 or clone,
139e616dcecSderaadt 	 * avoid accessing this register because it is death.
140e616dcecSderaadt 	 */
141e616dcecSderaadt 	if (skip_fc && cmd == 0xfc)
142e616dcecSderaadt 		return (0xffff);
143a5d919cdSgrange 	iic_acquire_bus(probe_ic, 0);
144643d52faSgrange 	if (iic_exec(probe_ic, I2C_OP_READ_WITH_STOP,
14591eacc75Sderaadt 	    probe_addr, &cmd, sizeof cmd, &data, sizeof data, 0) != 0)
14691eacc75Sderaadt 		data = 0xffff;
147a5d919cdSgrange 	iic_release_bus(probe_ic, 0);
14891eacc75Sderaadt 	return betoh16(data);
149fe4ffc8aSderaadt }
150fe4ffc8aSderaadt 
15124b22cd5Sderaadt u_int8_t
15224b22cd5Sderaadt iicprobe(u_int8_t cmd)
1533a561bd4Sderaadt {
1543a561bd4Sderaadt 	if (probe_val[cmd] != 0xff)
1553a561bd4Sderaadt 		return probe_val[cmd];
15624b22cd5Sderaadt 	probe_val[cmd] = iicprobenc(cmd);
1573a561bd4Sderaadt 	return (probe_val[cmd]);
1583a561bd4Sderaadt }
1594e1e7e6eSderaadt 
160010c3e6aSderaadt #define LM75TEMP	0x00
161010c3e6aSderaadt #define LM75CONF	0x01
162010c3e6aSderaadt #define LM75Thyst	0x02
163010c3e6aSderaadt #define LM75Tos		0x03
164010c3e6aSderaadt #define LM77Tlow	0x04
165010c3e6aSderaadt #define LM77Thigh	0x05
166010c3e6aSderaadt #define LM75TMASK	0xff80	/* 9 bits in temperature registers */
167010c3e6aSderaadt #define LM77TMASK	0xfff8	/* 13 bits in temperature registers */
168010c3e6aSderaadt 
169fe4ffc8aSderaadt /*
1709ef2fefcSderaadt  * The LM75/LM75A/LM77 family are very hard to detect.  Thus, we check
1719ef2fefcSderaadt  * for all other possible chips first.  These chips do not have an
1729ef2fefcSderaadt  * ID register.  They do have a few quirks though:
1739ef2fefcSderaadt  * -  on the LM75 and LM77, registers 0x06 and 0x07 return whatever
1749ef2fefcSderaadt  *    value was read before
1759ef2fefcSderaadt  * -  the LM75 lacks registers 0x04 and 0x05, so those act as above
1769ef2fefcSderaadt  * -  the LM75A returns 0xffff for registers 0x04, 0x05, 0x06 and 0x07
1779ef2fefcSderaadt  * -  the chip registers loop every 8 registers
178010c3e6aSderaadt  * The downside is that we must read almost every register to guess
1799ef2fefcSderaadt  * if this is an LM75, LM75A or LM77.
180fe4ffc8aSderaadt  */
181010c3e6aSderaadt char *
182fe4ffc8aSderaadt lm75probe(void)
183fe4ffc8aSderaadt {
184010c3e6aSderaadt 	u_int16_t temp, thyst, tos, tlow, thigh, mask = LM75TMASK;
185010c3e6aSderaadt 	u_int8_t conf;
1869ef2fefcSderaadt 	int i, echocount, ffffcount, score;
1879ef2fefcSderaadt 	int echoreg67, echoreg45, ffffreg67, ffffreg45;
188fe4ffc8aSderaadt 
18982814087Skettenis 	temp = iicprobew(LM75TEMP);
1909ef2fefcSderaadt 
1919ef2fefcSderaadt 	/*
1929ef2fefcSderaadt 	 * Sometimes the other probes can upset the chip, if we get 0xffff
1939ef2fefcSderaadt 	 * the first time, try it once more.
1949ef2fefcSderaadt 	 */
1959ef2fefcSderaadt 	if (temp == 0xffff)
1969ef2fefcSderaadt 		temp = iicprobew(LM75TEMP);
1979ef2fefcSderaadt 
198010c3e6aSderaadt 	conf = iicprobenc(LM75CONF);
19982814087Skettenis 	thyst = iicprobew(LM75Thyst);
20082814087Skettenis 	tos = iicprobew(LM75Tos);
201fe4ffc8aSderaadt 
202010c3e6aSderaadt 	/* totally bogus data */
203010c3e6aSderaadt 	if (conf == 0xff && temp == 0xffff && thyst == 0xffff)
204010c3e6aSderaadt 		return (NULL);
205fe4ffc8aSderaadt 
20682814087Skettenis 	temp &= mask;
20782814087Skettenis 	thyst &= mask;
20882814087Skettenis 	tos &= mask;
20982814087Skettenis 
210010c3e6aSderaadt 	/* All values the same?  Very unlikely */
211010c3e6aSderaadt 	if (temp == thyst && thyst == tos)
212010c3e6aSderaadt 		return (NULL);
213fe4ffc8aSderaadt 
214010c3e6aSderaadt #if notsure
215010c3e6aSderaadt 	/* more register aliasing effects that indicate not a lm75 */
216010c3e6aSderaadt 	if ((temp >> 8) == conf)
217010c3e6aSderaadt 		return (NULL);
218a859ac9bSderaadt #endif
219fe4ffc8aSderaadt 
220010c3e6aSderaadt 	/*
221010c3e6aSderaadt 	 * LM77/LM75 registers 6, 7
222010c3e6aSderaadt 	 * echo whatever was read just before them from reg 0, 1, or 2
2239ef2fefcSderaadt 	 *
2249ef2fefcSderaadt 	 * LM75A doesn't appear to do this, but does appear to reliably
2259ef2fefcSderaadt 	 * return 0xffff
226010c3e6aSderaadt 	 */
2279ef2fefcSderaadt 	for (i = 6, echocount = 2, ffffcount = 0; i <= 7; i++) {
228010c3e6aSderaadt 		if ((iicprobew(LM75TEMP) & mask) != (iicprobew(i) & mask) ||
229010c3e6aSderaadt 		    (iicprobew(LM75Thyst) & mask) != (iicprobew(i) & mask) ||
230010c3e6aSderaadt 		    (iicprobew(LM75Tos) & mask) != (iicprobew(i) & mask))
2319ef2fefcSderaadt 			echocount--;
2329ef2fefcSderaadt 		if (iicprobew(i) == 0xffff)
2339ef2fefcSderaadt 			ffffcount++;
234010c3e6aSderaadt 	}
235010c3e6aSderaadt 
2369ef2fefcSderaadt 	/* Make sure either both registers echo, or neither does */
2379ef2fefcSderaadt 	if (echocount == 1 || ffffcount == 1)
2389ef2fefcSderaadt 		return (NULL);
2399ef2fefcSderaadt 
2409ef2fefcSderaadt 	echoreg67 = (echocount == 0) ? 0 : 1;
2419ef2fefcSderaadt 	ffffreg67 = (ffffcount == 0) ? 0 : 1;
2429ef2fefcSderaadt 
243010c3e6aSderaadt 	/*
244010c3e6aSderaadt 	 * LM75 has no registers 4 or 5, and they will act as echos too
2459ef2fefcSderaadt 	 *
2469ef2fefcSderaadt 	 * LM75A doesn't appear to do this either, but does appear to
2479ef2fefcSderaadt 	 * reliably return 0xffff
248010c3e6aSderaadt 	 */
2499ef2fefcSderaadt 	for (i = 4, echocount = 2, ffffcount = 0; i <= 5; i++) {
2509ef2fefcSderaadt 		if ((iicprobew(LM75TEMP) & mask) != (iicprobew(i) & mask) ||
2519ef2fefcSderaadt 		    (iicprobew(LM75Thyst) & mask) != (iicprobew(i) & mask) ||
2529ef2fefcSderaadt 		    (iicprobew(LM75Tos) & mask) != (iicprobew(i) & mask))
2539ef2fefcSderaadt 			echocount--;
2549ef2fefcSderaadt 		if (iicprobew(i) == 0xffff)
2559ef2fefcSderaadt 			ffffcount++;
2569ef2fefcSderaadt 	}
2579ef2fefcSderaadt 
2589ef2fefcSderaadt 	/* Make sure either both registers echo, or neither does */
2599ef2fefcSderaadt 	if (echocount == 1 || ffffcount == 1)
2609ef2fefcSderaadt 		return (NULL);
2619ef2fefcSderaadt 
2629ef2fefcSderaadt 	echoreg45 = (echocount == 0) ? 0 : 1;
2639ef2fefcSderaadt 	ffffreg45 = (ffffcount == 0) ? 0 : 1;
2649ef2fefcSderaadt 
2659ef2fefcSderaadt 	/*
2669ef2fefcSderaadt 	 * If we find that 4 and 5 are not echos, and don't return 0xffff
2679ef2fefcSderaadt 	 * then based on whether the echo test of registers 6 and 7
2689ef2fefcSderaadt 	 * succeeded or not, we may have an LM77
2699ef2fefcSderaadt 	 */
2709ef2fefcSderaadt 	if (echoreg45 == 0 && ffffreg45 == 0 && echoreg67 == 1) {
271010c3e6aSderaadt 		mask = LM77TMASK;
272010c3e6aSderaadt 
273010c3e6aSderaadt 		/* mask size changed, must re-read for the next checks */
274010c3e6aSderaadt 		thyst = iicprobew(LM75Thyst) & mask;
275010c3e6aSderaadt 		tos = iicprobew(LM75Tos) & mask;
276010c3e6aSderaadt 		tlow = iicprobew(LM77Tlow) & mask;
277010c3e6aSderaadt 		thigh = iicprobew(LM77Thigh) & mask;
278010c3e6aSderaadt 	}
279010c3e6aSderaadt 
2800f1683a6Smiod 	/* a real LM75/LM75A/LM77 repeats its registers.... */
281ecefcc24Smiod 	for (i = 0x08; i <= 0xf8; i += 8) {
282010c3e6aSderaadt 		if (conf != iicprobenc(LM75CONF + i) ||
283010c3e6aSderaadt 		    thyst != (iicprobew(LM75Thyst + i) & mask) ||
284010c3e6aSderaadt 		    tos != (iicprobew(LM75Tos + i) & mask))
285010c3e6aSderaadt 			return (NULL);
2869ef2fefcSderaadt 
2879ef2fefcSderaadt 		/*
2889ef2fefcSderaadt 		 * Check that the repeated registers 0x06 and 0x07 still
2899ef2fefcSderaadt 		 * either echo or return 0xffff
2909ef2fefcSderaadt 		 */
2919ef2fefcSderaadt 		if (echoreg67 == 1) {
292010c3e6aSderaadt 			tos = iicprobew(LM75Tos) & mask;
293010c3e6aSderaadt 			if (tos != (iicprobew(0x06 + i) & mask) ||
294010c3e6aSderaadt 			    tos != (iicprobew(0x07 + i) & mask))
295010c3e6aSderaadt 				return (NULL);
2969ef2fefcSderaadt 		} else if (ffffreg67 == 1)
2979ef2fefcSderaadt 			if (iicprobew(0x06 + i) != 0xffff ||
2989ef2fefcSderaadt 			    iicprobew(0x07 + i) != 0xffff)
2999ef2fefcSderaadt 				return (NULL);
3009ef2fefcSderaadt 
3019ef2fefcSderaadt 		/*
3029ef2fefcSderaadt 		 * Check that the repeated registers 0x04 and 0x05 still
3039ef2fefcSderaadt 		 * either echo or return 0xffff. If they do neither, and
3049ef2fefcSderaadt 		 * registers 0x06 and 0x07 echo, then we will be probing
3059ef2fefcSderaadt 		 * for an LM77, so make sure those still repeat
3069ef2fefcSderaadt 		 */
3079ef2fefcSderaadt 		if (echoreg45 == 1) {
308010c3e6aSderaadt 			tos = iicprobew(LM75Tos) & mask;
309010c3e6aSderaadt 			if (tos != (iicprobew(LM77Tlow + i) & mask) ||
310010c3e6aSderaadt 			    tos != (iicprobew(LM77Thigh + i) & mask))
311010c3e6aSderaadt 				return (NULL);
3129ef2fefcSderaadt 		} else if (ffffreg45 == 1) {
3139ef2fefcSderaadt 			if (iicprobew(LM77Tlow + i) != 0xffff ||
3149ef2fefcSderaadt 			    iicprobew(LM77Thigh + i) != 0xffff)
3159ef2fefcSderaadt 				return (NULL);
3169ef2fefcSderaadt 		} else if (echoreg67 == 1)
317010c3e6aSderaadt 			if (tlow != (iicprobew(LM77Tlow + i) & mask) ||
318010c3e6aSderaadt 			    thigh != (iicprobew(LM77Thigh + i) & mask))
319010c3e6aSderaadt 				return (NULL);
320010c3e6aSderaadt 	}
321fe4ffc8aSderaadt 
3229ef2fefcSderaadt 	/*
3239ef2fefcSderaadt 	 * Given that we now know how the first eight registers behave and
3249ef2fefcSderaadt 	 * that this behaviour is consistently repeated, we can now use
3259ef2fefcSderaadt 	 * the following table:
3269ef2fefcSderaadt 	 *
3279ef2fefcSderaadt 	 * echoreg67 | echoreg45 | ffffreg67 | ffffreg45 | chip
3289ef2fefcSderaadt 	 * ----------+-----------+-----------+-----------+------
3299ef2fefcSderaadt 	 *     1     |     1     |     0     |     0     | LM75
3309ef2fefcSderaadt 	 *     1     |     0     |     0     |     0     | LM77
3319ef2fefcSderaadt 	 *     0     |     0     |     1     |     1     | LM75A
3329ef2fefcSderaadt 	 */
3339ef2fefcSderaadt 
3349ef2fefcSderaadt 	/* Convert the various flags into a single score */
3359ef2fefcSderaadt 	score = (echoreg67 << 3) + (echoreg45 << 2) + (ffffreg67 << 1) +
3369ef2fefcSderaadt 	    ffffreg45;
3379ef2fefcSderaadt 
3389ef2fefcSderaadt 	switch (score) {
3399ef2fefcSderaadt 	case 12:
340010c3e6aSderaadt 		return ("lm75");
3419ef2fefcSderaadt 	case 8:
342010c3e6aSderaadt 		return ("lm77");
3439ef2fefcSderaadt 	case 3:
3449ef2fefcSderaadt 		return ("lm75a");
3459ef2fefcSderaadt 	default:
3463fe49b44Sderaadt #if defined(I2C_DEBUG)
3479ef2fefcSderaadt 		printf("lm75probe: unknown chip, scored %d\n", score);
3483fe49b44Sderaadt #endif /* defined(I2C_DEBUG) */
3499ef2fefcSderaadt 		return (NULL);
3509ef2fefcSderaadt 	}
351fe4ffc8aSderaadt }
352fe4ffc8aSderaadt 
35324b22cd5Sderaadt char *
3545f31ae5bSkettenis adm1032cloneprobe(u_int8_t addr)
355e109779fSderaadt {
356e109779fSderaadt 	if (addr == 0x18 || addr == 0x1a || addr == 0x29 ||
357e109779fSderaadt 	    addr == 0x2b || addr == 0x4c || addr == 0x4e) {
3589cc05711Sderaadt 		u_int8_t reg, val;
3590c1eb8deSderaadt 		int zero = 0, copy = 0;
360e109779fSderaadt 
36124b22cd5Sderaadt 		val = iicprobe(0x00);
3627af89a61Sderaadt 		for (reg = 0x00; reg < 0x09; reg++) {
36324b22cd5Sderaadt 			if (iicprobe(reg) == 0xff)
3649cc05711Sderaadt 				return (NULL);
36524b22cd5Sderaadt 			if (iicprobe(reg) == 0x00)
3667af89a61Sderaadt 				zero++;
36724b22cd5Sderaadt 			if (val == iicprobe(reg))
3680c1eb8deSderaadt 				copy++;
3697af89a61Sderaadt 		}
3700c1eb8deSderaadt 		if (zero > 6 || copy > 6)
3717af89a61Sderaadt 			return (NULL);
37224b22cd5Sderaadt 		val = iicprobe(0x09);
373e616dcecSderaadt 		for (reg = 0x0a; reg < 0xfc; reg++) {
37424b22cd5Sderaadt 			if (iicprobe(reg) != val)
3759cc05711Sderaadt 				return (NULL);
3767af89a61Sderaadt 		}
377c7afa571Skettenis 		/* 0xfe may be Maxim, or some other vendor */
37824b22cd5Sderaadt 		if (iicprobe(0xfe) == 0x4d)
379c7afa571Skettenis 			return ("max1617");
380a1f396d4Sderaadt 		/*
381a1f396d4Sderaadt 		 * "xeontemp" is the name we choose for clone chips
382a1f396d4Sderaadt 		 * which have all sorts of buggy bus interactions, such
383a1f396d4Sderaadt 		 * as those we just probed.  Why?
384a1f396d4Sderaadt 		 * Intel is partly to blame for this situation.
385a1f396d4Sderaadt 		 */
3869cc05711Sderaadt 		return ("xeontemp");
387e109779fSderaadt 	}
3889cc05711Sderaadt 	return (NULL);
389e109779fSderaadt }
390e109779fSderaadt 
391b8fabd7dSderaadt void
392b8fabd7dSderaadt iic_ignore_addr(u_int8_t addr)
393b8fabd7dSderaadt {
394b8fabd7dSderaadt 	int i;
395e109779fSderaadt 
396b8fabd7dSderaadt 	for (i = 0; i < sizeof(ignore_addrs); i++)
397b8fabd7dSderaadt 		if (ignore_addrs[i] == 0) {
398b8fabd7dSderaadt 			ignore_addrs[i] = addr;
399b8fabd7dSderaadt 			return;
400b8fabd7dSderaadt 		}
401b8fabd7dSderaadt }
402e109779fSderaadt 
403d70d6113Scnst #ifdef I2C_VERBOSE
404ad90345aSderaadt void
405ad90345aSderaadt iic_dump(struct device *dv, u_int8_t addr, char *name)
406ad90345aSderaadt {
407481fe91dSderaadt 	static u_int8_t iicvalcnt[256];
408481fe91dSderaadt 	u_int8_t val, val2, max;
409ad90345aSderaadt 	int i, cnt = 0;
410ad90345aSderaadt 
411481fe91dSderaadt 	/*
412481fe91dSderaadt 	 * Don't bother printing the most often repeated register
413481fe91dSderaadt 	 * value, since it is often weird devices that respond
414481fe91dSderaadt 	 * incorrectly, busted controller driver, or in the worst
415481fe91dSderaadt 	 * case, it in mosts cases, the value 0xff.
416481fe91dSderaadt 	 */
417481fe91dSderaadt 	bzero(iicvalcnt, sizeof iicvalcnt);
418481fe91dSderaadt 	val = iicprobe(0);
419481fe91dSderaadt 	iicvalcnt[val]++;
420ad90345aSderaadt 	for (i = 1; i <= 0xff; i++) {
421481fe91dSderaadt 		val2 = iicprobe(i);
422481fe91dSderaadt 		iicvalcnt[val2]++;
423481fe91dSderaadt 		if (val == val2)
424ad90345aSderaadt 			cnt++;
425ad90345aSderaadt 	}
426481fe91dSderaadt 
427481fe91dSderaadt 	for (val = max = i = 0; i <= 0xff; i++)
428481fe91dSderaadt 		if (max < iicvalcnt[i]) {
429481fe91dSderaadt 			max = iicvalcnt[i];
430481fe91dSderaadt 			val = i;
431481fe91dSderaadt 		}
432481fe91dSderaadt 
433447d4274Sderaadt 	if (cnt == 255)
434447d4274Sderaadt 		return;
435447d4274Sderaadt 
436ad90345aSderaadt 	printf("%s: addr 0x%x", dv->dv_xname, addr);
437ad90345aSderaadt 	for (i = 0; i <= 0xff; i++) {
438481fe91dSderaadt 		if (iicprobe(i) != val)
439ad90345aSderaadt 			printf(" %02x=%02x", i, iicprobe(i));
440ad90345aSderaadt 	}
44152d7500cScnst 	printf(" words");
442b86f8d57Sderaadt 	for (i = 0; i < 8; i++)
443447d4274Sderaadt 		printf(" %02x=%04x", i, iicprobew(i));
444ad90345aSderaadt 	if (name)
445ad90345aSderaadt 		printf(": %s", name);
446ad90345aSderaadt 	printf("\n");
447ad90345aSderaadt }
448d70d6113Scnst #endif /* I2C_VERBOSE */
449ad90345aSderaadt 
45022ef5474Sderaadt char *
4511c658e45Scnst iic_probe_sensor(struct device *self, u_int8_t addr)
45247098ca3Sderaadt {
45347098ca3Sderaadt 	char *name = NULL;
45447098ca3Sderaadt 
455e616dcecSderaadt 	skip_fc = 0;
45648a89adfSderaadt 
45747098ca3Sderaadt 	/*
458b3667398Skettenis 	 * Many I2C/SMBus devices use register 0x3e as a vendor ID
459b3667398Skettenis 	 * register.
460b3667398Skettenis 	 */
461b3667398Skettenis 	switch (iicprobe(0x3e)) {
462a15c982aSkettenis 	case 0x01:		/* National Semiconductor */
463a15c982aSkettenis 		/*
464a15c982aSkettenis 		 * Some newer National products use a vendor code at
465a15c982aSkettenis 		 * 0x3e of 0x01, and then 0x3f contains a product code
466a15c982aSkettenis 		 * But some older products are missing a product code,
467a15c982aSkettenis 		 * and contain who knows what in that register.  We assume
468a15c982aSkettenis 		 * that some employee was smart enough to keep the numbers
469a15c982aSkettenis 		 * unique.
470a15c982aSkettenis 		 */
471a15c982aSkettenis 		if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
472969e6ec1Sderaadt 		    (iicprobe(0x3f) == 0x73 || iicprobe(0x3f) == 0x72) &&
473969e6ec1Sderaadt 		    iicprobe(0x00) == 0x00)
474969e6ec1Sderaadt 			name = "lm93";	/* product 0x72 is the prototype */
475a15c982aSkettenis 		else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
476a15c982aSkettenis 		    iicprobe(0x3f) == 0x68)
477a15c982aSkettenis 			name = "lm96000";	/* adt7460 compat? */
478a15c982aSkettenis 		else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
479a15c982aSkettenis 		    (iicprobe(0x3f) == 0x60 || iicprobe(0x3f) == 0x62))
480a15c982aSkettenis 			name = "lm85";		/* lm85C/B == adt7460 compat */
481a15c982aSkettenis 		else if ((addr & 0x7c) == 0x2c &&	/* addr 0b01011xx */
482a15c982aSkettenis 		    iicprobe(0x48) == addr &&
483a15c982aSkettenis 		    (iicprobe(0x3f) == 0x03 || iicprobe(0x3f) == 0x04) &&
484a15c982aSkettenis 		    (iicprobe(0x40) & 0x80) == 0x00)
485a15c982aSkettenis 			name = "lm81";
486a15c982aSkettenis 		break;
487a15c982aSkettenis 	case 0x02:		/* National Semiconductor? */
488a15c982aSkettenis 		if ((iicprobe(0x3f) & 0xfc) == 0x04)
489a15c982aSkettenis 			name = "lm87";		/* complete check */
490a15c982aSkettenis 		break;
491a15c982aSkettenis 	case 0x23:		/* Analog Devices? */
492a15c982aSkettenis 		if (iicprobe(0x48) == addr &&
493a15c982aSkettenis 		    (iicprobe(0x40) & 0x80) == 0x00 &&
494a15c982aSkettenis 		    (addr & 0x7c) == 0x2c)
495a15c982aSkettenis 			name = "adm9240";	/* lm87 clone */
496a15c982aSkettenis 		break;
497b3667398Skettenis 	case 0x41:		/* Analog Devices */
498b3667398Skettenis 		/*
499e6bfbe09Sderaadt 		 * Newer chips have a valid 0x3d product number, while
500e6bfbe09Sderaadt 		 * older ones sometimes encoded the product into the
501b3667398Skettenis 		 * upper half of the "step register" at 0x3f.
50247098ca3Sderaadt 		 */
503b3667398Skettenis 		if ((addr == 0x2c || addr == 0x2e || addr == 0x2f) &&
50424b22cd5Sderaadt 		    iicprobe(0x3d) == 0x70)
50547098ca3Sderaadt 			name = "adt7470";
506b3667398Skettenis 		else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
507b3667398Skettenis 		    iicprobe(0x3d) == 0x76)
50834110729Sderaadt 			name = "adt7476"; /* or adt7476a */
509e2beff3dSkettenis 		else if (addr == 0x2e && iicprobe(0x3d) == 0x75)
510d57c2af9Sderaadt 			name = "adt7475";
51124b22cd5Sderaadt 		else if (iicprobe(0x3d) == 0x27 &&
51224b22cd5Sderaadt 		    (iicprobe(0x3f) == 0x60 || iicprobe(0x3f) == 0x6a))
513680deb82Sderaadt 			name = "adm1027";	/* or adt7463 */
51424b22cd5Sderaadt 		else if (iicprobe(0x3d) == 0x27 &&
51524b22cd5Sderaadt 		    (iicprobe(0x3f) == 0x62 || iicprobe(0x3f) == 0x6a))
5161719fadaSderaadt 			name = "adt7460";	/* complete check */
51734110729Sderaadt 		else if ((addr == 0x2c || addr == 0x2e) &&
51834110729Sderaadt 		    iicprobe(0x3d) == 0x62 && iicprobe(0x3f) == 0x04)
51934110729Sderaadt 			name = "adt7462";
520680deb82Sderaadt 		else if (addr == 0x4c &&
521680deb82Sderaadt 		    iicprobe(0x3d) == 0x66 && iicprobe(0x3f) == 0x02)
522680deb82Sderaadt 			name = "adt7466";
523b3667398Skettenis 		else if (addr == 0x2e &&
524b3667398Skettenis 		    iicprobe(0x3d) == 0x68 && (iicprobe(0x3f) & 0xf0) == 0x70)
52534110729Sderaadt 			name = "adt7467"; /* or adt7468 */
526a3ed46d5Sderaadt 		else if (iicprobe(0x3d) == 0x33 && iicprobe(0x3f) == 0x02)
52747098ca3Sderaadt 			name = "adm1033";
528d46ba363Sderaadt 		else if (iicprobe(0x3d) == 0x34 && iicprobe(0x3f) == 0x02)
529d46ba363Sderaadt 			name = "adm1034";
5304ecc4011Skettenis 		else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
53124b22cd5Sderaadt 		    iicprobe(0x3d) == 0x30 &&
5324ecc4011Skettenis 		    (iicprobe(0x01) & 0x80) == 0x00 &&
53324b22cd5Sderaadt 		    (iicprobe(0x0d) & 0x70) == 0x00 &&
53424b22cd5Sderaadt 		    (iicprobe(0x0e) & 0x70) == 0x00)
5354ecc4011Skettenis 			/*
5364ecc4011Skettenis 			 * Revision 3 seems to be an adm1031 with
5374ecc4011Skettenis 			 * remote diode 2 shorted.  Therefore we
5384ecc4011Skettenis 			 * cannot assume the reserved/unused bits of
5394ecc4011Skettenis 			 * register 0x03 and 0x06 are set to zero.
5404ecc4011Skettenis 			 */
5411719fadaSderaadt 			name = "adm1030";	/* complete check */
5424ecc4011Skettenis 		else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
54324b22cd5Sderaadt 		    iicprobe(0x3d) == 0x31 &&
5444ecc4011Skettenis 		    (iicprobe(0x01) & 0x80) == 0x00 &&
54524b22cd5Sderaadt 		    (iicprobe(0x0d) & 0x70) == 0x00 &&
54624b22cd5Sderaadt 		    (iicprobe(0x0e) & 0x70) == 0x00 &&
54724b22cd5Sderaadt 		    (iicprobe(0x0f) & 0x70) == 0x00)
5481719fadaSderaadt 			name = "adm1031";	/* complete check */
5499cc05711Sderaadt 		else if ((addr & 0x7c) == 0x2c &&	/* addr 0b01011xx */
55024b22cd5Sderaadt 		    (iicprobe(0x3f) & 0xf0) == 0x20 &&
55124b22cd5Sderaadt 		    (iicprobe(0x40) & 0x80) == 0x00 &&
55224b22cd5Sderaadt 		    (iicprobe(0x41) & 0xc0) == 0x00 &&
55324b22cd5Sderaadt 		    (iicprobe(0x42) & 0xbc) == 0x00)
5541719fadaSderaadt 			name = "adm1025";	/* complete check */
5559cc05711Sderaadt 		else if ((addr & 0x7c) == 0x2c &&	/* addr 0b01011xx */
55624b22cd5Sderaadt 		    (iicprobe(0x3f) & 0xf0) == 0x10 &&
55724b22cd5Sderaadt 		    (iicprobe(0x40) & 0x80) == 0x00)
5581719fadaSderaadt 			name = "adm1024";	/* complete check */
55924b22cd5Sderaadt 		else if ((iicprobe(0xff) & 0xf0) == 0x30)
56047098ca3Sderaadt 			name = "adm1023";
561b3667398Skettenis 		else if (addr == 0x2e &&
562b3667398Skettenis 		    (iicprobe(0x3f) & 0xf0) == 0xd0 &&
56324b22cd5Sderaadt 		    (iicprobe(0x40) & 0x80) == 0x00)
56480c89fdcSderaadt 			name = "adm1028";	/* adm1022 clone? */
565b3667398Skettenis 		else if ((addr == 0x2c || addr == 0x2e || addr == 0x2f) &&
566b3667398Skettenis 		    (iicprobe(0x3f) & 0xf0) == 0xc0 &&
56724b22cd5Sderaadt 		    (iicprobe(0x40) & 0x80) == 0x00)
56847098ca3Sderaadt 			name = "adm1022";
5691719fadaSderaadt 		break;
570a15c982aSkettenis 	case 0x49:		/* Texas Instruments */
571a15c982aSkettenis 		if ((addr == 0x2c || addr == 0x2e || addr == 0x2f) &&
572a15c982aSkettenis 		    (iicprobe(0x3f) & 0xf0) == 0xc0 &&
573a15c982aSkettenis 		    (iicprobe(0x40) & 0x80) == 0x00)
574a15c982aSkettenis 			name = "thmc50";	/* adm1022 clone */
575c3d2b8f7Sderaadt 		break;
576b3667398Skettenis 	case 0x55:		/* SMSC */
577b3667398Skettenis 		if ((addr & 0x7c) == 0x2c &&		/* addr 0b01011xx */
578b3667398Skettenis 		    iicprobe(0x3f) == 0x20 &&
579b3667398Skettenis 		    (iicprobe(0x47) & 0x70) == 0x00 &&
580b3667398Skettenis 		    (iicprobe(0x49) & 0xfe) == 0x80)
58148a89adfSderaadt 			name = "47m192";	/* adm1025 compat */
5821719fadaSderaadt 		break;
58380c89fdcSderaadt 	case 0x5c:		/* SMSC */
584b3667398Skettenis 		if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
585ce21cebcSderaadt 		    (iicprobe(0x3f) == 0x69))
586ce21cebcSderaadt 			name = "sch5027";
587ce21cebcSderaadt 		else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
588b3667398Skettenis 		    (iicprobe(0x3f) & 0xf0) == 0x60)
589e5888777Skettenis 			name = "emc6d100";   /* emc6d101, emc6d102, emc6d103 */
590d3d6d5a2Skettenis 		else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
591d3d6d5a2Skettenis 		    (iicprobe(0x3f) & 0xf0) == 0x80)
592d3d6d5a2Skettenis 			name = "sch5017";
593d3d6d5a2Skettenis 		else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
594d3d6d5a2Skettenis 		    (iicprobe(0x3f) & 0xf0) == 0xb0)
595d3d6d5a2Skettenis 			name = "emc6w201";
5961719fadaSderaadt 		break;
5974c61b7c4Skettenis 	case 0x61:		/* Andigilog */
5984c61b7c4Skettenis 		if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
59975412184Scnst 		    iicprobe(0x3f) == 0x69 &&
60079d4b091Scnst 		    iicprobe(0x22) >= 0xaf &&		/* Vdd */
60175412184Scnst 		    (iicprobe(0x09) & 0xbf) == 0x00 && iicprobe(0x0f) == 0x00 &&
60275412184Scnst 		    (iicprobe(0x40) & 0xf0) == 0x00)
60375412184Scnst 			name = "asc7611";
60475412184Scnst 		else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
60579d4b091Scnst 		    iicprobe(0x3f) == 0x6c &&
60679d4b091Scnst 		    iicprobe(0x22) >= 0xae)		/* Vdd */
6074c61b7c4Skettenis 			name = "asc7621";
6084c61b7c4Skettenis 		break;
609a15c982aSkettenis 	case 0xa1:		/* Philips */
610a15c982aSkettenis 		if ((iicprobe(0x3f) & 0xf0) == 0x20 &&
611a15c982aSkettenis 		    (iicprobe(0x40) & 0x80) == 0x00 &&
612a15c982aSkettenis 		    (iicprobe(0x41) & 0xc0) == 0x00 &&
613a15c982aSkettenis 		    (iicprobe(0x42) & 0xbc) == 0x00)
614a15c982aSkettenis 			name = "ne1619";	/* adm1025 compat */
61580c89fdcSderaadt 		break;
616b3667398Skettenis 	case 0xda:		/* Dallas Semiconductor */
61724b22cd5Sderaadt 		if (iicprobe(0x3f) == 0x01 && iicprobe(0x48) == addr &&
61824b22cd5Sderaadt 		    (iicprobe(0x40) & 0x80) == 0x00)
619933ace77Sderaadt 			name = "ds1780";	/* lm87 clones */
6201719fadaSderaadt 		break;
6211719fadaSderaadt 	}
622b7b8e57cSkettenis 
62324b22cd5Sderaadt 	switch (iicprobe(0x4e)) {
624b3667398Skettenis 	case 0x41:		/* Analog Devices */
6259cc05711Sderaadt 		if ((addr == 0x48 || addr == 0x4a || addr == 0x4b) &&
62624b22cd5Sderaadt 		    (iicprobe(0x4d) == 0x03 || iicprobe(0x4d) == 0x08 ||
62724b22cd5Sderaadt 		    iicprobe(0x4d) == 0x07))
6289cc05711Sderaadt 			name = "adt7516";	/* adt7517, adt7519 */
6299cc05711Sderaadt 		break;
6309cc05711Sderaadt 	}
6311719fadaSderaadt 
632b7b8e57cSkettenis 	switch (iicprobe(0xfe)) {
633b7b8e57cSkettenis 	case 0x01:		/* National Semiconductor */
634b7b8e57cSkettenis 		if (addr == 0x4c &&
6356991a698Skettenis 		    iicprobe(0xff) == 0x41 && (iicprobe(0x03) & 0x18) == 0 &&
6366991a698Skettenis 		    iicprobe(0x04) <= 0x0f && (iicprobe(0xbf) & 0xf8) == 0)
6376991a698Skettenis 			name = "lm63";
6386991a698Skettenis 		else if (addr == 0x4c &&
639b7b8e57cSkettenis 		    iicprobe(0xff) == 0x11 && (iicprobe(0x03) & 0x2a) == 0 &&
640b7b8e57cSkettenis 		    iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0)
6413b5e26bdSderaadt 			name = "lm86";
6426991a698Skettenis 		else if (addr == 0x4c &&
643b7b8e57cSkettenis 		    iicprobe(0xff) == 0x31 && (iicprobe(0x03) & 0x2a) == 0 &&
644b7b8e57cSkettenis 		    iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0)
645b7b8e57cSkettenis 			name = "lm89";		/* or lm99 */
646b7b8e57cSkettenis 		else if (addr == 0x4d &&
647b7b8e57cSkettenis 		    iicprobe(0xff) == 0x34 && (iicprobe(0x03) & 0x2a) == 0 &&
648b7b8e57cSkettenis 		    iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0)
649b7b8e57cSkettenis 			name = "lm89-1";	/* or lm99-1 */
650b7b8e57cSkettenis 		else if (addr == 0x4c &&
651b7b8e57cSkettenis 		    iicprobe(0xff) == 0x21 && (iicprobe(0x03) & 0x2a) == 0 &&
652b7b8e57cSkettenis 		    iicprobe(0x04) <= 0x09 && (iicprobe(0xbf) & 0xf8) == 0)
653b7b8e57cSkettenis 			name = "lm90";
654b7b8e57cSkettenis 		break;
6557a7081baSkettenis 	case 0x23:		/* Genesys Logic? */
6567a7081baSkettenis 		if ((addr == 0x4c) &&
6577a7081baSkettenis 		    (iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x08)
6587a7081baSkettenis 			/*
6597a7081baSkettenis 			 * Genesys Logic doesn't make the datasheet
660*9593dc34Smglocker 			 * for the GL523SM publicly available, so
6617a7081baSkettenis 			 * the checks above are nothing more than a
6627a7081baSkettenis 			 * (conservative) educated guess.
6637a7081baSkettenis 			 */
6647a7081baSkettenis 			name = "gl523sm";
6657a7081baSkettenis 		break;
666a15c982aSkettenis 	case 0x41:		/* Analog Devices */
667b7b8e57cSkettenis 		if ((addr == 0x4c || addr == 0x4d) &&
668b7b8e57cSkettenis 		    iicprobe(0xff) == 0x51 &&
669b7b8e57cSkettenis 		    (iicprobe(0x03) & 0x1f) == 0x04 &&
670b7b8e57cSkettenis 		    iicprobe(0x04) <= 0x0a) {
671b7b8e57cSkettenis 			/* If not in adm1032 compatibility mode. */
672b7b8e57cSkettenis 			name = "adt7461";
673b7b8e57cSkettenis 		} else if ((addr == 0x18 || addr == 0x19 || addr == 0x1a ||
674b7b8e57cSkettenis 		    addr == 0x29 || addr == 0x2a || addr == 0x2b ||
675b7b8e57cSkettenis 		    addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
676b7b8e57cSkettenis 		    (iicprobe(0xff) & 0xf0) == 0x00 &&
677b7b8e57cSkettenis 		    (iicprobe(0x03) & 0x3f) == 0x00 &&
678b7b8e57cSkettenis 		    iicprobe(0x04) <= 0x07) {
679b7b8e57cSkettenis 			name = "adm1021";
680e616dcecSderaadt 			skip_fc = 1;
681b3667398Skettenis 		} else if ((addr == 0x18 || addr == 0x19 || addr == 0x1a ||
6828b568ffdSderaadt 		    addr == 0x29 || addr == 0x2a || addr == 0x2b ||
683b3667398Skettenis 		    addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
684b7b8e57cSkettenis 		    (iicprobe(0xff) & 0xf0) == 0x30 &&
685b7b8e57cSkettenis 		    (iicprobe(0x03) & 0x3f) == 0x00 &&
686b7b8e57cSkettenis 		    iicprobe(0x04) <= 0x07) {
687b7b8e57cSkettenis 			name = "adm1023";	/* or adm1021a */
688e616dcecSderaadt 			skip_fc = 1;
689b7b8e57cSkettenis 		} else if ((addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
690b7b8e57cSkettenis 		    (iicprobe(0x03) & 0x3f) == 0x00 &&
691b7b8e57cSkettenis 		    iicprobe(0x04) <= 0x0a) {
692b7b8e57cSkettenis 			name = "adm1032";	/* or adm1020 */
693b7b8e57cSkettenis 			skip_fc = 1;
694b7b8e57cSkettenis 		}
69564146f5fSkettenis 		break;
6967a7081baSkettenis 	case 0x47:		/* Global Mixed-mode Technology */
6977a7081baSkettenis 		if (addr == 0x4c && iicprobe(0xff) == 0x01 &&
6987a7081baSkettenis 		    (iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x08)
6997a7081baSkettenis 			name = "g781";
7007a7081baSkettenis 		if (addr == 0x4d && iicprobe(0xff) == 0x03 &&
7017a7081baSkettenis 		    (iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x08)
7027a7081baSkettenis 			name = "g781-1";
7037a7081baSkettenis 		break;
704a15c982aSkettenis 	case 0x4d:		/* Maxim */
705a15c982aSkettenis 		if ((addr == 0x18 || addr == 0x19 || addr == 0x1a ||
706a15c982aSkettenis 		     addr == 0x29 || addr == 0x2a || addr == 0x2b ||
707a15c982aSkettenis 		     addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
708a15c982aSkettenis 		    iicprobe(0xff) == 0x08 && (iicprobe(0x02) & 0x03) == 0 &&
709a15c982aSkettenis 		    (iicprobe(0x03) & 0x07) == 0 && iicprobe(0x04) <= 0x08)
710a15c982aSkettenis 			name = "max6690";
711a15c982aSkettenis 		else if ((addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
712a15c982aSkettenis 		    iicprobe(0xff) == 0x59 && (iicprobe(0x03) & 0x1f) == 0 &&
713a15c982aSkettenis 		    iicprobe(0x04) <= 0x07)
714a15c982aSkettenis 			name = "max6646";	/* max6647/8/9, max6692 */
715a15c982aSkettenis 		else if ((addr == 0x4c || addr == 0x4d || addr == 0x4e) &&
716a15c982aSkettenis 		    (iicprobe(0x02) & 0x2b) == 0 &&
717a15c982aSkettenis 		    (iicprobe(0x03) & 0x0f) == 0 && iicprobe(0x04) <= 0x09) {
718a15c982aSkettenis 			name = "max6657";	/* max6658, max6659 */
719a15c982aSkettenis 			skip_fc = 1;
720a15c982aSkettenis 		} else if ((addr >= 0x48 && addr <= 0x4f) &&
721a15c982aSkettenis 		    (iicprobe(0x02) & 0x2b) == 0 &&
722a15c982aSkettenis 		    (iicprobe(0x03) & 0x0f) == 0)
723a15c982aSkettenis 			name = "max6642";
724a15c982aSkettenis 		break;
7254f5e1e1cSderaadt 	case 0x55:		/* Texas Instruments */
7264f5e1e1cSderaadt 		if (addr == 0x4c && iicprobe(0xff) == 0x11 &&
7274f5e1e1cSderaadt 		    (iicprobe(0x03) & 0x1b) == 0x00 &&
7284f5e1e1cSderaadt 		    (iicprobe(0x04) & 0xf0) == 0x00 &&
7294f5e1e1cSderaadt 		    (iicprobe(0x10) & 0x0f) == 0x00 &&
7304f5e1e1cSderaadt 		    (iicprobe(0x13) & 0x0f) == 0x00 &&
7314f5e1e1cSderaadt 		    (iicprobe(0x14) & 0x0f) == 0x00 &&
7324f5e1e1cSderaadt 		    (iicprobe(0x15) & 0x0f) == 0x00 &&
7334f5e1e1cSderaadt 		    (iicprobe(0x16) & 0x0f) == 0x00 &&
7344f5e1e1cSderaadt 		    (iicprobe(0x17) & 0x0f) == 0x00)
7354f5e1e1cSderaadt 			name = "tmp401";
7364f5e1e1cSderaadt 		break;
737ab19912bSderaadt 	case 0xa1:
738ab19912bSderaadt 		if ((addr >= 0x48 && addr <= 0x4f) &&
739ab19912bSderaadt 		    iicprobe(0xff) == 0x00 &&
740ab19912bSderaadt 		    (iicprobe(0x03) & 0xf8) == 0x00 &&
741ab19912bSderaadt 		    iicprobe(0x04) <= 0x09) {
742ab19912bSderaadt 			name = "sa56004x";	/* NXP sa56004x */
743ab19912bSderaadt 			skip_fc = 1;
744ab19912bSderaadt 		}
745ab19912bSderaadt 		break;
746b7b8e57cSkettenis 	}
747b7b8e57cSkettenis 
748b7b8e57cSkettenis 	if (addr == iicprobe(0x48) &&
74970eaf079Skettenis 	    ((iicprobe(0x4f) == 0x5c && (iicprobe(0x4e) & 0x80)) ||
75070eaf079Skettenis 	    (iicprobe(0x4f) == 0xa3 && !(iicprobe(0x4e) & 0x80)))) {
751b486fbb1Sderaadt 		/*
752a1f396d4Sderaadt 		 * We could toggle 0x4e bit 0x80, then re-read 0x4f to
753a1f396d4Sderaadt 		 * see if the value changes to 0xa3 (indicating Winbond).
754a1f396d4Sderaadt 		 * But we are trying to avoid writes.
755d60647f1Skettenis 		 */
75670eaf079Skettenis 		if ((iicprobe(0x4e) & 0x07) == 0) {
757d60647f1Skettenis 			switch (iicprobe(0x58)) {
758d60647f1Skettenis 			case 0x10:
759e3516dc3Skettenis 			case 0x11:			/* rev 2? */
760d60647f1Skettenis 				name = "w83781d";
761d60647f1Skettenis 				break;
762d60647f1Skettenis 			case 0x21:
763d60647f1Skettenis 				name = "w83627hf";
764d60647f1Skettenis 				break;
765d60647f1Skettenis 			case 0x30:
766d60647f1Skettenis 				name = "w83782d";
767d60647f1Skettenis 				break;
768d60647f1Skettenis 			case 0x31:
769d60647f1Skettenis 				name = "as99127f";	/* rev 2 */
770d60647f1Skettenis 				break;
771d60647f1Skettenis 			case 0x40:
772d60647f1Skettenis 				name = "w83783s";
773d60647f1Skettenis 				break;
774d60647f1Skettenis 			case 0x71:
775d60647f1Skettenis 				name = "w83791d";
776d60647f1Skettenis 				break;
7779cd4d9d7Skettenis 			case 0x72:
7789cd4d9d7Skettenis 				name = "w83791sd";
7799cd4d9d7Skettenis 				break;
780d60647f1Skettenis 			case 0x7a:
781d60647f1Skettenis 				name = "w83792d";
782d60647f1Skettenis 				break;
783abd5869cScnst 			case 0xc1:
784abd5869cScnst 				name = "w83627dhg";
785abd5869cScnst 				break;
786d60647f1Skettenis 			}
78770eaf079Skettenis 		} else {
78870eaf079Skettenis 			/*
78970eaf079Skettenis 			 * The BIOS left the chip in a non-zero
79070eaf079Skettenis 			 * register bank.  Assume it's a W83781D and
79170eaf079Skettenis 			 * let lm(4) sort out the real model.
79270eaf079Skettenis 			 */
79370eaf079Skettenis 			name = "w83781d";
79470eaf079Skettenis 		}
795cfcc5026Skettenis 	} else if (addr == (iicprobe(0xfc) & 0x7f) &&
796cfcc5026Skettenis 	    iicprobe(0xfe) == 0x79 && iicprobe(0xfb) == 0x51 &&
797cfcc5026Skettenis 	    ((iicprobe(0xfd) == 0x5c && (iicprobe(0x00) & 0x80)) ||
798cfcc5026Skettenis 	    (iicprobe(0xfd) == 0xa3 && !(iicprobe(0x00) & 0x80)))) {
799cfcc5026Skettenis 		/*
800cfcc5026Skettenis 		 * We could toggle 0x00 bit 0x80, then re-read 0xfd to
801cfcc5026Skettenis 		 * see if the value changes to 0xa3 (indicating Nuvoton).
802cfcc5026Skettenis 		 * But we are trying to avoid writes.
803cfcc5026Skettenis 		 */
804cfcc5026Skettenis 		name = "w83795g";
8059cd4d9d7Skettenis 	} else if (addr == iicprobe(0x4a) && iicprobe(0x4e) == 0x50 &&
8069cd4d9d7Skettenis 	    iicprobe(0x4c) == 0xa3 && iicprobe(0x4d) == 0x5c) {
8079cd4d9d7Skettenis 		name = "w83l784r";
8089cd4d9d7Skettenis 	} else if (addr == 0x2d && iicprobe(0x4e) == 0x60 &&
8099cd4d9d7Skettenis 	    iicprobe(0x4c) == 0xa3 && iicprobe(0x4d) == 0x5c) {
8109cd4d9d7Skettenis 		name = "w83l785r";
8112bc4c753Skettenis 	} else if (addr == 0x2e && iicprobe(0x4e) == 0x70 &&
8129cd4d9d7Skettenis 	    iicprobe(0x4c) == 0xa3 && iicprobe(0x4d) == 0x5c) {
813e737756fSkettenis 		name = "w83l785ts-l";
814d58ac4cdScnst 	} else if (addr >= 0x2c && addr <= 0x2f &&
8157c26d915Scnst 	    ((iicprobe(0x00) & 0x07) != 0x0 ||
8167c26d915Scnst 	    ((iicprobe(0x00) & 0x07) == 0x0 && addr * 2 == iicprobe(0x0b) &&
8177c26d915Scnst 	    (iicprobe(0x0c) & 0x40) && !(iicprobe(0x0c) & 0x04))) &&
818d58ac4cdScnst 	    iicprobe(0x0e) == 0x7b &&
8197c26d915Scnst 	    (iicprobe(0x0f) & 0xf0) == 0x10 &&
820d58ac4cdScnst 	    ((iicprobe(0x0d) == 0x5c && (iicprobe(0x00) & 0x80)) ||
821d58ac4cdScnst 	    (iicprobe(0x0d) == 0xa3 && !(iicprobe(0x00) & 0x80)))) {
822d58ac4cdScnst 		name = "w83793g";
8230c1990beSkettenis 	} else if (addr >= 0x28 && addr <= 0x2f &&
82470eaf079Skettenis 	    iicprobe(0x4f) == 0x12 && (iicprobe(0x4e) & 0x80)) {
825d60647f1Skettenis 		/*
826a1f396d4Sderaadt 		 * We could toggle 0x4e bit 0x80, then re-read 0x4f to
827a1f396d4Sderaadt 		 * see if the value changes to 0xc3 (indicating ASUS).
828a1f396d4Sderaadt 		 * But we are trying to avoid writes.
829b486fbb1Sderaadt 		 */
83024b22cd5Sderaadt 		if (iicprobe(0x58) == 0x31)
831d60647f1Skettenis 			name = "as99127f";	/* rev 1 */
832c09e2fbaSderaadt 	} else if ((addr == 0x2d || addr == 0x2e) &&
833c09e2fbaSderaadt 	    addr * 2 == iicprobe(0x04) &&
834c09e2fbaSderaadt 	    iicprobe(0x5d) == 0x19 && iicprobe(0x5e) == 0x34 &&
835c09e2fbaSderaadt 	    iicprobe(0x5a) == 0x03 && iicprobe(0x5b) == 0x06) {
836c09e2fbaSderaadt 		name = "f75375";	/* Fintek */
837e19478bdSdjm 	} else if (addr == 0x2d &&
838e19478bdSdjm 	    ((iicprobe(0x4f) == 0x06 && (iicprobe(0x4e) & 0x80)) ||
839e19478bdSdjm 	    (iicprobe(0x4f) == 0x94 && !(iicprobe(0x4e) & 0x80)))) {
840e19478bdSdjm 		/*
841a1f396d4Sderaadt 		 * We could toggle 0x4e bit 0x80, then re-read 0x4f to
842a1f396d4Sderaadt 		 * see if the value changes to 0x94 (indicating ASUS).
843a1f396d4Sderaadt 		 * But we are trying to avoid writes.
844e19478bdSdjm 		 *
845e19478bdSdjm 		 * NB. we won't match if the BIOS has selected a non-zero
846e19478bdSdjm 		 * register bank (set via 0x4e). We could select bank 0 so
847a1f396d4Sderaadt 		 * we see the right registers, but that would require a
848a1f396d4Sderaadt 		 * write.  In general though, we bet no BIOS would leave us
849a1f396d4Sderaadt 		 * in the wrong state.
850e19478bdSdjm 		 */
851e19478bdSdjm 		if ((iicprobe(0x58) & 0x7f) == 0x31 &&
852e19478bdSdjm 		    (iicprobe(0x4e) & 0xf) == 0x00)
853e19478bdSdjm 			name = "asb100";
854b3667398Skettenis 	} else if ((addr == 0x2c || addr == 0x2d) &&
855b3667398Skettenis 	    iicprobe(0x00) == 0x80 &&
85642fb8b88Skettenis 	    (iicprobe(0x01) == 0x00 || iicprobe(0x01) == 0x80) &&
85742fb8b88Skettenis 	    iicprobe(0x02) == 0x00 && (iicprobe(0x03) & 0x83) == 0x00 &&
85842fb8b88Skettenis 	    (iicprobe(0x0f) & 0x07) == 0x00 &&
85942fb8b88Skettenis 	    (iicprobe(0x11) & 0x80) == 0x00 &&
86042fb8b88Skettenis 	    (iicprobe(0x12) & 0x80) == 0x00) {
86142fb8b88Skettenis 		/*
86242fb8b88Skettenis 		 * The GL518SM is really crappy.  It has both byte and
86342fb8b88Skettenis 		 * word registers, and reading a word register with a
86442fb8b88Skettenis 		 * byte read command will make the device crap out and
86542fb8b88Skettenis 		 * hang the bus.  This has nasty consequences on some
86642fb8b88Skettenis 		 * machines, like preventing warm reboots.  The word
86742fb8b88Skettenis 		 * registers are 0x07 through 0x0c, so make sure the
86842fb8b88Skettenis 		 * checks above don't access those registers.  We
86942fb8b88Skettenis 		 * don't want to do this check right up front though
87042fb8b88Skettenis 		 * since this chip is somewhat hard to detect (which
87142fb8b88Skettenis 		 * is why we check for every single fixed bit it has).
87242fb8b88Skettenis 		 */
87342fb8b88Skettenis 		name = "gl518sm";
874b3667398Skettenis 	} else if ((addr == 0x2c || addr == 0x2d || addr == 0x2e) &&
875b3667398Skettenis 	    iicprobe(0x16) == 0x41 && ((iicprobe(0x17) & 0xf0) == 0x40)) {
87680c89fdcSderaadt 		name = "adm1026";
8771ab2fcb9Scnst 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1131 &&
878305d5022Sderaadt 	    (iicprobew(0x07) & 0xfffc) == 0xa200) {
879305d5022Sderaadt 		name = "se97";		/* or se97b */
8806869b31aSderaadt 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1131 &&
8813f8e4e1eSjsg 	    (iicprobew(0x07) & 0xfffc) == 0xa100 &&
8826869b31aSderaadt 	    (iicprobew(0x00) & 0xfff0) == 0x0010) {
8836869b31aSderaadt 		name = "se98";
8846869b31aSderaadt 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x004d &&
8856869b31aSderaadt 	    iicprobew(0x07) == 0x3e00 &&
8866869b31aSderaadt 	    (iicprobew(0x00) & 0xffe0) == 0x0000) {
8876869b31aSderaadt 		name = "max6604";
8881ab2fcb9Scnst 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 &&
889462cb67aSjsg 	    (iicprobew(0x07) & 0xfffc) == 0x0200 &&
890462cb67aSjsg 	    (iicprobew(0x00) & 0xffe0) == 0x0000) {
891462cb67aSjsg 		name = "mcp9804";
892462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 &&
893305d5022Sderaadt 	    (iicprobew(0x07) & 0xff00) == 0x0000 &&
8947a2e6054Sderaadt 	    (iicprobew(0x00) & 0xffe0) == 0x0000) {
895305d5022Sderaadt 		name = "mcp9805";		/* or mcp9843 */
8961ab2fcb9Scnst 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 &&
8976869b31aSderaadt 	    (iicprobew(0x07) & 0xfffc) == 0x2000 &&
8984c930efaSderaadt 	    (iicprobew(0x00) & 0xffe0) == 0x0000) {
8994c930efaSderaadt 		name = "mcp98242";
9006869b31aSderaadt 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 &&
901305d5022Sderaadt 	    (iicprobew(0x07) & 0xff00) == 0x2100 &&
902a5f76fa9Sderaadt 	    (iicprobew(0x00) & 0xff00) == 0x0000) {
9036869b31aSderaadt 		name = "mcp98243";
904462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x0054 &&
905462cb67aSjsg 	    (iicprobew(0x07) & 0xfffc) == 0x2200 &&
906462cb67aSjsg 	    (iicprobew(0x00) & 0xff00) == 0x0000) {
907462cb67aSjsg 		name = "mcp98244";
9081ab2fcb9Scnst 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x11d4 &&
9096869b31aSderaadt 	    iicprobew(0x07) == 0x0800 &&
910e5f96281Sderaadt 	    iicprobew(0x00) == 0x001d) {
911e5f96281Sderaadt 		name = "adt7408";
9121ab2fcb9Scnst 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a &&
913273857bcSderaadt 	    (iicprobew(0x07) & 0xfffe) == 0x0000 &&
9145061e512Sderaadt 	    (iicprobew(0x00) == 0x002d || iicprobew(0x00) == 0x002f)) {
915273857bcSderaadt 		name = "stts424e02";
9166869b31aSderaadt 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a &&
917305d5022Sderaadt 	    (iicprobew(0x07) & 0xfffe) == 0x0300 &&
918305d5022Sderaadt 	    (iicprobew(0x00) == 0x006f)) {
919305d5022Sderaadt 		name = "stts2002";
920305d5022Sderaadt 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a &&
921462cb67aSjsg 	    (iicprobew(0x07) & 0xffff) == 0x2201 &&
922462cb67aSjsg 	    (iicprobew(0x00) == 0x00ef)) {
923462cb67aSjsg 		name = "stts2004";
924462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a &&
925462cb67aSjsg 	    (iicprobew(0x07) & 0xffff) == 0x0200 &&
926462cb67aSjsg 	    (iicprobew(0x00) == 0x006f)) {
927462cb67aSjsg 		name = "stts3000";
928462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x104a &&
9293f8e4e1eSjsg 	    (iicprobew(0x07) & 0xffff) == 0x0101 &&
9306869b31aSderaadt 	    (iicprobew(0x00) == 0x002d || iicprobew(0x00) == 0x002f)) {
9316869b31aSderaadt 		name = "stts424";
9321ab2fcb9Scnst 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1b09 &&
93370281b6fScnst 	    (iicprobew(0x07) & 0xffe0) == 0x0800 &&
934305d5022Sderaadt 	    (iicprobew(0x00) & 0x001f) == 0x001f) {
935305d5022Sderaadt 		name = "cat34ts02";		/* or cat6095, prod 0x0813 */
936462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1b09 &&
937462cb67aSjsg 	    (iicprobew(0x07) & 0xffff) == 0x0a00 &&
938462cb67aSjsg 	    (iicprobew(0x00) & 0x001f) == 0x001f) {
939462cb67aSjsg 		name = "cat34ts02c";
9400bd5d415Sjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1b09 &&
9410bd5d415Sjsg 	    (iicprobew(0x07) & 0xffff) == 0x2200 &&
9420bd5d415Sjsg 	    (iicprobew(0x00) == 0x007f)) {
9430bd5d415Sjsg 		name = "cat34ts04";
944305d5022Sderaadt 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 &&
945305d5022Sderaadt 	    (iicprobew(0x07) & 0xffff) == 0x2903 &&
946305d5022Sderaadt 	    (iicprobew(0x00) == 0x004f)) {
947305d5022Sderaadt 		name = "ts3000b3";		/* or tse2002b3 */
948462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 &&
949462cb67aSjsg 	    (iicprobew(0x07) & 0xffff) == 0x2912 &&
950462cb67aSjsg 	    (iicprobew(0x00) == 0x006f)) {
951462cb67aSjsg 		name = "ts3000gb2";		/* or tse2002gb2 */
952462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 &&
953462cb67aSjsg 	    (iicprobew(0x07) & 0xffff) == 0x2913 &&
954462cb67aSjsg 	    (iicprobew(0x00) == 0x0077)) {
955462cb67aSjsg 		name = "ts3000gb0";
956462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 &&
957462cb67aSjsg 	    (iicprobew(0x07) & 0xffff) == 0x3001 &&
958462cb67aSjsg 	    (iicprobew(0x00) == 0x006f)) {
959462cb67aSjsg 		name = "ts3001gb2";
9600bd5d415Sjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x00b3 &&
9610bd5d415Sjsg 	    (iicprobew(0x07) & 0xffff) == 0x2214 &&
9620bd5d415Sjsg 	    (iicprobew(0x00) == 0x00ff)) {
9630bd5d415Sjsg 		name = "tse2004gb2";
964462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x001f &&
965462cb67aSjsg 	    (iicprobew(0x07) & 0xffff) == 0x8201 &&
966462cb67aSjsg 	    (iicprobew(0x00) & 0xff00) == 0x0000) {
967462cb67aSjsg 		name = "at30ts00";		/* or at30tse002 */
968462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1114 &&
969462cb67aSjsg 	    (iicprobew(0x07) & 0xffff) == 0x2200 &&
970462cb67aSjsg 	    (iicprobew(0x00) & 0xff00) == 0x0000) {
971462cb67aSjsg 		name = "at30tse004";
972462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x1c68 &&
973462cb67aSjsg 	    (iicprobew(0x07) & 0xffff) == 0x2201 &&
974462cb67aSjsg 	    (iicprobew(0x00) & 0xff00) == 0x0000) {
975462cb67aSjsg 		name = "gt30ts00";
976462cb67aSjsg 	} else if ((addr & 0x78) == 0x18 && iicprobew(0x06) == 0x132d &&
977462cb67aSjsg 	    (iicprobew(0x07) & 0xffff) == 0x3300 &&
978462cb67aSjsg 	    (iicprobew(0x00) & 0x001f) == 0x001f) {
979462cb67aSjsg 		name = "gt34ts02";
980143beb10Scnst 	} else if ((addr & 0x7e) == 0x1c && iicprobe(0x0f) == 0x3b &&
981143beb10Scnst 	    (iicprobe(0x21) & 0x60) == 0x00 &&
982143beb10Scnst 	    iicprobe(0x0f) == iicprobe(0x8f) &&	/* registers address is 7 bits */
983143beb10Scnst 	    iicprobe(0x20) == iicprobe(0xa0) &&
984143beb10Scnst 	    iicprobe(0x21) == iicprobe(0xa1) &&
985143beb10Scnst 	    iicprobe(0x22) == iicprobe(0xa2) &&
986143beb10Scnst 	    iicprobe(0x07) == 0x00) {		/* 0x00 to 0x0e are reserved */
987143beb10Scnst 		name = "lis331dl";
988b3667398Skettenis 	} else if (name == NULL &&
9899ef2fefcSderaadt 	    (addr & 0x78) == 0x48) {		/* addr 0b1001xxx */
990010c3e6aSderaadt 		name = lm75probe();
9917535fb6fSderaadt 	}
992d5a0db9eSkettenis #if 0
993d5a0db9eSkettenis 	/*
994d5a0db9eSkettenis 	 * XXX This probe needs to be improved; the driver does some
995d5a0db9eSkettenis 	 * dangerous writes.
996d5a0db9eSkettenis 	 */
997b3667398Skettenis 	if (name == NULL && (addr & 0x7c) == 0x48 &&	/* addr 0b1001xxx */
9987535fb6fSderaadt 	    (iicprobew(0xaa) & 0x0007) == 0x0000 &&
9997535fb6fSderaadt 	    (iicprobew(0xa1) & 0x0007) == 0x0000 &&
10007535fb6fSderaadt 	    (iicprobew(0xa2) & 0x0007) == 0x0000 &&
10017535fb6fSderaadt 	    (iicprobe(0xac) & 0x10) == 0x00) {
10027535fb6fSderaadt 		if ((iicprobe(0xac) & 0x7e) == 0x0a &&
10037535fb6fSderaadt 		    iicprobe(0xab) == 0x00 && iicprobe(0xa8) == 0x00)
100465b3882dSderaadt 			name = "ds1624";
10057535fb6fSderaadt 		else if ((iicprobe(0xac) & 0x7e) == 0x0c)
10067535fb6fSderaadt 			name = "ds1631";	/* terrible probe */
1007a7654efdSderaadt 		else if ((iicprobe(0xac) & 0x2e) == 0x2e)
10087535fb6fSderaadt 			name = "ds1721";	/* terrible probe */
1009010c3e6aSderaadt 	}
1010d5a0db9eSkettenis #endif
10117540d812Sderaadt 	if (name == NULL && (addr & 0xf8) == 0x28 && iicprobe(0x48) == addr &&
10127540d812Sderaadt 	    (iicprobe(0x00) & 0x90) == 0x10 && iicprobe(0x58) == 0x90) {
10137540d812Sderaadt 		if (iicprobe(0x5b) == 0x12)
10147540d812Sderaadt 			name = "it8712";
10157540d812Sderaadt 		else if (iicprobe(0x5b) == 0x00)
101625f3e8a5Sderaadt 			name = "it8712f-a";		/* sis950 too */
10177540d812Sderaadt 	}
10187540d812Sderaadt 
1019b35edbb1Skettenis 	if (name == NULL && iicprobe(0x48) == addr &&
1020b35edbb1Skettenis 	    (iicprobe(0x40) & 0x80) == 0x00 && iicprobe(0x58) == 0xac)
1021b35edbb1Skettenis 		name = "mtp008";
1022b35edbb1Skettenis 
1023010c3e6aSderaadt 	if (name == NULL) {
10245f31ae5bSkettenis 		name = adm1032cloneprobe(addr);
1025e616dcecSderaadt 		if (name)
1026e616dcecSderaadt 			skip_fc = 1;
102774ce0e42Sderaadt 	}
10284e1e7e6eSderaadt 
102922ef5474Sderaadt 	return (name);
103022ef5474Sderaadt }
103122ef5474Sderaadt 
103222ef5474Sderaadt char *
10331c658e45Scnst iic_probe_eeprom(struct device *self, u_int8_t addr)
103422ef5474Sderaadt {
1035dfbc0705Sjsg 	u_int8_t type;
103622ef5474Sderaadt 	char *name = NULL;
103722ef5474Sderaadt 
1038dfbc0705Sjsg 	type = iicprobe(0x02);
1039dfbc0705Sjsg 	/* limit to SPD types seen in the wild */
104061624148Sclaudio 	if (type < 4 || type > 16)
104147be2d17Sjsg 		return (name);
104247be2d17Sjsg 
1043dfbc0705Sjsg 	/* more matching in driver(s) */
1044dfbc0705Sjsg 	name = "eeprom";
104522ef5474Sderaadt 
104622ef5474Sderaadt 	return (name);
104747098ca3Sderaadt }
1048941c1a56Sderaadt 
10491165b4a3Sgrange void
10501165b4a3Sgrange iic_scan(struct device *self, struct i2cbus_attach_args *iba)
10511165b4a3Sgrange {
10521165b4a3Sgrange 	i2c_tag_t ic = iba->iba_tag;
105322ef5474Sderaadt 	struct i2c_attach_args ia;
105422ef5474Sderaadt 	struct iicprobelist *pl;
105548a89adfSderaadt 	u_int8_t cmd = 0, addr;
105622ef5474Sderaadt 	char *name;
1057717c6620Scnst 	int i, j, k;
10581165b4a3Sgrange 
1059b8fabd7dSderaadt 	bzero(ignore_addrs, sizeof(ignore_addrs));
106022ef5474Sderaadt 
106122ef5474Sderaadt 	for (i = 0; probes[i].probe; i++) {
10622349585bSderaadt #if NIPMI > 0
10632349585bSderaadt 		extern int ipmi_enabled;
10642349585bSderaadt 
10652349585bSderaadt 		if ((probes[i].flags & PFLAG_SENSOR) && ipmi_enabled) {
10662349585bSderaadt 			printf("%s: skipping sensors to avoid ipmi0 interactions\n",
10672349585bSderaadt 			    self->dv_xname);
10682349585bSderaadt 			continue;
10692349585bSderaadt 		}
10702349585bSderaadt #endif
107122ef5474Sderaadt 		pl = probes[i].pl;
107222ef5474Sderaadt 		for (j = 0; pl[j].start && pl[j].end; j++) {
107322ef5474Sderaadt 			for (addr = pl[j].start; addr <= pl[j].end; addr++) {
1074717c6620Scnst 				for (k = 0; k < sizeof(ignore_addrs); k++)
1075717c6620Scnst 					if (ignore_addrs[k] == addr)
107631309405Scnst 						break;
107731309405Scnst 				if (k < sizeof(ignore_addrs))
1078717c6620Scnst 					continue;
1079717c6620Scnst 
1080941c1a56Sderaadt 				/* Perform RECEIVE BYTE command */
1081a5d919cdSgrange 				iic_acquire_bus(ic, 0);
1082643d52faSgrange 				if (iic_exec(ic, I2C_OP_READ_WITH_STOP, addr,
108391eacc75Sderaadt 				    &cmd, sizeof cmd, NULL, 0, 0) == 0) {
1084a5d919cdSgrange 					iic_release_bus(ic, 0);
108547098ca3Sderaadt 
108622ef5474Sderaadt 					/* Some device exists */
108722ef5474Sderaadt 					iicprobeinit(iba, addr);
10881c658e45Scnst 					name = (*probes[i].probe)(self, addr);
1089d70d6113Scnst #ifndef I2C_VERBOSE
1090d70d6113Scnst 					if (name == NULL)
1091d70d6113Scnst 						name = "unknown";
1092d70d6113Scnst #endif /* !I2C_VERBOSE */
109322ef5474Sderaadt 					if (name) {
109422ef5474Sderaadt 						memset(&ia, 0, sizeof(ia));
109522ef5474Sderaadt 						ia.ia_tag = iba->iba_tag;
109622ef5474Sderaadt 						ia.ia_addr = addr;
109722ef5474Sderaadt 						ia.ia_size = 1;
109822ef5474Sderaadt 						ia.ia_name = name;
1099d70d6113Scnst 						if (config_found(self,
1100d70d6113Scnst 						    &ia, iic_print))
1101d70d6113Scnst 							continue;
11021165b4a3Sgrange 					}
1103d70d6113Scnst #ifdef I2C_VERBOSE
1104ae06ac7aSderaadt 					if ((probes[i].flags & PFLAG_SENSOR))
1105d70d6113Scnst 						iic_dump(self, addr, name);
1106d70d6113Scnst #endif /* I2C_VERBOSE */
110722ef5474Sderaadt 				} else
1108a5d919cdSgrange 					iic_release_bus(ic, 0);
11091165b4a3Sgrange 			}
1110941c1a56Sderaadt 		}
11111165b4a3Sgrange 	}
111222ef5474Sderaadt }
1113