hwmon: (lm75) Add detection of the National Semiconductor LM75A

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>
diff --git a/Documentation/hwmon/lm75 b/Documentation/hwmon/lm75
index 8e6356f..a179040 100644
--- a/Documentation/hwmon/lm75
+++ b/Documentation/hwmon/lm75
@@ -7,6 +7,11 @@
     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
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 47621ab..19d72bc 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -521,7 +521,7 @@
 		- 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
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index f36eb80..638dd05 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -232,6 +232,8 @@
 };
 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 @@
 	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 @@
 	   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.
 
-	/* Unused addresses */
+	   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. */
+
 	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 @@
 		 || 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;
 }