diff options
author | Guenter Roeck <guenter.roeck@ericsson.com> | 2010-10-28 14:31:43 -0400 |
---|---|---|
committer | Jean Delvare <khali@endymion.delvare> | 2010-10-28 14:31:43 -0400 |
commit | 6948708dd07573c578aa99f80915cd1867334abe (patch) | |
tree | ff218b1febbe70410d98589ae058cbad3784c0aa /drivers/hwmon/lm90.c | |
parent | 13c84951a3d75ba820adf47eb2a3b1c5ab1fa635 (diff) |
hwmon: (lm90) Add support for extra features of max6659
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/lm90.c')
-rw-r--r-- | drivers/hwmon/lm90.c | 65 |
1 files changed, 59 insertions, 6 deletions
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 68ee8f78843e..de544817d673 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c | |||
@@ -28,9 +28,11 @@ | |||
28 | * This driver also supports the MAX6657, MAX6658 and MAX6659 sensor | 28 | * This driver also supports the MAX6657, MAX6658 and MAX6659 sensor |
29 | * chips made by Maxim. These chips are similar to the LM86. | 29 | * chips made by Maxim. These chips are similar to the LM86. |
30 | * Note that there is no easy way to differentiate between the three | 30 | * Note that there is no easy way to differentiate between the three |
31 | * variants. The extra address and features of the MAX6659 are not | 31 | * variants. We use the device address to detect MAX6659, which will result |
32 | * supported by this driver. These chips lack the remote temperature | 32 | * in a detection as max6657 if it is on address 0x4c. The extra address |
33 | * offset feature. | 33 | * and features of the MAX6659 are only supported if the chip is configured |
34 | * explicitly as max6659, or if its address is not 0x4c. | ||
35 | * These chips lack the remote temperature offset feature. | ||
34 | * | 36 | * |
35 | * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and | 37 | * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and |
36 | * MAX6692 chips made by Maxim. These are again similar to the LM86, | 38 | * MAX6692 chips made by Maxim. These are again similar to the LM86, |
@@ -138,6 +140,10 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, | |||
138 | /* MAX6646/6647/6649/6657/6658/6659 registers */ | 140 | /* MAX6646/6647/6649/6657/6658/6659 registers */ |
139 | 141 | ||
140 | #define MAX6657_REG_R_LOCAL_TEMPL 0x11 | 142 | #define MAX6657_REG_R_LOCAL_TEMPL 0x11 |
143 | #define MAX6659_REG_R_REMOTE_EMERG 0x16 | ||
144 | #define MAX6659_REG_W_REMOTE_EMERG 0x16 | ||
145 | #define MAX6659_REG_R_LOCAL_EMERG 0x17 | ||
146 | #define MAX6659_REG_W_LOCAL_EMERG 0x17 | ||
141 | 147 | ||
142 | /* | 148 | /* |
143 | * Device flags | 149 | * Device flags |
@@ -147,6 +153,7 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, | |||
147 | #define LM90_HAVE_OFFSET (1 << 1) /* temperature offset register */ | 153 | #define LM90_HAVE_OFFSET (1 << 1) /* temperature offset register */ |
148 | #define LM90_HAVE_LOCAL_EXT (1 << 2) /* extended local temperature */ | 154 | #define LM90_HAVE_LOCAL_EXT (1 << 2) /* extended local temperature */ |
149 | #define LM90_HAVE_REM_LIMIT_EXT (1 << 3) /* extended remote limit */ | 155 | #define LM90_HAVE_REM_LIMIT_EXT (1 << 3) /* extended remote limit */ |
156 | #define LM90_HAVE_EMERGENCY (1 << 4) /* 3rd upper (emergency) limit */ | ||
150 | 157 | ||
151 | /* | 158 | /* |
152 | * Functions declaration | 159 | * Functions declaration |
@@ -213,10 +220,12 @@ struct lm90_data { | |||
213 | u8 alert_alarms; /* Which alarm bits trigger ALERT# */ | 220 | u8 alert_alarms; /* Which alarm bits trigger ALERT# */ |
214 | 221 | ||
215 | /* registers values */ | 222 | /* registers values */ |
216 | s8 temp8[4]; /* 0: local low limit | 223 | s8 temp8[6]; /* 0: local low limit |
217 | 1: local high limit | 224 | 1: local high limit |
218 | 2: local critical limit | 225 | 2: local critical limit |
219 | 3: remote critical limit */ | 226 | 3: remote critical limit |
227 | 4: local emergency limit (max6659 only) | ||
228 | 5: remote emergency limit (max6659 only) */ | ||
220 | s16 temp11[5]; /* 0: remote input | 229 | s16 temp11[5]; /* 0: remote input |
221 | 1: remote low limit | 230 | 1: remote low limit |
222 | 2: remote high limit | 231 | 2: remote high limit |
@@ -381,11 +390,13 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr, | |||
381 | static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, | 390 | static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, |
382 | const char *buf, size_t count) | 391 | const char *buf, size_t count) |
383 | { | 392 | { |
384 | static const u8 reg[4] = { | 393 | static const u8 reg[6] = { |
385 | LM90_REG_W_LOCAL_LOW, | 394 | LM90_REG_W_LOCAL_LOW, |
386 | LM90_REG_W_LOCAL_HIGH, | 395 | LM90_REG_W_LOCAL_HIGH, |
387 | LM90_REG_W_LOCAL_CRIT, | 396 | LM90_REG_W_LOCAL_CRIT, |
388 | LM90_REG_W_REMOTE_CRIT, | 397 | LM90_REG_W_REMOTE_CRIT, |
398 | MAX6659_REG_W_LOCAL_EMERG, | ||
399 | MAX6659_REG_W_REMOTE_EMERG, | ||
389 | }; | 400 | }; |
390 | 401 | ||
391 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 402 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
@@ -608,6 +619,30 @@ static const struct attribute_group lm90_group = { | |||
608 | .attrs = lm90_attributes, | 619 | .attrs = lm90_attributes, |
609 | }; | 620 | }; |
610 | 621 | ||
622 | /* | ||
623 | * Additional attributes for devices with emergency sensors | ||
624 | */ | ||
625 | static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO, show_temp8, | ||
626 | set_temp8, 4); | ||
627 | static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO, show_temp8, | ||
628 | set_temp8, 5); | ||
629 | static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO, show_temphyst, | ||
630 | NULL, 4); | ||
631 | static SENSOR_DEVICE_ATTR(temp2_emergency_hyst, S_IRUGO, show_temphyst, | ||
632 | NULL, 5); | ||
633 | |||
634 | static struct attribute *lm90_emergency_attributes[] = { | ||
635 | &sensor_dev_attr_temp1_emergency.dev_attr.attr, | ||
636 | &sensor_dev_attr_temp2_emergency.dev_attr.attr, | ||
637 | &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr, | ||
638 | &sensor_dev_attr_temp2_emergency_hyst.dev_attr.attr, | ||
639 | NULL | ||
640 | }; | ||
641 | |||
642 | static const struct attribute_group lm90_emergency_group = { | ||
643 | .attrs = lm90_emergency_attributes, | ||
644 | }; | ||
645 | |||
611 | /* pec used for ADM1032 only */ | 646 | /* pec used for ADM1032 only */ |
612 | static ssize_t show_pec(struct device *dev, struct device_attribute *dummy, | 647 | static ssize_t show_pec(struct device *dev, struct device_attribute *dummy, |
613 | char *buf) | 648 | char *buf) |
@@ -826,6 +861,9 @@ static int lm90_detect(struct i2c_client *new_client, | |||
826 | 861 | ||
827 | static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data) | 862 | static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data) |
828 | { | 863 | { |
864 | if (data->flags & LM90_HAVE_EMERGENCY) | ||
865 | sysfs_remove_group(&client->dev.kobj, | ||
866 | &lm90_emergency_group); | ||
829 | if (data->flags & LM90_HAVE_OFFSET) | 867 | if (data->flags & LM90_HAVE_OFFSET) |
830 | device_remove_file(&client->dev, | 868 | device_remove_file(&client->dev, |
831 | &sensor_dev_attr_temp2_offset.dev_attr); | 869 | &sensor_dev_attr_temp2_offset.dev_attr); |
@@ -881,6 +919,9 @@ static int lm90_probe(struct i2c_client *new_client, | |||
881 | && data->kind != max6646 && data->kind != max6680) | 919 | && data->kind != max6646 && data->kind != max6680) |
882 | data->flags |= LM90_HAVE_REM_LIMIT_EXT; | 920 | data->flags |= LM90_HAVE_REM_LIMIT_EXT; |
883 | 921 | ||
922 | if (data->kind == max6659) | ||
923 | data->flags |= LM90_HAVE_EMERGENCY; | ||
924 | |||
884 | /* Initialize the LM90 chip */ | 925 | /* Initialize the LM90 chip */ |
885 | lm90_init_client(new_client); | 926 | lm90_init_client(new_client); |
886 | 927 | ||
@@ -899,6 +940,12 @@ static int lm90_probe(struct i2c_client *new_client, | |||
899 | if (err) | 940 | if (err) |
900 | goto exit_remove_files; | 941 | goto exit_remove_files; |
901 | } | 942 | } |
943 | if (data->flags & LM90_HAVE_EMERGENCY) { | ||
944 | err = sysfs_create_group(&new_client->dev.kobj, | ||
945 | &lm90_emergency_group); | ||
946 | if (err) | ||
947 | goto exit_remove_files; | ||
948 | } | ||
902 | 949 | ||
903 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | 950 | data->hwmon_dev = hwmon_device_register(&new_client->dev); |
904 | if (IS_ERR(data->hwmon_dev)) { | 951 | if (IS_ERR(data->hwmon_dev)) { |
@@ -1082,6 +1129,12 @@ static struct lm90_data *lm90_update_device(struct device *dev) | |||
1082 | &l) == 0) | 1129 | &l) == 0) |
1083 | data->temp11[3] = (h << 8) | l; | 1130 | data->temp11[3] = (h << 8) | l; |
1084 | } | 1131 | } |
1132 | if (data->flags & LM90_HAVE_EMERGENCY) { | ||
1133 | lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG, | ||
1134 | &data->temp8[4]); | ||
1135 | lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, | ||
1136 | &data->temp8[5]); | ||
1137 | } | ||
1085 | lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms); | 1138 | lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms); |
1086 | 1139 | ||
1087 | /* Re-enable ALERT# output if it was originally enabled and | 1140 | /* Re-enable ALERT# output if it was originally enabled and |