aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2012-01-16 16:51:46 -0500
committerJean Delvare <khali@endymion.delvare>2012-01-16 16:51:46 -0500
commitf496b2d4f181fa5fcdf24016b11caaa33eb12477 (patch)
tree8b52c917c9e95dcd4fd0c1907ac083c293601ed1
parent04738b2b2f37c13bbe37b7695fec6c1c60d79c7a (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>
-rw-r--r--Documentation/hwmon/lm633
-rw-r--r--drivers/hwmon/lm63.c50
2 files changed, 52 insertions, 1 deletions
diff --git a/Documentation/hwmon/lm63 b/Documentation/hwmon/lm63
index 0e695d3567eb..8202825cd095 100644
--- a/Documentation/hwmon/lm63
+++ b/Documentation/hwmon/lm63
@@ -69,4 +69,5 @@ The LM64 is effectively an LM63 with GPIO lines. The driver does not
69support these GPIO lines at present. 69support these GPIO lines at present.
70 70
71The LM96163 is an enhanced version of LM63 with improved temperature accuracy 71The LM96163 is an enhanced version of LM63 with improved temperature accuracy
72and better PWM resolution. 72and better PWM resolution. For LM96163, the external temperature sensor type is
73configurable as CPU embedded diode(1) or 3904 transistor(2).
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
218static inline int temp8_from_reg(struct lm63_data *data, int nr) 220static 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
518static 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
527static 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
516static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, 553static 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,
553static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, 590static 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
593static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type);
594
556/* Individual alarm files */ 595/* Individual alarm files */
557static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0); 596static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
558static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); 597static 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
724exit_remove_files: 769exit_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);
727exit_free: 773exit_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