Skip to content

Commit

Permalink
hwmon: (lm80) Add detection of NatSemi/TI LM96080
Browse files Browse the repository at this point in the history
Add detection of the National Semiconductor (now Texas Instruments)
LM96080. It is functionally compatible with the LM80 but detection is
completely different.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Guenter Roeck <guenter.roeck@ericsson.com>
Cc: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
  • Loading branch information
Jean Delvare authored and Guenter Roeck committed Mar 19, 2012
1 parent 0e190b7 commit 9908ad4
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 12 deletions.
9 changes: 8 additions & 1 deletion Documentation/hwmon/lm80
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand All @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions drivers/hwmon/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
44 changes: 35 additions & 9 deletions drivers/hwmon/lm80.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 9908ad4

Please sign in to comment.