summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/hwmon/lm809
-rw-r--r--drivers/hwmon/Kconfig4
-rw-r--r--drivers/hwmon/lm80.c44
3 files changed, 45 insertions, 12 deletions
diff --git a/Documentation/hwmon/lm80 b/Documentation/hwmon/lm80
index cb5b407ba3e6..a60b43efc32b 100644
--- a/Documentation/hwmon/lm80
+++ b/Documentation/hwmon/lm80
@@ -7,6 +7,11 @@ Supported chips:
Addresses scanned: I2C 0x28 - 0x2f
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/
+ * National Semiconductor LM96080
+ Prefix: 'lm96080'
+ Addresses scanned: I2C 0x28 - 0x2f
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/
Authors:
Frodo Looijaard <frodol@dds.nl>,
@@ -17,7 +22,9 @@ Description
This driver implements support for the National Semiconductor LM80.
It is described as a 'Serial Interface ACPI-Compatible Microprocessor
-System Hardware Monitor'.
+System Hardware Monitor'. The LM96080 is a more recent incarnation,
+it is pin and register compatible, with a few additional features not
+yet supported by the driver.
The LM80 implements one temperature sensor, two fan rotation speed sensors,
seven voltage sensors, alarms, and some miscellaneous stuff.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index dad895fec62a..1cd0e201819c 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -598,11 +598,11 @@ config SENSORS_LM78
will be called lm78.
config SENSORS_LM80
- tristate "National Semiconductor LM80"
+ tristate "National Semiconductor LM80 and LM96080"
depends on I2C
help
If you say yes here you get support for National Semiconductor
- LM80 sensor chips.
+ LM80 and LM96080 sensor chips.
This driver can also be built as a module. If so, the module
will be called lm80.
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index a996f2795db0..e2c43e1774be 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -60,6 +60,10 @@ static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
#define LM80_REG_FANDIV 0x05
#define LM80_REG_RES 0x06
+#define LM96080_REG_CONV_RATE 0x07
+#define LM96080_REG_MAN_ID 0x3e
+#define LM96080_REG_DEV_ID 0x3f
+
/*
* Conversions. Rounding and limit checking is only done on the TO_REG
@@ -147,6 +151,7 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
static const struct i2c_device_id lm80_id[] = {
{ "lm80", 0 },
+ { "lm96080", 1 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm80_id);
@@ -490,23 +495,44 @@ static const struct attribute_group lm80_group = {
static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
- int i, cur;
+ int i, cur, man_id, dev_id;
+ const char *name = NULL;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
- /* Now, we do the remaining detection. It is lousy. */
- if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0)
+ /* First check for unused bits, common to both chip types */
+ if ((lm80_read_value(client, LM80_REG_ALARM2) & 0xc0)
+ || (lm80_read_value(client, LM80_REG_CONFIG) & 0x80))
return -ENODEV;
- for (i = 0x2a; i <= 0x3d; i++) {
- cur = i2c_smbus_read_byte_data(client, i);
- if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur)
- || (i2c_smbus_read_byte_data(client, i + 0x80) != cur)
- || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur))
+
+ /*
+ * The LM96080 has manufacturer and stepping/die rev registers so we
+ * can just check that. The LM80 does not have such registers so we
+ * have to use a more expensive trick.
+ */
+ man_id = lm80_read_value(client, LM96080_REG_MAN_ID);
+ dev_id = lm80_read_value(client, LM96080_REG_DEV_ID);
+ if (man_id == 0x01 && dev_id == 0x08) {
+ /* Check more unused bits for confirmation */
+ if (lm80_read_value(client, LM96080_REG_CONV_RATE) & 0xfe)
return -ENODEV;
+
+ name = "lm96080";
+ } else {
+ /* Check 6-bit addressing */
+ for (i = 0x2a; i <= 0x3d; i++) {
+ cur = i2c_smbus_read_byte_data(client, i);
+ if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur)
+ || (i2c_smbus_read_byte_data(client, i + 0x80) != cur)
+ || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur))
+ return -ENODEV;
+ }
+
+ name = "lm80";
}
- strlcpy(info->type, "lm80", I2C_NAME_SIZE);
+ strlcpy(info->type, name, I2C_NAME_SIZE);
return 0;
}