]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
hwmon: (lm90) Add basic support for TI TMP461
authorGuenter Roeck <linux@roeck-us.net>
Tue, 19 Oct 2021 03:03:32 +0000 (20:03 -0700)
committerGuenter Roeck <linux@roeck-us.net>
Thu, 28 Oct 2021 02:48:19 +0000 (19:48 -0700)
TMP461 is almost identical to TMP451 and was actually detected as TMP451
with the existing lm90 driver if its I2C address is 0x4c. Add support
for it to the lm90 driver. At the same time, improve the chip detection
function to at least try to distinguish between TMP451 and TMP461.

As a side effect, this fixes commit 24333ac26d01 ("hwmon: (tmp401) use
smb word operations instead of 2 smb byte operations"). TMP461 does not
support word operations on temperature registers, which causes bad
temperature readings with the tmp401 driver. The lm90 driver does not
perform word operations on temperature registers and thus does not have
this problem.

Support is listed as basic because TMP461 supports a sensor resolution
of 0.0625 degrees C, while the lm90 driver assumes a resolution of 0.125
degrees C. Also, the TMP461 supports negative temperatures with its
default temperature range, which is not the case for similar chips
supported by the lm90 and the tmp401 drivers. Those limitations will be
addressed with follow-up patches.

Fixes: 24333ac26d01 ("hwmon: (tmp401) use smb word operations instead of 2 smb byte operations")
Reported-by: David T. Wilson <david.wilson@nasa.gov>
Cc: David T. Wilson <david.wilson@nasa.gov>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Documentation/hwmon/lm90.rst
drivers/hwmon/Kconfig
drivers/hwmon/lm90.c

index 3da8c6e06a365d0f440116530d542d8bddbe0faf..05391fb4042d96d1a00fa386cf638d569204772c 100644 (file)
@@ -265,6 +265,16 @@ Supported chips:
 
               https://www.ti.com/litv/pdf/sbos686
 
+  * Texas Instruments TMP461
+
+    Prefix: 'tmp461'
+
+    Addresses scanned: I2C 0x48 through 0x4F
+
+    Datasheet: Publicly available at TI website
+
+              https://www.ti.com/lit/gpn/tmp461
+
 Author: Jean Delvare <jdelvare@suse.de>
 
 
index 7fde4c6e1e7fb1d0e036383c29ed12e4f5472893..8c776fb9244570562052a16c61de7b675a20cec6 100644 (file)
@@ -1327,7 +1327,7 @@ config SENSORS_LM90
          Maxim 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, and Texas Instruments TMP451
+         Philips SA56004, GMT G781, Texas Instruments TMP451 and TMP461
          sensor chips.
 
          This driver can also be built as a module. If so, the module
index 1a1d7bfcb30b06a6548ef6bcdc671387ff891f8a..618052c6cdb6458f85fdd7ae91b95f72a3c19512 100644 (file)
  * This driver also supports the G781 from GMT. This device is compatible
  * with the ADM1032.
  *
- * This driver also supports TMP451 from Texas Instruments. This device is
- * supported in both compatibility and extended mode. It's mostly compatible
- * with ADT7461 except for local temperature low byte register and max
- * conversion rate.
+ * This driver also supports TMP451 and TMP461 from Texas Instruments.
+ * Those devices are supported in both compatibility and extended mode.
+ * They are mostly compatible with ADT7461 except for local temperature
+ * low byte register and max conversion rate.
  *
  * Since the LM90 was the first chipset supported by this driver, most
  * comments will refer to this chipset, but are actually general and
@@ -112,7 +112,7 @@ static const unsigned short normal_i2c[] = {
        0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
 
 enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
-       max6646, w83l771, max6696, sa56004, g781, tmp451, max6654 };
+       max6646, w83l771, max6696, sa56004, g781, tmp451, tmp461, max6654 };
 
 /*
  * The LM90 registers
@@ -168,8 +168,12 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
 
 #define LM90_MAX_CONVRATE_MS   16000   /* Maximum conversion rate in ms */
 
-/* TMP451 registers */
+/* TMP451/TMP461 registers */
 #define TMP451_REG_R_LOCAL_TEMPL       0x15
+#define TMP451_REG_CONALERT            0x22
+
+#define TMP461_REG_CHEN                        0x16
+#define TMP461_REG_DFC                 0x24
 
 /*
  * Device flags
@@ -230,6 +234,7 @@ static const struct i2c_device_id lm90_id[] = {
        { "w83l771", w83l771 },
        { "sa56004", sa56004 },
        { "tmp451", tmp451 },
+       { "tmp461", tmp461 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, lm90_id);
@@ -327,6 +332,10 @@ static const struct of_device_id __maybe_unused lm90_of_match[] = {
                .compatible = "ti,tmp451",
                .data = (void *)tmp451
        },
+       {
+               .compatible = "ti,tmp461",
+               .data = (void *)tmp461
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, lm90_of_match);
@@ -428,6 +437,13 @@ static const struct lm90_params lm90_params[] = {
                .max_convrate = 9,
                .reg_local_ext = TMP451_REG_R_LOCAL_TEMPL,
        },
+       [tmp461] = {
+               .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
+                 | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP,
+               .alert_alarms = 0x7c,
+               .max_convrate = 9,
+               .reg_local_ext = TMP451_REG_R_LOCAL_TEMPL,
+       },
 };
 
 /*
@@ -1628,18 +1644,26 @@ static int lm90_detect(struct i2c_client *client,
                 && convrate <= 0x08)
                        name = "g781";
        } else
-       if (address == 0x4C
-        && man_id == 0x55) { /* Texas Instruments */
-               int local_ext;
+       if (man_id == 0x55 && chip_id == 0x00 &&
+           (config1 & 0x1B) == 0x00 && convrate <= 0x09) {
+               int local_ext, conalert, chen, dfc;
 
                local_ext = i2c_smbus_read_byte_data(client,
                                                     TMP451_REG_R_LOCAL_TEMPL);
-
-               if (chip_id == 0x00 /* TMP451 */
-                && (config1 & 0x1B) == 0x00
-                && convrate <= 0x09
-                && (local_ext & 0x0F) == 0x00)
-                       name = "tmp451";
+               conalert = i2c_smbus_read_byte_data(client,
+                                                   TMP451_REG_CONALERT);
+               chen = i2c_smbus_read_byte_data(client, TMP461_REG_CHEN);
+               dfc = i2c_smbus_read_byte_data(client, TMP461_REG_DFC);
+
+               if ((local_ext & 0x0F) == 0x00 &&
+                   (conalert & 0xf1) == 0x01 &&
+                   (chen & 0xfc) == 0x00 &&
+                   (dfc & 0xfc) == 0x00) {
+                       if (address == 0x4c && !(chen & 0x03))
+                               name = "tmp451";
+                       else if (address >= 0x48 && address <= 0x4f)
+                               name = "tmp461";
+               }
        }
 
        if (!name) { /* identification failed */