hwmon: (lm80) Add detection of NatSemi/TI LM96080
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>
This commit is contained in:
Родитель
0e190b7fa3
Коммит
9908ad4cd4
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче