Improve chip detection in ADM1021 driver to avoid misdetections

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJRsz1aAAoJEMsfJm/On5mBpq8QAKydDEjh16CnScNzjqED6vgv
 lLXBlD7/WeJcyqd6yktVM5tigkSblyZiyn9ydJ9s+3IcI4NBVBYse3n2Bu37Daet
 AfeCHnwVfyKJdIs+wpWyZs7nI2xJn4SHmulV2fKL2HC3GosyRA/A7b5Oodxs+3Jj
 5qtYeAMxCaUYbmJu9otx6FmJQgrQErjPBKJvawhQs9aMfzohzSVSfQOXCiPS8HGX
 Pyu7oUEvbbpS40dsGe4LuP1oA8oMXJM8OOl2MiJnAUQB7+J/uE+H2ztkoWE2vyMt
 n2rX+sjEz+G+JbFUAfvXBNqHLoVvceQcZ1GCBD1y33VJxhLzqVsm+O6fGqlq16pK
 FNV8r4tn+KrO+P0EuCSCKm2TwhP1+cWf4GM7VygUktMKtIYB5/CAtyy/XkRDexcD
 NLe0rjzQ/XRuvZyOnnPVt6QqNfGJVnVSrSM06KSsiHBHsKry20ne2ycEFWnGASFT
 5LBz+r6en4D3qBV0mldrMy4rEUDi0eFnqC7YRvrQEYxQl+x9vzr9Tkd7Kn+vdKri
 /qNtqY8FsaHFhaUVsB/tPHRooAM0Xoweqp307YjKtiycemx6mlQnuXOKplCmHLTn
 VXTvmsMA2EQMSgF2ZPW8yn5eZeaja5RcBpjM9crdCIRAgAjYw+B6IFC44g9GaOlJ
 kV26YR8WyOfsPdK24Dxs
 =lVk4
 -----END PGP SIGNATURE-----

Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging

Pull hwmon fix from Guenter Roeck:
 "Improve chip detection in ADM1021 driver to avoid misdetections

  This is not a critical patch, but one we'll want to have applied to
  -stable, since the misdetection especially of LM84 has been causing
  trouble for quite some time."

* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
  hwmon: (adm1021) Strengthen chip detection for ADM1021, LM84 and MAX1617
This commit is contained in:
Linus Torvalds 2013-06-09 14:56:48 -07:00
commit 6dbda5bfe1

View file

@ -331,26 +331,68 @@ static int adm1021_detect(struct i2c_client *client,
man_id = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_ID);
dev_id = i2c_smbus_read_byte_data(client, ADM1021_REG_DEV_ID);
if (man_id < 0 || dev_id < 0)
return -ENODEV;
if (man_id == 0x4d && dev_id == 0x01)
type_name = "max1617a";
else if (man_id == 0x41) {
if ((dev_id & 0xF0) == 0x30)
type_name = "adm1023";
else
else if ((dev_id & 0xF0) == 0x00)
type_name = "adm1021";
else
return -ENODEV;
} else if (man_id == 0x49)
type_name = "thmc10";
else if (man_id == 0x23)
type_name = "gl523sm";
else if (man_id == 0x54)
type_name = "mc1066";
/* LM84 Mfr ID in a different place, and it has more unused bits */
else if (conv_rate == 0x00
&& (config & 0x7F) == 0x00
&& (status & 0xAB) == 0x00)
type_name = "lm84";
else
type_name = "max1617";
else {
int lte, rte, lhi, rhi, llo, rlo;
/* extra checks for LM84 and MAX1617 to avoid misdetections */
llo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(0));
rlo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(1));
/* fail if any of the additional register reads failed */
if (llo < 0 || rlo < 0)
return -ENODEV;
lte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(0));
rte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(1));
lhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(0));
rhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(1));
/*
* Fail for negative temperatures and negative high limits.
* This check also catches read errors on the tested registers.
*/
if ((s8)lte < 0 || (s8)rte < 0 || (s8)lhi < 0 || (s8)rhi < 0)
return -ENODEV;
/* fail if all registers hold the same value */
if (lte == rte && lte == lhi && lte == rhi && lte == llo
&& lte == rlo)
return -ENODEV;
/*
* LM84 Mfr ID is in a different place,
* and it has more unused bits.
*/
if (conv_rate == 0x00
&& (config & 0x7F) == 0x00
&& (status & 0xAB) == 0x00) {
type_name = "lm84";
} else {
/* fail if low limits are larger than high limits */
if ((s8)llo > lhi || (s8)rlo > rhi)
return -ENODEV;
type_name = "max1617";
}
}
pr_debug("Detected chip %s at adapter %d, address 0x%02x.\n",
type_name, i2c_adapter_id(adapter), client->addr);