diff options
author | Guenter Roeck <linux@roeck-us.net> | 2012-12-19 16:17:01 -0500 |
---|---|---|
committer | Jean Delvare <khali@endymion.delvare> | 2012-12-19 16:17:01 -0500 |
commit | 161d898ac974818156afe48d755578bfd0d6e7c0 (patch) | |
tree | a6e6b76494ec02219f2b701c0b2103e7ff1777aa | |
parent | 2cece01ffd622ab65a4f5a6704e3a74c1174d2fa (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/it87 | 9 | ||||
-rw-r--r-- | drivers/hwmon/it87.c | 66 |
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. | |||
209 | Trip points must be set properly before switching to automatic fan speed | 209 | Trip points must be set properly before switching to automatic fan speed |
210 | control mode. The driver will perform basic integrity checks before | 210 | control mode. The driver will perform basic integrity checks before |
211 | actually switching to automatic control mode. | 211 | actually switching to automatic control mode. |
212 | |||
213 | |||
214 | Temperature offset attributes | ||
215 | ----------------------------- | ||
216 | |||
217 | The driver supports temp[1-3]_offset sysfs attributes to adjust the reported | ||
218 | temperature for thermal diodes or diode-connected thermal transistors. | ||
219 | If a temperature sensor is configured for thermistors, the attribute values | ||
220 | are 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 }; | |||
203 | static const u8 IT87_REG_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86 }; | 203 | static const u8 IT87_REG_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86 }; |
204 | static const u8 IT87_REG_FANX[] = { 0x18, 0x19, 0x1a, 0x81, 0x83 }; | 204 | static const u8 IT87_REG_FANX[] = { 0x18, 0x19, 0x1a, 0x81, 0x83 }; |
205 | static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; | 205 | static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; |
206 | static 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 | ||
317 | static 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 | |||
315 | static int adc_lsb(const struct it87_data *data, int nr) | 328 | static 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); |
566 | static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | 597 | static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, |
567 | 0, 2); | 598 | 0, 2); |
599 | static SENSOR_DEVICE_ATTR_2(temp1_offset, S_IRUGO | S_IWUSR, show_temp, | ||
600 | set_temp, 0, 3); | ||
568 | static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0); | 601 | static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0); |
569 | static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp, | 602 | static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp, |
570 | 1, 1); | 603 | 1, 1); |
571 | static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | 604 | static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, |
572 | 1, 2); | 605 | 1, 2); |
606 | static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IRUGO | S_IWUSR, show_temp, | ||
607 | set_temp, 1, 3); | ||
573 | static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0); | 608 | static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0); |
574 | static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp, | 609 | static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp, |
575 | 2, 1); | 610 | 2, 1); |
576 | static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, | 611 | static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, |
577 | 2, 2); | 612 | 2, 2); |
613 | static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp, | ||
614 | set_temp, 2, 3); | ||
578 | 615 | ||
579 | static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr, | 616 | static 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 | ||
1469 | static 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 | |||
1432 | static struct attribute *it87_attributes[] = { | 1475 | static 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 */ |