aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2012-12-19 16:17:01 -0500
committerJean Delvare <khali@endymion.delvare>2012-12-19 16:17:01 -0500
commit161d898ac974818156afe48d755578bfd0d6e7c0 (patch)
treea6e6b76494ec02219f2b701c0b2103e7ff1777aa
parent2cece01ffd622ab65a4f5a6704e3a74c1174d2fa (diff)
hwmon: (it87) Introduce support for tempX_offset sysfs attribute
Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r--Documentation/hwmon/it879
-rw-r--r--drivers/hwmon/it87.c66
2 files changed, 70 insertions, 5 deletions
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 87850d86c559..e1f38287fbb3 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -209,3 +209,12 @@ doesn't use CPU cycles.
209Trip points must be set properly before switching to automatic fan speed 209Trip points must be set properly before switching to automatic fan speed
210control mode. The driver will perform basic integrity checks before 210control mode. The driver will perform basic integrity checks before
211actually switching to automatic control mode. 211actually switching to automatic control mode.
212
213
214Temperature offset attributes
215-----------------------------
216
217The driver supports temp[1-3]_offset sysfs attributes to adjust the reported
218temperature for thermal diodes or diode-connected thermal transistors.
219If a temperature sensor is configured for thermistors, the attribute values
220are ignored.
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 21fb7f24152c..767563269182 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -203,6 +203,8 @@ static const u8 IT87_REG_FAN[] = { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
203static const u8 IT87_REG_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86 }; 203static const u8 IT87_REG_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86 };
204static const u8 IT87_REG_FANX[] = { 0x18, 0x19, 0x1a, 0x81, 0x83 }; 204static const u8 IT87_REG_FANX[] = { 0x18, 0x19, 0x1a, 0x81, 0x83 };
205static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; 205static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
206static const u8 IT87_REG_TEMP_OFFSET[] = { 0x56, 0x57, 0x59 };
207
206#define IT87_REG_FAN_MAIN_CTRL 0x13 208#define IT87_REG_FAN_MAIN_CTRL 0x13
207#define IT87_REG_FAN_CTL 0x14 209#define IT87_REG_FAN_CTL 0x14
208#define IT87_REG_PWM(nr) (0x15 + (nr)) 210#define IT87_REG_PWM(nr) (0x15 + (nr))
@@ -263,7 +265,7 @@ struct it87_data {
263 u16 fan[5]; /* Register values, possibly combined */ 265 u16 fan[5]; /* Register values, possibly combined */
264 u16 fan_min[5]; /* Register values, possibly combined */ 266 u16 fan_min[5]; /* Register values, possibly combined */
265 u8 has_temp; /* Bitfield, temp sensors enabled */ 267 u8 has_temp; /* Bitfield, temp sensors enabled */
266 s8 temp[3][3]; /* [nr][0]=temp, [1]=min, [2]=max */ 268 s8 temp[3][4]; /* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */
267 u8 sensor; /* Register value */ 269 u8 sensor; /* Register value */
268 u8 fan_div[3]; /* Register encoding, shifted right */ 270 u8 fan_div[3]; /* Register encoding, shifted right */
269 u8 vid; /* Register encoding, combined */ 271 u8 vid; /* Register encoding, combined */
@@ -312,6 +314,17 @@ static inline int has_newer_autopwm(const struct it87_data *data)
312 || data->type == it8728; 314 || data->type == it8728;
313} 315}
314 316
317static inline int has_temp_offset(const struct it87_data *data)
318{
319 return data->type == it8716
320 || data->type == it8718
321 || data->type == it8720
322 || data->type == it8721
323 || data->type == it8728
324 || data->type == it8782
325 || data->type == it8783;
326}
327
315static int adc_lsb(const struct it87_data *data, int nr) 328static int adc_lsb(const struct it87_data *data, int nr)
316{ 329{
317 int lsb = has_12mv_adc(data) ? 12 : 16; 330 int lsb = has_12mv_adc(data) ? 12 : 16;
@@ -546,16 +559,34 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
546 int index = sattr->index; 559 int index = sattr->index;
547 struct it87_data *data = dev_get_drvdata(dev); 560 struct it87_data *data = dev_get_drvdata(dev);
548 long val; 561 long val;
562 u8 reg, regval;
549 563
550 if (kstrtol(buf, 10, &val) < 0) 564 if (kstrtol(buf, 10, &val) < 0)
551 return -EINVAL; 565 return -EINVAL;
552 566
553 mutex_lock(&data->update_lock); 567 mutex_lock(&data->update_lock);
568
569 switch (index) {
570 default:
571 case 1:
572 reg = IT87_REG_TEMP_LOW(nr);
573 break;
574 case 2:
575 reg = IT87_REG_TEMP_HIGH(nr);
576 break;
577 case 3:
578 regval = it87_read_value(data, IT87_REG_BEEP_ENABLE);
579 if (!(regval & 0x80)) {
580 regval |= 0x80;
581 it87_write_value(data, IT87_REG_BEEP_ENABLE, regval);
582 }
583 data->valid = 0;
584 reg = IT87_REG_TEMP_OFFSET[nr];
585 break;
586 }
587
554 data->temp[nr][index] = TEMP_TO_REG(val); 588 data->temp[nr][index] = TEMP_TO_REG(val);
555 it87_write_value(data, 589 it87_write_value(data, reg, data->temp[nr][index]);
556 index == 1 ? IT87_REG_TEMP_LOW(nr)
557 : IT87_REG_TEMP_HIGH(nr),
558 data->temp[nr][index]);
559 mutex_unlock(&data->update_lock); 590 mutex_unlock(&data->update_lock);
560 return count; 591 return count;
561} 592}
@@ -565,16 +596,22 @@ static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
565 0, 1); 596 0, 1);
566static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, 597static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
567 0, 2); 598 0, 2);
599static SENSOR_DEVICE_ATTR_2(temp1_offset, S_IRUGO | S_IWUSR, show_temp,
600 set_temp, 0, 3);
568static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0); 601static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0);
569static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp, 602static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
570 1, 1); 603 1, 1);
571static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, 604static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
572 1, 2); 605 1, 2);
606static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IRUGO | S_IWUSR, show_temp,
607 set_temp, 1, 3);
573static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0); 608static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0);
574static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp, 609static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
575 2, 1); 610 2, 1);
576static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, 611static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
577 2, 2); 612 2, 2);
613static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp,
614 set_temp, 2, 3);
578 615
579static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr, 616static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
580 char *buf) 617 char *buf)
@@ -1429,6 +1466,12 @@ static const struct attribute_group it87_group_temp[3] = {
1429 { .attrs = it87_attributes_temp[2] }, 1466 { .attrs = it87_attributes_temp[2] },
1430}; 1467};
1431 1468
1469static struct attribute *it87_attributes_temp_offset[] = {
1470 &sensor_dev_attr_temp1_offset.dev_attr.attr,
1471 &sensor_dev_attr_temp2_offset.dev_attr.attr,
1472 &sensor_dev_attr_temp3_offset.dev_attr.attr,
1473};
1474
1432static struct attribute *it87_attributes[] = { 1475static struct attribute *it87_attributes[] = {
1433 &dev_attr_alarms.attr, 1476 &dev_attr_alarms.attr,
1434 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, 1477 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
@@ -1899,6 +1942,9 @@ static void it87_remove_files(struct device *dev)
1899 if (!(data->has_temp & (1 << i))) 1942 if (!(data->has_temp & (1 << i)))
1900 continue; 1943 continue;
1901 sysfs_remove_group(&dev->kobj, &it87_group_temp[i]); 1944 sysfs_remove_group(&dev->kobj, &it87_group_temp[i]);
1945 if (has_temp_offset(data))
1946 sysfs_remove_file(&dev->kobj,
1947 it87_attributes_temp_offset[i]);
1902 if (sio_data->beep_pin) 1948 if (sio_data->beep_pin)
1903 sysfs_remove_file(&dev->kobj, 1949 sysfs_remove_file(&dev->kobj,
1904 it87_attributes_temp_beep[i]); 1950 it87_attributes_temp_beep[i]);
@@ -2026,6 +2072,12 @@ static int it87_probe(struct platform_device *pdev)
2026 err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]); 2072 err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]);
2027 if (err) 2073 if (err)
2028 goto error; 2074 goto error;
2075 if (has_temp_offset(data)) {
2076 err = sysfs_create_file(&dev->kobj,
2077 it87_attributes_temp_offset[i]);
2078 if (err)
2079 goto error;
2080 }
2029 if (sio_data->beep_pin) { 2081 if (sio_data->beep_pin) {
2030 err = sysfs_create_file(&dev->kobj, 2082 err = sysfs_create_file(&dev->kobj,
2031 it87_attributes_temp_beep[i]); 2083 it87_attributes_temp_beep[i]);
@@ -2383,6 +2435,10 @@ static struct it87_data *it87_update_device(struct device *dev)
2383 it87_read_value(data, IT87_REG_TEMP_LOW(i)); 2435 it87_read_value(data, IT87_REG_TEMP_LOW(i));
2384 data->temp[i][2] = 2436 data->temp[i][2] =
2385 it87_read_value(data, IT87_REG_TEMP_HIGH(i)); 2437 it87_read_value(data, IT87_REG_TEMP_HIGH(i));
2438 if (has_temp_offset(data))
2439 data->temp[i][3] =
2440 it87_read_value(data,
2441 IT87_REG_TEMP_OFFSET[i]);
2386 } 2442 }
2387 2443
2388 /* Newer chips don't have clock dividers */ 2444 /* Newer chips don't have clock dividers */