diff options
author | Guenter Roeck <linux@roeck-us.net> | 2012-01-16 16:51:46 -0500 |
---|---|---|
committer | Jean Delvare <khali@endymion.delvare> | 2012-01-16 16:51:46 -0500 |
commit | f496b2d4f181fa5fcdf24016b11caaa33eb12477 (patch) | |
tree | 8b52c917c9e95dcd4fd0c1907ac083c293601ed1 /drivers/hwmon | |
parent | 04738b2b2f37c13bbe37b7695fec6c1c60d79c7a (diff) |
hwmon: (lm63) Add sensor type attribute for external sensor on LM96163
On LM96163, the external temperature sensor type is configurable to
either a thermal diode or a 3904 transistor. The chip reports a wrong
temperature if misconfigured. Add writable attribute to support it.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/lm63.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 5f6da52a7219..75e3a15c2f61 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c | |||
@@ -93,6 +93,7 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END }; | |||
93 | #define LM63_REG_MAN_ID 0xFE | 93 | #define LM63_REG_MAN_ID 0xFE |
94 | #define LM63_REG_CHIP_ID 0xFF | 94 | #define LM63_REG_CHIP_ID 0xFF |
95 | 95 | ||
96 | #define LM96163_REG_TRUTHERM 0x30 | ||
96 | #define LM96163_REG_REMOTE_TEMP_U_MSB 0x31 | 97 | #define LM96163_REG_REMOTE_TEMP_U_MSB 0x31 |
97 | #define LM96163_REG_REMOTE_TEMP_U_LSB 0x32 | 98 | #define LM96163_REG_REMOTE_TEMP_U_LSB 0x32 |
98 | #define LM96163_REG_CONFIG_ENHANCED 0x45 | 99 | #define LM96163_REG_CONFIG_ENHANCED 0x45 |
@@ -213,6 +214,7 @@ struct lm63_data { | |||
213 | u8 alarms; | 214 | u8 alarms; |
214 | bool pwm_highres; | 215 | bool pwm_highres; |
215 | bool remote_unsigned; /* true if unsigned remote upper limits */ | 216 | bool remote_unsigned; /* true if unsigned remote upper limits */ |
217 | bool trutherm; | ||
216 | }; | 218 | }; |
217 | 219 | ||
218 | static inline int temp8_from_reg(struct lm63_data *data, int nr) | 220 | static inline int temp8_from_reg(struct lm63_data *data, int nr) |
@@ -513,6 +515,41 @@ static ssize_t set_update_interval(struct device *dev, | |||
513 | return count; | 515 | return count; |
514 | } | 516 | } |
515 | 517 | ||
518 | static ssize_t show_type(struct device *dev, struct device_attribute *attr, | ||
519 | char *buf) | ||
520 | { | ||
521 | struct i2c_client *client = to_i2c_client(dev); | ||
522 | struct lm63_data *data = i2c_get_clientdata(client); | ||
523 | |||
524 | return sprintf(buf, data->trutherm ? "1\n" : "2\n"); | ||
525 | } | ||
526 | |||
527 | static ssize_t set_type(struct device *dev, struct device_attribute *attr, | ||
528 | const char *buf, size_t count) | ||
529 | { | ||
530 | struct i2c_client *client = to_i2c_client(dev); | ||
531 | struct lm63_data *data = i2c_get_clientdata(client); | ||
532 | unsigned long val; | ||
533 | int ret; | ||
534 | u8 reg; | ||
535 | |||
536 | ret = kstrtoul(buf, 10, &val); | ||
537 | if (ret < 0) | ||
538 | return ret; | ||
539 | if (val != 1 && val != 2) | ||
540 | return -EINVAL; | ||
541 | |||
542 | mutex_lock(&data->update_lock); | ||
543 | data->trutherm = val == 1; | ||
544 | reg = i2c_smbus_read_byte_data(client, LM96163_REG_TRUTHERM) & ~0x02; | ||
545 | i2c_smbus_write_byte_data(client, LM96163_REG_TRUTHERM, | ||
546 | reg | (data->trutherm ? 0x02 : 0x00)); | ||
547 | data->valid = 0; | ||
548 | mutex_unlock(&data->update_lock); | ||
549 | |||
550 | return count; | ||
551 | } | ||
552 | |||
516 | static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, | 553 | static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, |
517 | char *buf) | 554 | char *buf) |
518 | { | 555 | { |
@@ -553,6 +590,8 @@ static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8, | |||
553 | static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, | 590 | static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, |
554 | set_temp2_crit_hyst); | 591 | set_temp2_crit_hyst); |
555 | 592 | ||
593 | static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type); | ||
594 | |||
556 | /* Individual alarm files */ | 595 | /* Individual alarm files */ |
557 | static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0); | 596 | static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0); |
558 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); | 597 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); |
@@ -712,6 +751,12 @@ static int lm63_probe(struct i2c_client *new_client, | |||
712 | if (err) | 751 | if (err) |
713 | goto exit_remove_files; | 752 | goto exit_remove_files; |
714 | } | 753 | } |
754 | if (data->kind == lm96163) { | ||
755 | err = device_create_file(&new_client->dev, | ||
756 | &dev_attr_temp2_type); | ||
757 | if (err) | ||
758 | goto exit_remove_files; | ||
759 | } | ||
715 | 760 | ||
716 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | 761 | data->hwmon_dev = hwmon_device_register(&new_client->dev); |
717 | if (IS_ERR(data->hwmon_dev)) { | 762 | if (IS_ERR(data->hwmon_dev)) { |
@@ -722,6 +767,7 @@ static int lm63_probe(struct i2c_client *new_client, | |||
722 | return 0; | 767 | return 0; |
723 | 768 | ||
724 | exit_remove_files: | 769 | exit_remove_files: |
770 | device_remove_file(&new_client->dev, &dev_attr_temp2_type); | ||
725 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group); | 771 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group); |
726 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1); | 772 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1); |
727 | exit_free: | 773 | exit_free: |
@@ -763,6 +809,9 @@ static void lm63_init_client(struct i2c_client *client) | |||
763 | break; | 809 | break; |
764 | case lm96163: | 810 | case lm96163: |
765 | data->max_convrate_hz = LM96163_MAX_CONVRATE_HZ; | 811 | data->max_convrate_hz = LM96163_MAX_CONVRATE_HZ; |
812 | data->trutherm | ||
813 | = i2c_smbus_read_byte_data(client, | ||
814 | LM96163_REG_TRUTHERM) & 0x02; | ||
766 | break; | 815 | break; |
767 | } | 816 | } |
768 | convrate = i2c_smbus_read_byte_data(client, LM63_REG_CONVRATE); | 817 | convrate = i2c_smbus_read_byte_data(client, LM63_REG_CONVRATE); |
@@ -803,6 +852,7 @@ static int lm63_remove(struct i2c_client *client) | |||
803 | struct lm63_data *data = i2c_get_clientdata(client); | 852 | struct lm63_data *data = i2c_get_clientdata(client); |
804 | 853 | ||
805 | hwmon_device_unregister(data->hwmon_dev); | 854 | hwmon_device_unregister(data->hwmon_dev); |
855 | device_remove_file(&client->dev, &dev_attr_temp2_type); | ||
806 | sysfs_remove_group(&client->dev.kobj, &lm63_group); | 856 | sysfs_remove_group(&client->dev.kobj, &lm63_group); |
807 | sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); | 857 | sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); |
808 | 858 | ||