hwmon: (lm75) Add detection of the National Semiconductor LM75A
authorLen Sorensen <lsorense@csclub.uwaterloo.ca>
Mon, 21 Mar 2011 16:59:36 +0000 (17:59 +0100)
committerJean Delvare <khali@endymion.delvare>
Mon, 21 Mar 2011 16:59:36 +0000 (17:59 +0100)
Add support for detection of the National Semiconductor LM75A using the ID
register value.

Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Jean Delvare <khali@linux-fr.org>

Documentation/hwmon/lm75
drivers/hwmon/Kconfig
drivers/hwmon/lm75.c

index 8e6356f..a179040 100644 (file)
@@ -7,6 +7,11 @@ Supported chips:
     Addresses scanned: I2C 0x48 - 0x4f
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/
+  * National Semiconductor LM75A
+    Prefix: 'lm75a'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
   * Dallas Semiconductor DS75
     Prefix: 'lm75'
     Addresses scanned: I2C 0x48 - 0x4f
index 47621ab..19d72bc 100644 (file)
@@ -521,7 +521,7 @@ config SENSORS_LM75
                - Dallas Semiconductor DS75 and DS1775
                - Maxim MAX6625 and MAX6626
                - Microchip MCP980x
-               - National Semiconductor LM75
+               - National Semiconductor LM75, LM75A
                - NXP's LM75A
                - ST Microelectronics STDS75
                - TelCom (now Microchip) TCN75
index f36eb80..638dd05 100644 (file)
@@ -232,6 +232,8 @@ static const struct i2c_device_id lm75_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, lm75_ids);
 
+#define LM75A_ID 0xA1
+
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int lm75_detect(struct i2c_client *new_client,
                       struct i2c_board_info *info)
@@ -239,6 +241,7 @@ static int lm75_detect(struct i2c_client *new_client,
        struct i2c_adapter *adapter = new_client->adapter;
        int i;
        int cur, conf, hyst, os;
+       bool is_lm75a = 0;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
                                     I2C_FUNC_SMBUS_WORD_DATA))
@@ -250,23 +253,43 @@ static int lm75_detect(struct i2c_client *new_client,
           addresses 0x04-0x07 returning the last read value.
           The cycling+unused addresses combination is not tested,
           since it would significantly slow the detection down and would
-          hardly add any value. */
+          hardly add any value.
+
+          The National Semiconductor LM75A is different than earlier
+          LM75s.  It has an ID byte of 0xaX (where X is the chip
+          revision, with 1 being the only revision in existence) in
+          register 7, and unused registers return 0xff rather than the
+          last read value. */
 
-       /* Unused addresses */
        cur = i2c_smbus_read_word_data(new_client, 0);
        conf = i2c_smbus_read_byte_data(new_client, 1);
-       hyst = i2c_smbus_read_word_data(new_client, 2);
-       if (i2c_smbus_read_word_data(new_client, 4) != hyst
-        || i2c_smbus_read_word_data(new_client, 5) != hyst
-        || i2c_smbus_read_word_data(new_client, 6) != hyst
-        || i2c_smbus_read_word_data(new_client, 7) != hyst)
-               return -ENODEV;
-       os = i2c_smbus_read_word_data(new_client, 3);
-       if (i2c_smbus_read_word_data(new_client, 4) != os
-        || i2c_smbus_read_word_data(new_client, 5) != os
-        || i2c_smbus_read_word_data(new_client, 6) != os
-        || i2c_smbus_read_word_data(new_client, 7) != os)
-               return -ENODEV;
+
+       /* First check for LM75A */
+       if (i2c_smbus_read_byte_data(new_client, 7) == LM75A_ID) {
+               /* LM75A returns 0xff on unused registers so
+                  just to be sure we check for that too. */
+               if (i2c_smbus_read_byte_data(new_client, 4) != 0xff
+                || i2c_smbus_read_byte_data(new_client, 5) != 0xff
+                || i2c_smbus_read_byte_data(new_client, 6) != 0xff)
+                       return -ENODEV;
+               is_lm75a = 1;
+               hyst = i2c_smbus_read_word_data(new_client, 2);
+               os = i2c_smbus_read_word_data(new_client, 3);
+       } else { /* Traditional style LM75 detection */
+               /* Unused addresses */
+               hyst = i2c_smbus_read_word_data(new_client, 2);
+               if (i2c_smbus_read_word_data(new_client, 4) != hyst
+                || i2c_smbus_read_word_data(new_client, 5) != hyst
+                || i2c_smbus_read_word_data(new_client, 6) != hyst
+                || i2c_smbus_read_word_data(new_client, 7) != hyst)
+                       return -ENODEV;
+               os = i2c_smbus_read_word_data(new_client, 3);
+               if (i2c_smbus_read_word_data(new_client, 4) != os
+                || i2c_smbus_read_word_data(new_client, 5) != os
+                || i2c_smbus_read_word_data(new_client, 6) != os
+                || i2c_smbus_read_word_data(new_client, 7) != os)
+                       return -ENODEV;
+       }
 
        /* Unused bits */
        if (conf & 0xe0)
@@ -278,9 +301,12 @@ static int lm75_detect(struct i2c_client *new_client,
                 || i2c_smbus_read_word_data(new_client, i + 2) != hyst
                 || i2c_smbus_read_word_data(new_client, i + 3) != os)
                        return -ENODEV;
+               if (is_lm75a && i2c_smbus_read_byte_data(new_client, i + 7)
+                               != LM75A_ID)
+                       return -ENODEV;
        }
 
-       strlcpy(info->type, "lm75", I2C_NAME_SIZE);
+       strlcpy(info->type, is_lm75a ? "lm75a" : "lm75", I2C_NAME_SIZE);
 
        return 0;
 }