aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/hwmon/lm90.rst16
-rw-r--r--drivers/hwmon/Kconfig5
-rw-r--r--drivers/hwmon/lm90.c78
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);