Commit f496b2d4f181fa5fcdf24016b11caaa33eb12477

Authored by Guenter Roeck
Committed by Jean Delvare
1 parent 04738b2b2f

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>

Showing 2 changed files with 52 additions and 1 deletions Side-by-side Diff

Documentation/hwmon/lm63
... ... @@ -69,5 +69,6 @@
69 69 support these GPIO lines at present.
70 70  
71 71 The LM96163 is an enhanced version of LM63 with improved temperature accuracy
72   -and better PWM resolution.
  72 +and better PWM resolution. For LM96163, the external temperature sensor type is
  73 +configurable as CPU embedded diode(1) or 3904 transistor(2).
drivers/hwmon/lm63.c
... ... @@ -93,6 +93,7 @@
93 93 #define LM63_REG_MAN_ID 0xFE
94 94 #define LM63_REG_CHIP_ID 0xFF
95 95  
  96 +#define LM96163_REG_TRUTHERM 0x30
96 97 #define LM96163_REG_REMOTE_TEMP_U_MSB 0x31
97 98 #define LM96163_REG_REMOTE_TEMP_U_LSB 0x32
98 99 #define LM96163_REG_CONFIG_ENHANCED 0x45
... ... @@ -213,6 +214,7 @@
213 214 u8 alarms;
214 215 bool pwm_highres;
215 216 bool remote_unsigned; /* true if unsigned remote upper limits */
  217 + bool trutherm;
216 218 };
217 219  
218 220 static inline int temp8_from_reg(struct lm63_data *data, int nr)
... ... @@ -513,6 +515,41 @@
513 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 553 static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
517 554 char *buf)
518 555 {
... ... @@ -553,6 +590,8 @@
553 590 static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
554 591 set_temp2_crit_hyst);
555 592  
  593 +static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type);
  594 +
556 595 /* Individual alarm files */
557 596 static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
558 597 static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
... ... @@ -712,6 +751,12 @@
712 751 if (err)
713 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 761 data->hwmon_dev = hwmon_device_register(&new_client->dev);
717 762 if (IS_ERR(data->hwmon_dev)) {
... ... @@ -722,6 +767,7 @@
722 767 return 0;
723 768  
724 769 exit_remove_files:
  770 + device_remove_file(&new_client->dev, &dev_attr_temp2_type);
725 771 sysfs_remove_group(&new_client->dev.kobj, &lm63_group);
726 772 sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1);
727 773 exit_free:
... ... @@ -763,6 +809,9 @@
763 809 break;
764 810 case lm96163:
765 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 815 break;
767 816 }
768 817 convrate = i2c_smbus_read_byte_data(client, LM63_REG_CONVRATE);
... ... @@ -803,6 +852,7 @@
803 852 struct lm63_data *data = i2c_get_clientdata(client);
804 853  
805 854 hwmon_device_unregister(data->hwmon_dev);
  855 + device_remove_file(&client->dev, &dev_attr_temp2_type);
806 856 sysfs_remove_group(&client->dev.kobj, &lm63_group);
807 857 sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1);
808 858