diff options
-rw-r--r-- | Documentation/hwmon/lm90.rst | 16 | ||||
-rw-r--r-- | drivers/hwmon/Kconfig | 5 | ||||
-rw-r--r-- | drivers/hwmon/lm90.c | 78 |
3 files changed, 83 insertions, 16 deletions
diff --git a/Documentation/hwmon/lm90.rst b/Documentation/hwmon/lm90.rst index 45bc333a1219..313b18f6531d 100644 --- a/Documentation/hwmon/lm90.rst +++ b/Documentation/hwmon/lm90.rst @@ -113,6 +113,16 @@ Supported chips: https://www.onsemi.com/PowerSolutions/product.do?id=NCT1008 + * Maxim MAX6642 + + Prefix: 'max6642' + + Addresses scanned: I2C 0x48-0x4f + + Datasheet: Publicly available at the Maxim website + + http://datasheets.maxim-ic.com/en/ds/MAX6642.pdf + * Maxim MAX6646 Prefix: 'max6646' @@ -362,6 +372,12 @@ ADT7481, ADT7482, ADT7483: * Two remote sensors * Selectable address (ADT7483) +MAX6642: + * No critical limit register + * Conversion rate not configurable + * Better local resolution (10 bit) + * 10 bit external sensor resolution + MAX6646, MAX6647, MAX6649: * Better local resolution * Extended range unsigned external temperature diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index df54628bd36b..39ce1b2ccbb3 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1102,6 +1102,7 @@ config SENSORS_MAX6639 config SENSORS_MAX6642 tristate "Maxim MAX6642 sensor chip" depends on I2C + depends on SENSORS_LM90=n help If you say yes here you get support for MAX6642 sensor chip. MAX6642 is a SMBus-Compatible Remote/Local Temperature Sensor @@ -1360,8 +1361,8 @@ config SENSORS_LM90 If you say yes here you get support for National Semiconductor LM90, LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, ADT7461A, ADT7481, ADT7482, and ADT7483A, - Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6654, MAX6657, MAX6658, - MAX6659, MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, + Maxim MAX6642, MAX6646, MAX6647, MAX6648, MAX6649, MAX6654, MAX6657, + MAX6658, MAX6659, MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008, Winbond/Nuvoton W83L771W/G/AWG/ASG, Philips SA56004, GMT G781, Texas Instruments TMP451 and TMP461 sensor chips. diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index ae14b0f60100..181fc1efaa47 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -120,7 +120,7 @@ static const unsigned short normal_i2c[] = { 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; enum chips { adm1032, adt7461, adt7461a, adt7481, g781, lm86, lm90, lm99, - max6646, max6648, max6654, max6657, max6659, max6680, max6696, + max6642, max6646, max6648, max6654, max6657, max6659, max6680, max6696, sa56004, tmp451, tmp461, w83l771, }; @@ -230,6 +230,7 @@ static const struct i2c_device_id lm90_id[] = { { "lm86", lm86 }, { "lm89", lm86 }, { "lm99", lm99 }, + { "max6642", max6642 }, { "max6646", max6646 }, { "max6647", max6646 }, { "max6648", max6648 }, @@ -434,6 +435,12 @@ static const struct lm90_params lm90_params[] = { .alert_alarms = 0x7b, .max_convrate = 9, }, + [max6642] = { + .flags = LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXT_UNSIGNED, + .alert_alarms = 0x50, + .reg_local_ext = MAX6657_REG_LOCAL_TEMPL, + .resolution = 10, + }, [max6646] = { .flags = LM90_HAVE_CRIT | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXT_UNSIGNED | LM90_HAVE_ALARMS | LM90_HAVE_LOW @@ -1668,18 +1675,18 @@ static const char *lm90_detect_analog(struct i2c_client *client, int chip_id, return name; } -static const char *lm90_detect_maxim(struct i2c_client *client, int chip_id, - int config1, int convrate) +static const char *lm90_detect_maxim(struct i2c_client *client, bool common_address, + int chip_id, int config1, int convrate) { int man_id, emerg, emerg2, status2; int address = client->addr; const char *name = NULL; - if ((address >= 0x48 && address <= 0x4b) || address == 0x4f) - return NULL; - switch (chip_id) { case 0x01: + if (!common_address) + break; + /* * We read MAX6659_REG_REMOTE_EMERG twice, and re-read * LM90_REG_MAN_ID in between. If MAX6659_REG_REMOTE_EMERG @@ -1726,7 +1733,7 @@ static const char *lm90_detect_maxim(struct i2c_client *client, int chip_id, * The lowest 3 bits of the config1 register are unused and * should return zero when read. */ - if (!(config1 & 0x07) && convrate <= 0x07) + if (common_address && !(config1 & 0x07) && convrate <= 0x07) name = "max6654"; break; case 0x09: @@ -1739,16 +1746,21 @@ static const char *lm90_detect_maxim(struct i2c_client *client, int chip_id, * MAX6690 datasheet lists a chip ID of 0x08, and a chip labeled * MAX6654 was observed to have a chip ID of 0x09. */ - if (!(config1 & 0x07) && convrate <= 0x07) + if (common_address && !(config1 & 0x07) && convrate <= 0x07) name = "max6690"; break; case 0x4d: /* - * The MAX6657, MAX6658 and MAX6659 do NOT have a chip_id + * MAX6642, MAX6657, MAX6658 and MAX6659 do NOT have a chip_id * register. Reading from that address will return the last * read value, which in our case is those of the man_id - * register, or 0x4d. Likewise, the config1 register seems to - * lack a low nibble, so the value will be those of the previous + * register, or 0x4d. + * MAX6642 does not have a conversion rate register, nor low + * limit registers. Reading from those registers returns the + * last read value. + * + * For MAX6657, MAX6658 and MAX6659, the config1 register lacks + * a low nibble, so the value will be those of the previous * read, so in our case again those of the man_id register. * MAX6659 has a third set of upper temperature limit registers. * Those registers also return values on MAX6657 and MAX6658, @@ -1756,8 +1768,40 @@ static const char *lm90_detect_maxim(struct i2c_client *client, int chip_id, * For this reason it will be mis-detected as MAX6657 if its * address is 0x4c. */ - if ((address == 0x4c || address == 0x4d || address == 0x4e) && - (config1 & 0x1f) == 0x0d && convrate <= 0x09) { + if (address >= 0x48 && address <= 0x4f && config1 == convrate && + !(config1 & 0x0f)) { + int regval; + + /* + * We know that this is not a MAX6657/58/59 because its + * configuration register has the wrong value and it does + * not appear to have a conversion rate register. + */ + + /* re-read manufacturer ID to have a good baseline */ + if (i2c_smbus_read_byte_data(client, LM90_REG_MAN_ID) != 0x4d) + break; + + /* check various non-existing registers */ + if (i2c_smbus_read_byte_data(client, LM90_REG_CONVRATE) != 0x4d || + i2c_smbus_read_byte_data(client, LM90_REG_LOCAL_LOW) != 0x4d || + i2c_smbus_read_byte_data(client, LM90_REG_REMOTE_LOWH) != 0x4d) + break; + + /* check for unused status register bits */ + regval = i2c_smbus_read_byte_data(client, LM90_REG_STATUS); + if (regval < 0 || (regval & 0x2b)) + break; + + /* re-check unsupported registers */ + if (i2c_smbus_read_byte_data(client, LM90_REG_CONVRATE) != regval || + i2c_smbus_read_byte_data(client, LM90_REG_LOCAL_LOW) != regval || + i2c_smbus_read_byte_data(client, LM90_REG_REMOTE_LOWH) != regval) + break; + + name = "max6642"; + } else if ((address == 0x4c || address == 0x4d || address == 0x4e) && + (config1 & 0x1f) == 0x0d && convrate <= 0x09) { if (address == 0x4c) name = "max6657"; else @@ -1929,6 +1973,11 @@ static int lm90_detect(struct i2c_client *client, struct i2c_board_info *info) struct i2c_adapter *adapter = client->adapter; int man_id, chip_id, config1, convrate; const char *name = NULL; + int address = client->addr; + bool common_address = + (address >= 0x18 && address <= 0x1a) || + (address >= 0x29 && address <= 0x2b) || + (address >= 0x4c && address <= 0x4e); if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; @@ -1952,7 +2001,8 @@ static int lm90_detect(struct i2c_client *client, struct i2c_board_info *info) name = lm90_detect_gmt(client, chip_id, config1, convrate); break; case 0x4d: /* Maxim Integrated */ - name = lm90_detect_maxim(client, chip_id, config1, convrate); + name = lm90_detect_maxim(client, common_address, chip_id, + config1, convrate); break; case 0x55: /* TI */ name = lm90_detect_ti(client, chip_id, config1, convrate); |