diff options
author | Jean Delvare <khali@linux-fr.org> | 2012-01-31 09:27:11 -0500 |
---|---|---|
committer | Guenter Roeck <guenter.roeck@ericsson.com> | 2012-03-18 21:27:43 -0400 |
commit | 9908ad4cd4bc3e6620e1819e7f9b43f109650e1b (patch) | |
tree | a1fd79fa9119c908e05a74f8207ba23f94566c24 /drivers | |
parent | 0e190b7fa330f19afed9e12d551432b8659886c7 (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/Kconfig | 4 | ||||
-rw-r--r-- | drivers/hwmon/lm80.c | 44 |
2 files changed, 37 insertions, 11 deletions
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 | |||
598 | will be called lm78. | 598 | will be called lm78. |
599 | 599 | ||
600 | config SENSORS_LM80 | 600 | config SENSORS_LM80 |
601 | tristate "National Semiconductor LM80" | 601 | tristate "National Semiconductor LM80 and LM96080" |
602 | depends on I2C | 602 | depends on I2C |
603 | help | 603 | help |
604 | If you say yes here you get support for National Semiconductor | 604 | If you say yes here you get support for National Semiconductor |
605 | LM80 sensor chips. | 605 | LM80 and LM96080 sensor chips. |
606 | 606 | ||
607 | This driver can also be built as a module. If so, the module | 607 | This driver can also be built as a module. If so, the module |
608 | will be called lm80. | 608 | 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, | |||
60 | #define LM80_REG_FANDIV 0x05 | 60 | #define LM80_REG_FANDIV 0x05 |
61 | #define LM80_REG_RES 0x06 | 61 | #define LM80_REG_RES 0x06 |
62 | 62 | ||
63 | #define LM96080_REG_CONV_RATE 0x07 | ||
64 | #define LM96080_REG_MAN_ID 0x3e | ||
65 | #define LM96080_REG_DEV_ID 0x3f | ||
66 | |||
63 | 67 | ||
64 | /* | 68 | /* |
65 | * Conversions. Rounding and limit checking is only done on the TO_REG | 69 | * 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); | |||
147 | 151 | ||
148 | static const struct i2c_device_id lm80_id[] = { | 152 | static const struct i2c_device_id lm80_id[] = { |
149 | { "lm80", 0 }, | 153 | { "lm80", 0 }, |
154 | { "lm96080", 1 }, | ||
150 | { } | 155 | { } |
151 | }; | 156 | }; |
152 | MODULE_DEVICE_TABLE(i2c, lm80_id); | 157 | MODULE_DEVICE_TABLE(i2c, lm80_id); |
@@ -490,23 +495,44 @@ static const struct attribute_group lm80_group = { | |||
490 | static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info) | 495 | static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info) |
491 | { | 496 | { |
492 | struct i2c_adapter *adapter = client->adapter; | 497 | struct i2c_adapter *adapter = client->adapter; |
493 | int i, cur; | 498 | int i, cur, man_id, dev_id; |
499 | const char *name = NULL; | ||
494 | 500 | ||
495 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 501 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
496 | return -ENODEV; | 502 | return -ENODEV; |
497 | 503 | ||
498 | /* Now, we do the remaining detection. It is lousy. */ | 504 | /* First check for unused bits, common to both chip types */ |
499 | if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0) | 505 | if ((lm80_read_value(client, LM80_REG_ALARM2) & 0xc0) |
506 | || (lm80_read_value(client, LM80_REG_CONFIG) & 0x80)) | ||
500 | return -ENODEV; | 507 | return -ENODEV; |
501 | for (i = 0x2a; i <= 0x3d; i++) { | 508 | |
502 | cur = i2c_smbus_read_byte_data(client, i); | 509 | /* |
503 | if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur) | 510 | * The LM96080 has manufacturer and stepping/die rev registers so we |
504 | || (i2c_smbus_read_byte_data(client, i + 0x80) != cur) | 511 | * can just check that. The LM80 does not have such registers so we |
505 | || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur)) | 512 | * have to use a more expensive trick. |
513 | */ | ||
514 | man_id = lm80_read_value(client, LM96080_REG_MAN_ID); | ||
515 | dev_id = lm80_read_value(client, LM96080_REG_DEV_ID); | ||
516 | if (man_id == 0x01 && dev_id == 0x08) { | ||
517 | /* Check more unused bits for confirmation */ | ||
518 | if (lm80_read_value(client, LM96080_REG_CONV_RATE) & 0xfe) | ||
506 | return -ENODEV; | 519 | return -ENODEV; |
520 | |||
521 | name = "lm96080"; | ||
522 | } else { | ||
523 | /* Check 6-bit addressing */ | ||
524 | for (i = 0x2a; i <= 0x3d; i++) { | ||
525 | cur = i2c_smbus_read_byte_data(client, i); | ||
526 | if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur) | ||
527 | || (i2c_smbus_read_byte_data(client, i + 0x80) != cur) | ||
528 | || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur)) | ||
529 | return -ENODEV; | ||
530 | } | ||
531 | |||
532 | name = "lm80"; | ||
507 | } | 533 | } |
508 | 534 | ||
509 | strlcpy(info->type, "lm80", I2C_NAME_SIZE); | 535 | strlcpy(info->type, name, I2C_NAME_SIZE); |
510 | 536 | ||
511 | return 0; | 537 | return 0; |
512 | } | 538 | } |