diff options
Diffstat (limited to 'drivers/hwmon/it87.c')
-rw-r--r-- | drivers/hwmon/it87.c | 939 |
1 files changed, 686 insertions, 253 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 0ffe84d190bb..1002befd87d5 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -1,40 +1,40 @@ | |||
1 | /* | 1 | /* |
2 | it87.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | * it87.c - Part of lm_sensors, Linux kernel modules for hardware |
3 | monitoring. | 3 | * monitoring. |
4 | 4 | * | |
5 | The IT8705F is an LPC-based Super I/O part that contains UARTs, a | 5 | * The IT8705F is an LPC-based Super I/O part that contains UARTs, a |
6 | parallel port, an IR port, a MIDI port, a floppy controller, etc., in | 6 | * parallel port, an IR port, a MIDI port, a floppy controller, etc., in |
7 | addition to an Environment Controller (Enhanced Hardware Monitor and | 7 | * addition to an Environment Controller (Enhanced Hardware Monitor and |
8 | Fan Controller) | 8 | * Fan Controller) |
9 | 9 | * | |
10 | This driver supports only the Environment Controller in the IT8705F and | 10 | * This driver supports only the Environment Controller in the IT8705F and |
11 | similar parts. The other devices are supported by different drivers. | 11 | * similar parts. The other devices are supported by different drivers. |
12 | 12 | * | |
13 | Supports: IT8705F Super I/O chip w/LPC interface | 13 | * Supports: IT8705F Super I/O chip w/LPC interface |
14 | IT8712F Super I/O chip w/LPC interface | 14 | * IT8712F Super I/O chip w/LPC interface |
15 | IT8716F Super I/O chip w/LPC interface | 15 | * IT8716F Super I/O chip w/LPC interface |
16 | IT8718F Super I/O chip w/LPC interface | 16 | * IT8718F Super I/O chip w/LPC interface |
17 | IT8720F Super I/O chip w/LPC interface | 17 | * IT8720F Super I/O chip w/LPC interface |
18 | IT8726F Super I/O chip w/LPC interface | 18 | * IT8726F Super I/O chip w/LPC interface |
19 | Sis950 A clone of the IT8705F | 19 | * Sis950 A clone of the IT8705F |
20 | 20 | * | |
21 | Copyright (C) 2001 Chris Gauthron | 21 | * Copyright (C) 2001 Chris Gauthron |
22 | Copyright (C) 2005-2007 Jean Delvare <khali@linux-fr.org> | 22 | * Copyright (C) 2005-2010 Jean Delvare <khali@linux-fr.org> |
23 | 23 | * | |
24 | This program is free software; you can redistribute it and/or modify | 24 | * This program is free software; you can redistribute it and/or modify |
25 | it under the terms of the GNU General Public License as published by | 25 | * it under the terms of the GNU General Public License as published by |
26 | the Free Software Foundation; either version 2 of the License, or | 26 | * the Free Software Foundation; either version 2 of the License, or |
27 | (at your option) any later version. | 27 | * (at your option) any later version. |
28 | 28 | * | |
29 | This program is distributed in the hope that it will be useful, | 29 | * This program is distributed in the hope that it will be useful, |
30 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 30 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
31 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 31 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
32 | GNU General Public License for more details. | 32 | * GNU General Public License for more details. |
33 | 33 | * | |
34 | You should have received a copy of the GNU General Public License | 34 | * You should have received a copy of the GNU General Public License |
35 | along with this program; if not, write to the Free Software | 35 | * along with this program; if not, write to the Free Software |
36 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 36 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
@@ -128,6 +128,7 @@ superio_exit(void) | |||
128 | #define IT87_SIO_GPIO5_REG 0x29 | 128 | #define IT87_SIO_GPIO5_REG 0x29 |
129 | #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ | 129 | #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ |
130 | #define IT87_SIO_VID_REG 0xfc /* VID value */ | 130 | #define IT87_SIO_VID_REG 0xfc /* VID value */ |
131 | #define IT87_SIO_BEEP_PIN_REG 0xf6 /* Beep pin mapping */ | ||
131 | 132 | ||
132 | /* Update battery voltage after every reading if true */ | 133 | /* Update battery voltage after every reading if true */ |
133 | static int update_vbat; | 134 | static int update_vbat; |
@@ -187,9 +188,13 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; | |||
187 | 188 | ||
188 | #define IT87_REG_VIN_ENABLE 0x50 | 189 | #define IT87_REG_VIN_ENABLE 0x50 |
189 | #define IT87_REG_TEMP_ENABLE 0x51 | 190 | #define IT87_REG_TEMP_ENABLE 0x51 |
191 | #define IT87_REG_BEEP_ENABLE 0x5c | ||
190 | 192 | ||
191 | #define IT87_REG_CHIPID 0x58 | 193 | #define IT87_REG_CHIPID 0x58 |
192 | 194 | ||
195 | #define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i)) | ||
196 | #define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i)) | ||
197 | |||
193 | #define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255)) | 198 | #define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255)) |
194 | #define IN_FROM_REG(val) ((val) * 16) | 199 | #define IN_FROM_REG(val) ((val) * 16) |
195 | 200 | ||
@@ -246,6 +251,7 @@ struct it87_sio_data { | |||
246 | /* Values read from Super-I/O config space */ | 251 | /* Values read from Super-I/O config space */ |
247 | u8 revision; | 252 | u8 revision; |
248 | u8 vid_value; | 253 | u8 vid_value; |
254 | u8 beep_pin; | ||
249 | /* Features skipped based on config or DMI */ | 255 | /* Features skipped based on config or DMI */ |
250 | u8 skip_vid; | 256 | u8 skip_vid; |
251 | u8 skip_fan; | 257 | u8 skip_fan; |
@@ -279,9 +285,21 @@ struct it87_data { | |||
279 | u8 vid; /* Register encoding, combined */ | 285 | u8 vid; /* Register encoding, combined */ |
280 | u8 vrm; | 286 | u8 vrm; |
281 | u32 alarms; /* Register encoding, combined */ | 287 | u32 alarms; /* Register encoding, combined */ |
288 | u8 beeps; /* Register encoding */ | ||
282 | u8 fan_main_ctrl; /* Register value */ | 289 | u8 fan_main_ctrl; /* Register value */ |
283 | u8 fan_ctl; /* Register value */ | 290 | u8 fan_ctl; /* Register value */ |
284 | u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ | 291 | |
292 | /* The following 3 arrays correspond to the same registers. The | ||
293 | * meaning of bits 6-0 depends on the value of bit 7, and we want | ||
294 | * to preserve settings on mode changes, so we have to track all | ||
295 | * values separately. */ | ||
296 | u8 pwm_ctrl[3]; /* Register value */ | ||
297 | u8 pwm_duty[3]; /* Manual PWM value set by user (bit 6-0) */ | ||
298 | u8 pwm_temp_map[3]; /* PWM to temp. chan. mapping (bits 1-0) */ | ||
299 | |||
300 | /* Automatic fan speed control registers */ | ||
301 | u8 auto_pwm[3][4]; /* [nr][3] is hard-coded */ | ||
302 | s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ | ||
285 | }; | 303 | }; |
286 | 304 | ||
287 | static inline int has_16bit_fans(const struct it87_data *data) | 305 | static inline int has_16bit_fans(const struct it87_data *data) |
@@ -296,6 +314,15 @@ static inline int has_16bit_fans(const struct it87_data *data) | |||
296 | || data->type == it8720; | 314 | || data->type == it8720; |
297 | } | 315 | } |
298 | 316 | ||
317 | static inline int has_old_autopwm(const struct it87_data *data) | ||
318 | { | ||
319 | /* The old automatic fan speed control interface is implemented | ||
320 | by IT8705F chips up to revision F and IT8712F chips up to | ||
321 | revision G. */ | ||
322 | return (data->type == it87 && data->revision < 0x03) | ||
323 | || (data->type == it8712 && data->revision < 0x08); | ||
324 | } | ||
325 | |||
299 | static int it87_probe(struct platform_device *pdev); | 326 | static int it87_probe(struct platform_device *pdev); |
300 | static int __devexit it87_remove(struct platform_device *pdev); | 327 | static int __devexit it87_remove(struct platform_device *pdev); |
301 | 328 | ||
@@ -352,7 +379,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, | |||
352 | int nr = sensor_attr->index; | 379 | int nr = sensor_attr->index; |
353 | 380 | ||
354 | struct it87_data *data = dev_get_drvdata(dev); | 381 | struct it87_data *data = dev_get_drvdata(dev); |
355 | unsigned long val = simple_strtoul(buf, NULL, 10); | 382 | unsigned long val; |
383 | |||
384 | if (strict_strtoul(buf, 10, &val) < 0) | ||
385 | return -EINVAL; | ||
356 | 386 | ||
357 | mutex_lock(&data->update_lock); | 387 | mutex_lock(&data->update_lock); |
358 | data->in_min[nr] = IN_TO_REG(val); | 388 | data->in_min[nr] = IN_TO_REG(val); |
@@ -368,7 +398,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, | |||
368 | int nr = sensor_attr->index; | 398 | int nr = sensor_attr->index; |
369 | 399 | ||
370 | struct it87_data *data = dev_get_drvdata(dev); | 400 | struct it87_data *data = dev_get_drvdata(dev); |
371 | unsigned long val = simple_strtoul(buf, NULL, 10); | 401 | unsigned long val; |
402 | |||
403 | if (strict_strtoul(buf, 10, &val) < 0) | ||
404 | return -EINVAL; | ||
372 | 405 | ||
373 | mutex_lock(&data->update_lock); | 406 | mutex_lock(&data->update_lock); |
374 | data->in_max[nr] = IN_TO_REG(val); | 407 | data->in_max[nr] = IN_TO_REG(val); |
@@ -441,7 +474,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, | |||
441 | int nr = sensor_attr->index; | 474 | int nr = sensor_attr->index; |
442 | 475 | ||
443 | struct it87_data *data = dev_get_drvdata(dev); | 476 | struct it87_data *data = dev_get_drvdata(dev); |
444 | int val = simple_strtol(buf, NULL, 10); | 477 | long val; |
478 | |||
479 | if (strict_strtol(buf, 10, &val) < 0) | ||
480 | return -EINVAL; | ||
445 | 481 | ||
446 | mutex_lock(&data->update_lock); | 482 | mutex_lock(&data->update_lock); |
447 | data->temp_high[nr] = TEMP_TO_REG(val); | 483 | data->temp_high[nr] = TEMP_TO_REG(val); |
@@ -456,7 +492,10 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, | |||
456 | int nr = sensor_attr->index; | 492 | int nr = sensor_attr->index; |
457 | 493 | ||
458 | struct it87_data *data = dev_get_drvdata(dev); | 494 | struct it87_data *data = dev_get_drvdata(dev); |
459 | int val = simple_strtol(buf, NULL, 10); | 495 | long val; |
496 | |||
497 | if (strict_strtol(buf, 10, &val) < 0) | ||
498 | return -EINVAL; | ||
460 | 499 | ||
461 | mutex_lock(&data->update_lock); | 500 | mutex_lock(&data->update_lock); |
462 | data->temp_low[nr] = TEMP_TO_REG(val); | 501 | data->temp_low[nr] = TEMP_TO_REG(val); |
@@ -483,8 +522,9 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *attr, | |||
483 | int nr = sensor_attr->index; | 522 | int nr = sensor_attr->index; |
484 | 523 | ||
485 | struct it87_data *data = it87_update_device(dev); | 524 | struct it87_data *data = it87_update_device(dev); |
486 | u8 reg = data->sensor; /* In case the value is updated while we use it */ | 525 | u8 reg = data->sensor; /* In case the value is updated while |
487 | 526 | we use it */ | |
527 | |||
488 | if (reg & (1 << nr)) | 528 | if (reg & (1 << nr)) |
489 | return sprintf(buf, "3\n"); /* thermal diode */ | 529 | return sprintf(buf, "3\n"); /* thermal diode */ |
490 | if (reg & (8 << nr)) | 530 | if (reg & (8 << nr)) |
@@ -498,7 +538,10 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, | |||
498 | int nr = sensor_attr->index; | 538 | int nr = sensor_attr->index; |
499 | 539 | ||
500 | struct it87_data *data = dev_get_drvdata(dev); | 540 | struct it87_data *data = dev_get_drvdata(dev); |
501 | int val = simple_strtol(buf, NULL, 10); | 541 | long val; |
542 | |||
543 | if (strict_strtol(buf, 10, &val) < 0) | ||
544 | return -EINVAL; | ||
502 | 545 | ||
503 | mutex_lock(&data->update_lock); | 546 | mutex_lock(&data->update_lock); |
504 | 547 | ||
@@ -511,9 +554,9 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, | |||
511 | } | 554 | } |
512 | /* 3 = thermal diode; 4 = thermistor; 0 = disabled */ | 555 | /* 3 = thermal diode; 4 = thermistor; 0 = disabled */ |
513 | if (val == 3) | 556 | if (val == 3) |
514 | data->sensor |= 1 << nr; | 557 | data->sensor |= 1 << nr; |
515 | else if (val == 4) | 558 | else if (val == 4) |
516 | data->sensor |= 8 << nr; | 559 | data->sensor |= 8 << nr; |
517 | else if (val != 0) { | 560 | else if (val != 0) { |
518 | mutex_unlock(&data->update_lock); | 561 | mutex_unlock(&data->update_lock); |
519 | return -EINVAL; | 562 | return -EINVAL; |
@@ -531,6 +574,19 @@ show_sensor_offset(2); | |||
531 | show_sensor_offset(3); | 574 | show_sensor_offset(3); |
532 | 575 | ||
533 | /* 3 Fans */ | 576 | /* 3 Fans */ |
577 | |||
578 | static int pwm_mode(const struct it87_data *data, int nr) | ||
579 | { | ||
580 | int ctrl = data->fan_main_ctrl & (1 << nr); | ||
581 | |||
582 | if (ctrl == 0) /* Full speed */ | ||
583 | return 0; | ||
584 | if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ | ||
585 | return 2; | ||
586 | else /* Manual mode */ | ||
587 | return 1; | ||
588 | } | ||
589 | |||
534 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, | 590 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, |
535 | char *buf) | 591 | char *buf) |
536 | { | 592 | { |
@@ -538,7 +594,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, | |||
538 | int nr = sensor_attr->index; | 594 | int nr = sensor_attr->index; |
539 | 595 | ||
540 | struct it87_data *data = it87_update_device(dev); | 596 | struct it87_data *data = it87_update_device(dev); |
541 | return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], | 597 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], |
542 | DIV_FROM_REG(data->fan_div[nr]))); | 598 | DIV_FROM_REG(data->fan_div[nr]))); |
543 | } | 599 | } |
544 | static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, | 600 | static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, |
@@ -548,8 +604,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, | |||
548 | int nr = sensor_attr->index; | 604 | int nr = sensor_attr->index; |
549 | 605 | ||
550 | struct it87_data *data = it87_update_device(dev); | 606 | struct it87_data *data = it87_update_device(dev); |
551 | return sprintf(buf,"%d\n", | 607 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], |
552 | FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]))); | 608 | DIV_FROM_REG(data->fan_div[nr]))); |
553 | } | 609 | } |
554 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, | 610 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, |
555 | char *buf) | 611 | char *buf) |
@@ -560,14 +616,14 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, | |||
560 | struct it87_data *data = it87_update_device(dev); | 616 | struct it87_data *data = it87_update_device(dev); |
561 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); | 617 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); |
562 | } | 618 | } |
563 | static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, | 619 | static ssize_t show_pwm_enable(struct device *dev, |
564 | char *buf) | 620 | struct device_attribute *attr, char *buf) |
565 | { | 621 | { |
566 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 622 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
567 | int nr = sensor_attr->index; | 623 | int nr = sensor_attr->index; |
568 | 624 | ||
569 | struct it87_data *data = it87_update_device(dev); | 625 | struct it87_data *data = it87_update_device(dev); |
570 | return sprintf(buf,"%d\n", (data->fan_main_ctrl & (1 << nr)) ? 1 : 0); | 626 | return sprintf(buf, "%d\n", pwm_mode(data, nr)); |
571 | } | 627 | } |
572 | static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | 628 | static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, |
573 | char *buf) | 629 | char *buf) |
@@ -576,7 +632,7 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | |||
576 | int nr = sensor_attr->index; | 632 | int nr = sensor_attr->index; |
577 | 633 | ||
578 | struct it87_data *data = it87_update_device(dev); | 634 | struct it87_data *data = it87_update_device(dev); |
579 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); | 635 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm_duty[nr])); |
580 | } | 636 | } |
581 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, | 637 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, |
582 | char *buf) | 638 | char *buf) |
@@ -593,15 +649,24 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | |||
593 | int nr = sensor_attr->index; | 649 | int nr = sensor_attr->index; |
594 | 650 | ||
595 | struct it87_data *data = dev_get_drvdata(dev); | 651 | struct it87_data *data = dev_get_drvdata(dev); |
596 | int val = simple_strtol(buf, NULL, 10); | 652 | long val; |
597 | u8 reg; | 653 | u8 reg; |
598 | 654 | ||
655 | if (strict_strtol(buf, 10, &val) < 0) | ||
656 | return -EINVAL; | ||
657 | |||
599 | mutex_lock(&data->update_lock); | 658 | mutex_lock(&data->update_lock); |
600 | reg = it87_read_value(data, IT87_REG_FAN_DIV); | 659 | reg = it87_read_value(data, IT87_REG_FAN_DIV); |
601 | switch (nr) { | 660 | switch (nr) { |
602 | case 0: data->fan_div[nr] = reg & 0x07; break; | 661 | case 0: |
603 | case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; | 662 | data->fan_div[nr] = reg & 0x07; |
604 | case 2: data->fan_div[nr] = (reg & 0x40) ? 3 : 1; break; | 663 | break; |
664 | case 1: | ||
665 | data->fan_div[nr] = (reg >> 3) & 0x07; | ||
666 | break; | ||
667 | case 2: | ||
668 | data->fan_div[nr] = (reg & 0x40) ? 3 : 1; | ||
669 | break; | ||
605 | } | 670 | } |
606 | 671 | ||
607 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); | 672 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); |
@@ -616,10 +681,13 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | |||
616 | int nr = sensor_attr->index; | 681 | int nr = sensor_attr->index; |
617 | 682 | ||
618 | struct it87_data *data = dev_get_drvdata(dev); | 683 | struct it87_data *data = dev_get_drvdata(dev); |
619 | unsigned long val = simple_strtoul(buf, NULL, 10); | 684 | unsigned long val; |
620 | int min; | 685 | int min; |
621 | u8 old; | 686 | u8 old; |
622 | 687 | ||
688 | if (strict_strtoul(buf, 10, &val) < 0) | ||
689 | return -EINVAL; | ||
690 | |||
623 | mutex_lock(&data->update_lock); | 691 | mutex_lock(&data->update_lock); |
624 | old = it87_read_value(data, IT87_REG_FAN_DIV); | 692 | old = it87_read_value(data, IT87_REG_FAN_DIV); |
625 | 693 | ||
@@ -651,6 +719,32 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | |||
651 | mutex_unlock(&data->update_lock); | 719 | mutex_unlock(&data->update_lock); |
652 | return count; | 720 | return count; |
653 | } | 721 | } |
722 | |||
723 | /* Returns 0 if OK, -EINVAL otherwise */ | ||
724 | static int check_trip_points(struct device *dev, int nr) | ||
725 | { | ||
726 | const struct it87_data *data = dev_get_drvdata(dev); | ||
727 | int i, err = 0; | ||
728 | |||
729 | if (has_old_autopwm(data)) { | ||
730 | for (i = 0; i < 3; i++) { | ||
731 | if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1]) | ||
732 | err = -EINVAL; | ||
733 | } | ||
734 | for (i = 0; i < 2; i++) { | ||
735 | if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1]) | ||
736 | err = -EINVAL; | ||
737 | } | ||
738 | } | ||
739 | |||
740 | if (err) { | ||
741 | dev_err(dev, "Inconsistent trip points, not switching to " | ||
742 | "automatic mode\n"); | ||
743 | dev_err(dev, "Adjust the trip points and try again\n"); | ||
744 | } | ||
745 | return err; | ||
746 | } | ||
747 | |||
654 | static ssize_t set_pwm_enable(struct device *dev, | 748 | static ssize_t set_pwm_enable(struct device *dev, |
655 | struct device_attribute *attr, const char *buf, size_t count) | 749 | struct device_attribute *attr, const char *buf, size_t count) |
656 | { | 750 | { |
@@ -658,7 +752,16 @@ static ssize_t set_pwm_enable(struct device *dev, | |||
658 | int nr = sensor_attr->index; | 752 | int nr = sensor_attr->index; |
659 | 753 | ||
660 | struct it87_data *data = dev_get_drvdata(dev); | 754 | struct it87_data *data = dev_get_drvdata(dev); |
661 | int val = simple_strtol(buf, NULL, 10); | 755 | long val; |
756 | |||
757 | if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 2) | ||
758 | return -EINVAL; | ||
759 | |||
760 | /* Check trip points before switching to automatic mode */ | ||
761 | if (val == 2) { | ||
762 | if (check_trip_points(dev, nr) < 0) | ||
763 | return -EINVAL; | ||
764 | } | ||
662 | 765 | ||
663 | mutex_lock(&data->update_lock); | 766 | mutex_lock(&data->update_lock); |
664 | 767 | ||
@@ -669,16 +772,18 @@ static ssize_t set_pwm_enable(struct device *dev, | |||
669 | it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr)); | 772 | it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr)); |
670 | /* set on/off mode */ | 773 | /* set on/off mode */ |
671 | data->fan_main_ctrl &= ~(1 << nr); | 774 | data->fan_main_ctrl &= ~(1 << nr); |
672 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 775 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, |
673 | } else if (val == 1) { | 776 | data->fan_main_ctrl); |
777 | } else { | ||
778 | if (val == 1) /* Manual mode */ | ||
779 | data->pwm_ctrl[nr] = data->pwm_duty[nr]; | ||
780 | else /* Automatic mode */ | ||
781 | data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; | ||
782 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); | ||
674 | /* set SmartGuardian mode */ | 783 | /* set SmartGuardian mode */ |
675 | data->fan_main_ctrl |= (1 << nr); | 784 | data->fan_main_ctrl |= (1 << nr); |
676 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 785 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, |
677 | /* set saved pwm value, clear FAN_CTLX PWM mode bit */ | 786 | data->fan_main_ctrl); |
678 | it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); | ||
679 | } else { | ||
680 | mutex_unlock(&data->update_lock); | ||
681 | return -EINVAL; | ||
682 | } | 787 | } |
683 | 788 | ||
684 | mutex_unlock(&data->update_lock); | 789 | mutex_unlock(&data->update_lock); |
@@ -691,15 +796,19 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
691 | int nr = sensor_attr->index; | 796 | int nr = sensor_attr->index; |
692 | 797 | ||
693 | struct it87_data *data = dev_get_drvdata(dev); | 798 | struct it87_data *data = dev_get_drvdata(dev); |
694 | int val = simple_strtol(buf, NULL, 10); | 799 | long val; |
695 | 800 | ||
696 | if (val < 0 || val > 255) | 801 | if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 255) |
697 | return -EINVAL; | 802 | return -EINVAL; |
698 | 803 | ||
699 | mutex_lock(&data->update_lock); | 804 | mutex_lock(&data->update_lock); |
700 | data->manual_pwm_ctl[nr] = val; | 805 | data->pwm_duty[nr] = PWM_TO_REG(val); |
701 | if (data->fan_main_ctrl & (1 << nr)) | 806 | /* If we are in manual mode, write the duty cycle immediately; |
702 | it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); | 807 | * otherwise, just store it for later use. */ |
808 | if (!(data->pwm_ctrl[nr] & 0x80)) { | ||
809 | data->pwm_ctrl[nr] = data->pwm_duty[nr]; | ||
810 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); | ||
811 | } | ||
703 | mutex_unlock(&data->update_lock); | 812 | mutex_unlock(&data->update_lock); |
704 | return count; | 813 | return count; |
705 | } | 814 | } |
@@ -707,9 +816,12 @@ static ssize_t set_pwm_freq(struct device *dev, | |||
707 | struct device_attribute *attr, const char *buf, size_t count) | 816 | struct device_attribute *attr, const char *buf, size_t count) |
708 | { | 817 | { |
709 | struct it87_data *data = dev_get_drvdata(dev); | 818 | struct it87_data *data = dev_get_drvdata(dev); |
710 | unsigned long val = simple_strtoul(buf, NULL, 10); | 819 | unsigned long val; |
711 | int i; | 820 | int i; |
712 | 821 | ||
822 | if (strict_strtoul(buf, 10, &val) < 0) | ||
823 | return -EINVAL; | ||
824 | |||
713 | /* Search for the nearest available frequency */ | 825 | /* Search for the nearest available frequency */ |
714 | for (i = 0; i < 7; i++) { | 826 | for (i = 0; i < 7; i++) { |
715 | if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) | 827 | if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) |
@@ -724,6 +836,132 @@ static ssize_t set_pwm_freq(struct device *dev, | |||
724 | 836 | ||
725 | return count; | 837 | return count; |
726 | } | 838 | } |
839 | static ssize_t show_pwm_temp_map(struct device *dev, | ||
840 | struct device_attribute *attr, char *buf) | ||
841 | { | ||
842 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
843 | int nr = sensor_attr->index; | ||
844 | |||
845 | struct it87_data *data = it87_update_device(dev); | ||
846 | int map; | ||
847 | |||
848 | if (data->pwm_temp_map[nr] < 3) | ||
849 | map = 1 << data->pwm_temp_map[nr]; | ||
850 | else | ||
851 | map = 0; /* Should never happen */ | ||
852 | return sprintf(buf, "%d\n", map); | ||
853 | } | ||
854 | static ssize_t set_pwm_temp_map(struct device *dev, | ||
855 | struct device_attribute *attr, const char *buf, size_t count) | ||
856 | { | ||
857 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
858 | int nr = sensor_attr->index; | ||
859 | |||
860 | struct it87_data *data = dev_get_drvdata(dev); | ||
861 | long val; | ||
862 | u8 reg; | ||
863 | |||
864 | /* This check can go away if we ever support automatic fan speed | ||
865 | control on newer chips. */ | ||
866 | if (!has_old_autopwm(data)) { | ||
867 | dev_notice(dev, "Mapping change disabled for safety reasons\n"); | ||
868 | return -EINVAL; | ||
869 | } | ||
870 | |||
871 | if (strict_strtol(buf, 10, &val) < 0) | ||
872 | return -EINVAL; | ||
873 | |||
874 | switch (val) { | ||
875 | case (1 << 0): | ||
876 | reg = 0x00; | ||
877 | break; | ||
878 | case (1 << 1): | ||
879 | reg = 0x01; | ||
880 | break; | ||
881 | case (1 << 2): | ||
882 | reg = 0x02; | ||
883 | break; | ||
884 | default: | ||
885 | return -EINVAL; | ||
886 | } | ||
887 | |||
888 | mutex_lock(&data->update_lock); | ||
889 | data->pwm_temp_map[nr] = reg; | ||
890 | /* If we are in automatic mode, write the temp mapping immediately; | ||
891 | * otherwise, just store it for later use. */ | ||
892 | if (data->pwm_ctrl[nr] & 0x80) { | ||
893 | data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; | ||
894 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); | ||
895 | } | ||
896 | mutex_unlock(&data->update_lock); | ||
897 | return count; | ||
898 | } | ||
899 | |||
900 | static ssize_t show_auto_pwm(struct device *dev, | ||
901 | struct device_attribute *attr, char *buf) | ||
902 | { | ||
903 | struct it87_data *data = it87_update_device(dev); | ||
904 | struct sensor_device_attribute_2 *sensor_attr = | ||
905 | to_sensor_dev_attr_2(attr); | ||
906 | int nr = sensor_attr->nr; | ||
907 | int point = sensor_attr->index; | ||
908 | |||
909 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->auto_pwm[nr][point])); | ||
910 | } | ||
911 | |||
912 | static ssize_t set_auto_pwm(struct device *dev, | ||
913 | struct device_attribute *attr, const char *buf, size_t count) | ||
914 | { | ||
915 | struct it87_data *data = dev_get_drvdata(dev); | ||
916 | struct sensor_device_attribute_2 *sensor_attr = | ||
917 | to_sensor_dev_attr_2(attr); | ||
918 | int nr = sensor_attr->nr; | ||
919 | int point = sensor_attr->index; | ||
920 | long val; | ||
921 | |||
922 | if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 255) | ||
923 | return -EINVAL; | ||
924 | |||
925 | mutex_lock(&data->update_lock); | ||
926 | data->auto_pwm[nr][point] = PWM_TO_REG(val); | ||
927 | it87_write_value(data, IT87_REG_AUTO_PWM(nr, point), | ||
928 | data->auto_pwm[nr][point]); | ||
929 | mutex_unlock(&data->update_lock); | ||
930 | return count; | ||
931 | } | ||
932 | |||
933 | static ssize_t show_auto_temp(struct device *dev, | ||
934 | struct device_attribute *attr, char *buf) | ||
935 | { | ||
936 | struct it87_data *data = it87_update_device(dev); | ||
937 | struct sensor_device_attribute_2 *sensor_attr = | ||
938 | to_sensor_dev_attr_2(attr); | ||
939 | int nr = sensor_attr->nr; | ||
940 | int point = sensor_attr->index; | ||
941 | |||
942 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->auto_temp[nr][point])); | ||
943 | } | ||
944 | |||
945 | static ssize_t set_auto_temp(struct device *dev, | ||
946 | struct device_attribute *attr, const char *buf, size_t count) | ||
947 | { | ||
948 | struct it87_data *data = dev_get_drvdata(dev); | ||
949 | struct sensor_device_attribute_2 *sensor_attr = | ||
950 | to_sensor_dev_attr_2(attr); | ||
951 | int nr = sensor_attr->nr; | ||
952 | int point = sensor_attr->index; | ||
953 | long val; | ||
954 | |||
955 | if (strict_strtol(buf, 10, &val) < 0 || val < -128000 || val > 127000) | ||
956 | return -EINVAL; | ||
957 | |||
958 | mutex_lock(&data->update_lock); | ||
959 | data->auto_temp[nr][point] = TEMP_TO_REG(val); | ||
960 | it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point), | ||
961 | data->auto_temp[nr][point]); | ||
962 | mutex_unlock(&data->update_lock); | ||
963 | return count; | ||
964 | } | ||
727 | 965 | ||
728 | #define show_fan_offset(offset) \ | 966 | #define show_fan_offset(offset) \ |
729 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ | 967 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ |
@@ -744,7 +982,36 @@ static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | |||
744 | show_pwm, set_pwm, offset - 1); \ | 982 | show_pwm, set_pwm, offset - 1); \ |
745 | static DEVICE_ATTR(pwm##offset##_freq, \ | 983 | static DEVICE_ATTR(pwm##offset##_freq, \ |
746 | (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ | 984 | (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ |
747 | show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); | 985 | show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); \ |
986 | static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels_temp, \ | ||
987 | S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, \ | ||
988 | offset - 1); \ | ||
989 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_pwm, \ | ||
990 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | ||
991 | offset - 1, 0); \ | ||
992 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_pwm, \ | ||
993 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | ||
994 | offset - 1, 1); \ | ||
995 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_pwm, \ | ||
996 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | ||
997 | offset - 1, 2); \ | ||
998 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_pwm, \ | ||
999 | S_IRUGO, show_auto_pwm, NULL, offset - 1, 3); \ | ||
1000 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp, \ | ||
1001 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
1002 | offset - 1, 1); \ | ||
1003 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp_hyst, \ | ||
1004 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
1005 | offset - 1, 0); \ | ||
1006 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_temp, \ | ||
1007 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
1008 | offset - 1, 2); \ | ||
1009 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_temp, \ | ||
1010 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
1011 | offset - 1, 3); \ | ||
1012 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_temp, \ | ||
1013 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
1014 | offset - 1, 4); | ||
748 | 1015 | ||
749 | show_pwm_offset(1); | 1016 | show_pwm_offset(1); |
750 | show_pwm_offset(2); | 1017 | show_pwm_offset(2); |
@@ -775,7 +1042,10 @@ static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr, | |||
775 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 1042 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
776 | int nr = sensor_attr->index; | 1043 | int nr = sensor_attr->index; |
777 | struct it87_data *data = dev_get_drvdata(dev); | 1044 | struct it87_data *data = dev_get_drvdata(dev); |
778 | int val = simple_strtol(buf, NULL, 10); | 1045 | long val; |
1046 | |||
1047 | if (strict_strtol(buf, 10, &val) < 0) | ||
1048 | return -EINVAL; | ||
779 | 1049 | ||
780 | mutex_lock(&data->update_lock); | 1050 | mutex_lock(&data->update_lock); |
781 | data->fan_min[nr] = FAN16_TO_REG(val); | 1051 | data->fan_min[nr] = FAN16_TO_REG(val); |
@@ -805,7 +1075,8 @@ show_fan16_offset(4); | |||
805 | show_fan16_offset(5); | 1075 | show_fan16_offset(5); |
806 | 1076 | ||
807 | /* Alarms */ | 1077 | /* Alarms */ |
808 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 1078 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, |
1079 | char *buf) | ||
809 | { | 1080 | { |
810 | struct it87_data *data = it87_update_device(dev); | 1081 | struct it87_data *data = it87_update_device(dev); |
811 | return sprintf(buf, "%u\n", data->alarms); | 1082 | return sprintf(buf, "%u\n", data->alarms); |
@@ -836,27 +1107,78 @@ static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16); | |||
836 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17); | 1107 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17); |
837 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18); | 1108 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18); |
838 | 1109 | ||
839 | static ssize_t | 1110 | static ssize_t show_beep(struct device *dev, struct device_attribute *attr, |
840 | show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) | 1111 | char *buf) |
1112 | { | ||
1113 | int bitnr = to_sensor_dev_attr(attr)->index; | ||
1114 | struct it87_data *data = it87_update_device(dev); | ||
1115 | return sprintf(buf, "%u\n", (data->beeps >> bitnr) & 1); | ||
1116 | } | ||
1117 | static ssize_t set_beep(struct device *dev, struct device_attribute *attr, | ||
1118 | const char *buf, size_t count) | ||
1119 | { | ||
1120 | int bitnr = to_sensor_dev_attr(attr)->index; | ||
1121 | struct it87_data *data = dev_get_drvdata(dev); | ||
1122 | long val; | ||
1123 | |||
1124 | if (strict_strtol(buf, 10, &val) < 0 | ||
1125 | || (val != 0 && val != 1)) | ||
1126 | return -EINVAL; | ||
1127 | |||
1128 | mutex_lock(&data->update_lock); | ||
1129 | data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); | ||
1130 | if (val) | ||
1131 | data->beeps |= (1 << bitnr); | ||
1132 | else | ||
1133 | data->beeps &= ~(1 << bitnr); | ||
1134 | it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps); | ||
1135 | mutex_unlock(&data->update_lock); | ||
1136 | return count; | ||
1137 | } | ||
1138 | |||
1139 | static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, | ||
1140 | show_beep, set_beep, 1); | ||
1141 | static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO, show_beep, NULL, 1); | ||
1142 | static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO, show_beep, NULL, 1); | ||
1143 | static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO, show_beep, NULL, 1); | ||
1144 | static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO, show_beep, NULL, 1); | ||
1145 | static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO, show_beep, NULL, 1); | ||
1146 | static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO, show_beep, NULL, 1); | ||
1147 | static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO, show_beep, NULL, 1); | ||
1148 | /* fanX_beep writability is set later */ | ||
1149 | static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO, show_beep, set_beep, 0); | ||
1150 | static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO, show_beep, set_beep, 0); | ||
1151 | static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO, show_beep, set_beep, 0); | ||
1152 | static SENSOR_DEVICE_ATTR(fan4_beep, S_IRUGO, show_beep, set_beep, 0); | ||
1153 | static SENSOR_DEVICE_ATTR(fan5_beep, S_IRUGO, show_beep, set_beep, 0); | ||
1154 | static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, | ||
1155 | show_beep, set_beep, 2); | ||
1156 | static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO, show_beep, NULL, 2); | ||
1157 | static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, show_beep, NULL, 2); | ||
1158 | |||
1159 | static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, | ||
1160 | char *buf) | ||
841 | { | 1161 | { |
842 | struct it87_data *data = dev_get_drvdata(dev); | 1162 | struct it87_data *data = dev_get_drvdata(dev); |
843 | return sprintf(buf, "%u\n", data->vrm); | 1163 | return sprintf(buf, "%u\n", data->vrm); |
844 | } | 1164 | } |
845 | static ssize_t | 1165 | static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, |
846 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1166 | const char *buf, size_t count) |
847 | { | 1167 | { |
848 | struct it87_data *data = dev_get_drvdata(dev); | 1168 | struct it87_data *data = dev_get_drvdata(dev); |
849 | u32 val; | 1169 | unsigned long val; |
1170 | |||
1171 | if (strict_strtoul(buf, 10, &val) < 0) | ||
1172 | return -EINVAL; | ||
850 | 1173 | ||
851 | val = simple_strtoul(buf, NULL, 10); | ||
852 | data->vrm = val; | 1174 | data->vrm = val; |
853 | 1175 | ||
854 | return count; | 1176 | return count; |
855 | } | 1177 | } |
856 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); | 1178 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); |
857 | 1179 | ||
858 | static ssize_t | 1180 | static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, |
859 | show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) | 1181 | char *buf) |
860 | { | 1182 | { |
861 | struct it87_data *data = it87_update_device(dev); | 1183 | struct it87_data *data = it87_update_device(dev); |
862 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); | 1184 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); |
@@ -931,51 +1253,176 @@ static const struct attribute_group it87_group = { | |||
931 | .attrs = it87_attributes, | 1253 | .attrs = it87_attributes, |
932 | }; | 1254 | }; |
933 | 1255 | ||
934 | static struct attribute *it87_attributes_opt[] = { | 1256 | static struct attribute *it87_attributes_beep[] = { |
1257 | &sensor_dev_attr_in0_beep.dev_attr.attr, | ||
1258 | &sensor_dev_attr_in1_beep.dev_attr.attr, | ||
1259 | &sensor_dev_attr_in2_beep.dev_attr.attr, | ||
1260 | &sensor_dev_attr_in3_beep.dev_attr.attr, | ||
1261 | &sensor_dev_attr_in4_beep.dev_attr.attr, | ||
1262 | &sensor_dev_attr_in5_beep.dev_attr.attr, | ||
1263 | &sensor_dev_attr_in6_beep.dev_attr.attr, | ||
1264 | &sensor_dev_attr_in7_beep.dev_attr.attr, | ||
1265 | |||
1266 | &sensor_dev_attr_temp1_beep.dev_attr.attr, | ||
1267 | &sensor_dev_attr_temp2_beep.dev_attr.attr, | ||
1268 | &sensor_dev_attr_temp3_beep.dev_attr.attr, | ||
1269 | NULL | ||
1270 | }; | ||
1271 | |||
1272 | static const struct attribute_group it87_group_beep = { | ||
1273 | .attrs = it87_attributes_beep, | ||
1274 | }; | ||
1275 | |||
1276 | static struct attribute *it87_attributes_fan16[5][3+1] = { { | ||
935 | &sensor_dev_attr_fan1_input16.dev_attr.attr, | 1277 | &sensor_dev_attr_fan1_input16.dev_attr.attr, |
936 | &sensor_dev_attr_fan1_min16.dev_attr.attr, | 1278 | &sensor_dev_attr_fan1_min16.dev_attr.attr, |
1279 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
1280 | NULL | ||
1281 | }, { | ||
937 | &sensor_dev_attr_fan2_input16.dev_attr.attr, | 1282 | &sensor_dev_attr_fan2_input16.dev_attr.attr, |
938 | &sensor_dev_attr_fan2_min16.dev_attr.attr, | 1283 | &sensor_dev_attr_fan2_min16.dev_attr.attr, |
1284 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
1285 | NULL | ||
1286 | }, { | ||
939 | &sensor_dev_attr_fan3_input16.dev_attr.attr, | 1287 | &sensor_dev_attr_fan3_input16.dev_attr.attr, |
940 | &sensor_dev_attr_fan3_min16.dev_attr.attr, | 1288 | &sensor_dev_attr_fan3_min16.dev_attr.attr, |
1289 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | ||
1290 | NULL | ||
1291 | }, { | ||
941 | &sensor_dev_attr_fan4_input16.dev_attr.attr, | 1292 | &sensor_dev_attr_fan4_input16.dev_attr.attr, |
942 | &sensor_dev_attr_fan4_min16.dev_attr.attr, | 1293 | &sensor_dev_attr_fan4_min16.dev_attr.attr, |
1294 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, | ||
1295 | NULL | ||
1296 | }, { | ||
943 | &sensor_dev_attr_fan5_input16.dev_attr.attr, | 1297 | &sensor_dev_attr_fan5_input16.dev_attr.attr, |
944 | &sensor_dev_attr_fan5_min16.dev_attr.attr, | 1298 | &sensor_dev_attr_fan5_min16.dev_attr.attr, |
1299 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, | ||
1300 | NULL | ||
1301 | } }; | ||
1302 | |||
1303 | static const struct attribute_group it87_group_fan16[5] = { | ||
1304 | { .attrs = it87_attributes_fan16[0] }, | ||
1305 | { .attrs = it87_attributes_fan16[1] }, | ||
1306 | { .attrs = it87_attributes_fan16[2] }, | ||
1307 | { .attrs = it87_attributes_fan16[3] }, | ||
1308 | { .attrs = it87_attributes_fan16[4] }, | ||
1309 | }; | ||
945 | 1310 | ||
1311 | static struct attribute *it87_attributes_fan[3][4+1] = { { | ||
946 | &sensor_dev_attr_fan1_input.dev_attr.attr, | 1312 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
947 | &sensor_dev_attr_fan1_min.dev_attr.attr, | 1313 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
948 | &sensor_dev_attr_fan1_div.dev_attr.attr, | 1314 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
1315 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
1316 | NULL | ||
1317 | }, { | ||
949 | &sensor_dev_attr_fan2_input.dev_attr.attr, | 1318 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
950 | &sensor_dev_attr_fan2_min.dev_attr.attr, | 1319 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
951 | &sensor_dev_attr_fan2_div.dev_attr.attr, | 1320 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
1321 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
1322 | NULL | ||
1323 | }, { | ||
952 | &sensor_dev_attr_fan3_input.dev_attr.attr, | 1324 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
953 | &sensor_dev_attr_fan3_min.dev_attr.attr, | 1325 | &sensor_dev_attr_fan3_min.dev_attr.attr, |
954 | &sensor_dev_attr_fan3_div.dev_attr.attr, | 1326 | &sensor_dev_attr_fan3_div.dev_attr.attr, |
955 | |||
956 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
957 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
958 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | 1327 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, |
959 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, | 1328 | NULL |
960 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, | 1329 | } }; |
1330 | |||
1331 | static const struct attribute_group it87_group_fan[3] = { | ||
1332 | { .attrs = it87_attributes_fan[0] }, | ||
1333 | { .attrs = it87_attributes_fan[1] }, | ||
1334 | { .attrs = it87_attributes_fan[2] }, | ||
1335 | }; | ||
1336 | |||
1337 | static const struct attribute_group * | ||
1338 | it87_get_fan_group(const struct it87_data *data) | ||
1339 | { | ||
1340 | return has_16bit_fans(data) ? it87_group_fan16 : it87_group_fan; | ||
1341 | } | ||
961 | 1342 | ||
1343 | static struct attribute *it87_attributes_pwm[3][4+1] = { { | ||
962 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | 1344 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, |
963 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
964 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
965 | &sensor_dev_attr_pwm1.dev_attr.attr, | 1345 | &sensor_dev_attr_pwm1.dev_attr.attr, |
966 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
967 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
968 | &dev_attr_pwm1_freq.attr, | 1346 | &dev_attr_pwm1_freq.attr, |
1347 | &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, | ||
1348 | NULL | ||
1349 | }, { | ||
1350 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
1351 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
969 | &dev_attr_pwm2_freq.attr, | 1352 | &dev_attr_pwm2_freq.attr, |
1353 | &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, | ||
1354 | NULL | ||
1355 | }, { | ||
1356 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
1357 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
970 | &dev_attr_pwm3_freq.attr, | 1358 | &dev_attr_pwm3_freq.attr, |
1359 | &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, | ||
1360 | NULL | ||
1361 | } }; | ||
1362 | |||
1363 | static const struct attribute_group it87_group_pwm[3] = { | ||
1364 | { .attrs = it87_attributes_pwm[0] }, | ||
1365 | { .attrs = it87_attributes_pwm[1] }, | ||
1366 | { .attrs = it87_attributes_pwm[2] }, | ||
1367 | }; | ||
971 | 1368 | ||
1369 | static struct attribute *it87_attributes_autopwm[3][9+1] = { { | ||
1370 | &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, | ||
1371 | &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, | ||
1372 | &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, | ||
1373 | &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr, | ||
1374 | &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, | ||
1375 | &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr, | ||
1376 | &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, | ||
1377 | &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, | ||
1378 | &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr, | ||
1379 | NULL | ||
1380 | }, { | ||
1381 | &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, | ||
1382 | &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, | ||
1383 | &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr, | ||
1384 | &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr, | ||
1385 | &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr, | ||
1386 | &sensor_dev_attr_pwm2_auto_point1_temp_hyst.dev_attr.attr, | ||
1387 | &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, | ||
1388 | &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr, | ||
1389 | &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr, | ||
1390 | NULL | ||
1391 | }, { | ||
1392 | &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, | ||
1393 | &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, | ||
1394 | &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr, | ||
1395 | &sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr, | ||
1396 | &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr, | ||
1397 | &sensor_dev_attr_pwm3_auto_point1_temp_hyst.dev_attr.attr, | ||
1398 | &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, | ||
1399 | &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr, | ||
1400 | &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr, | ||
1401 | NULL | ||
1402 | } }; | ||
1403 | |||
1404 | static const struct attribute_group it87_group_autopwm[3] = { | ||
1405 | { .attrs = it87_attributes_autopwm[0] }, | ||
1406 | { .attrs = it87_attributes_autopwm[1] }, | ||
1407 | { .attrs = it87_attributes_autopwm[2] }, | ||
1408 | }; | ||
1409 | |||
1410 | static struct attribute *it87_attributes_fan_beep[] = { | ||
1411 | &sensor_dev_attr_fan1_beep.dev_attr.attr, | ||
1412 | &sensor_dev_attr_fan2_beep.dev_attr.attr, | ||
1413 | &sensor_dev_attr_fan3_beep.dev_attr.attr, | ||
1414 | &sensor_dev_attr_fan4_beep.dev_attr.attr, | ||
1415 | &sensor_dev_attr_fan5_beep.dev_attr.attr, | ||
1416 | }; | ||
1417 | |||
1418 | static struct attribute *it87_attributes_vid[] = { | ||
972 | &dev_attr_vrm.attr, | 1419 | &dev_attr_vrm.attr, |
973 | &dev_attr_cpu0_vid.attr, | 1420 | &dev_attr_cpu0_vid.attr, |
974 | NULL | 1421 | NULL |
975 | }; | 1422 | }; |
976 | 1423 | ||
977 | static const struct attribute_group it87_group_opt = { | 1424 | static const struct attribute_group it87_group_vid = { |
978 | .attrs = it87_attributes_opt, | 1425 | .attrs = it87_attributes_vid, |
979 | }; | 1426 | }; |
980 | 1427 | ||
981 | /* SuperIO detection - will change isa_address if a chip is found */ | 1428 | /* SuperIO detection - will change isa_address if a chip is found */ |
@@ -1035,6 +1482,10 @@ static int __init it87_find(unsigned short *address, | |||
1035 | if (sio_data->type == it87) { | 1482 | if (sio_data->type == it87) { |
1036 | /* The IT8705F doesn't have VID pins at all */ | 1483 | /* The IT8705F doesn't have VID pins at all */ |
1037 | sio_data->skip_vid = 1; | 1484 | sio_data->skip_vid = 1; |
1485 | |||
1486 | /* The IT8705F has a different LD number for GPIO */ | ||
1487 | superio_select(5); | ||
1488 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
1038 | } else { | 1489 | } else { |
1039 | int reg; | 1490 | int reg; |
1040 | 1491 | ||
@@ -1068,7 +1519,11 @@ static int __init it87_find(unsigned short *address, | |||
1068 | pr_info("it87: in3 is VCC (+5V)\n"); | 1519 | pr_info("it87: in3 is VCC (+5V)\n"); |
1069 | if (reg & (1 << 1)) | 1520 | if (reg & (1 << 1)) |
1070 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); | 1521 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); |
1522 | |||
1523 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
1071 | } | 1524 | } |
1525 | if (sio_data->beep_pin) | ||
1526 | pr_info("it87: Beeping is supported\n"); | ||
1072 | 1527 | ||
1073 | /* Disable specific features based on DMI strings */ | 1528 | /* Disable specific features based on DMI strings */ |
1074 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | 1529 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); |
@@ -1093,14 +1548,46 @@ exit: | |||
1093 | return err; | 1548 | return err; |
1094 | } | 1549 | } |
1095 | 1550 | ||
1551 | static void it87_remove_files(struct device *dev) | ||
1552 | { | ||
1553 | struct it87_data *data = platform_get_drvdata(pdev); | ||
1554 | struct it87_sio_data *sio_data = dev->platform_data; | ||
1555 | const struct attribute_group *fan_group = it87_get_fan_group(data); | ||
1556 | int i; | ||
1557 | |||
1558 | sysfs_remove_group(&dev->kobj, &it87_group); | ||
1559 | if (sio_data->beep_pin) | ||
1560 | sysfs_remove_group(&dev->kobj, &it87_group_beep); | ||
1561 | for (i = 0; i < 5; i++) { | ||
1562 | if (!(data->has_fan & (1 << i))) | ||
1563 | continue; | ||
1564 | sysfs_remove_group(&dev->kobj, &fan_group[i]); | ||
1565 | if (sio_data->beep_pin) | ||
1566 | sysfs_remove_file(&dev->kobj, | ||
1567 | it87_attributes_fan_beep[i]); | ||
1568 | } | ||
1569 | for (i = 0; i < 3; i++) { | ||
1570 | if (sio_data->skip_pwm & (1 << 0)) | ||
1571 | continue; | ||
1572 | sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]); | ||
1573 | if (has_old_autopwm(data)) | ||
1574 | sysfs_remove_group(&dev->kobj, | ||
1575 | &it87_group_autopwm[i]); | ||
1576 | } | ||
1577 | if (!sio_data->skip_vid) | ||
1578 | sysfs_remove_group(&dev->kobj, &it87_group_vid); | ||
1579 | } | ||
1580 | |||
1096 | static int __devinit it87_probe(struct platform_device *pdev) | 1581 | static int __devinit it87_probe(struct platform_device *pdev) |
1097 | { | 1582 | { |
1098 | struct it87_data *data; | 1583 | struct it87_data *data; |
1099 | struct resource *res; | 1584 | struct resource *res; |
1100 | struct device *dev = &pdev->dev; | 1585 | struct device *dev = &pdev->dev; |
1101 | struct it87_sio_data *sio_data = dev->platform_data; | 1586 | struct it87_sio_data *sio_data = dev->platform_data; |
1102 | int err = 0; | 1587 | const struct attribute_group *fan_group; |
1588 | int err = 0, i; | ||
1103 | int enable_pwm_interface; | 1589 | int enable_pwm_interface; |
1590 | int fan_beep_need_rw; | ||
1104 | static const char *names[] = { | 1591 | static const char *names[] = { |
1105 | "it87", | 1592 | "it87", |
1106 | "it8712", | 1593 | "it8712", |
@@ -1118,7 +1605,8 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1118 | goto ERROR0; | 1605 | goto ERROR0; |
1119 | } | 1606 | } |
1120 | 1607 | ||
1121 | if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) { | 1608 | data = kzalloc(sizeof(struct it87_data), GFP_KERNEL); |
1609 | if (!data) { | ||
1122 | err = -ENOMEM; | 1610 | err = -ENOMEM; |
1123 | goto ERROR1; | 1611 | goto ERROR1; |
1124 | } | 1612 | } |
@@ -1146,120 +1634,60 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1146 | it87_init_device(pdev); | 1634 | it87_init_device(pdev); |
1147 | 1635 | ||
1148 | /* Register sysfs hooks */ | 1636 | /* Register sysfs hooks */ |
1149 | if ((err = sysfs_create_group(&dev->kobj, &it87_group))) | 1637 | err = sysfs_create_group(&dev->kobj, &it87_group); |
1638 | if (err) | ||
1150 | goto ERROR2; | 1639 | goto ERROR2; |
1151 | 1640 | ||
1641 | if (sio_data->beep_pin) { | ||
1642 | err = sysfs_create_group(&dev->kobj, &it87_group_beep); | ||
1643 | if (err) | ||
1644 | goto ERROR4; | ||
1645 | } | ||
1646 | |||
1152 | /* Do not create fan files for disabled fans */ | 1647 | /* Do not create fan files for disabled fans */ |
1153 | if (has_16bit_fans(data)) { | 1648 | fan_group = it87_get_fan_group(data); |
1154 | /* 16-bit tachometers */ | 1649 | fan_beep_need_rw = 1; |
1155 | if (data->has_fan & (1 << 0)) { | 1650 | for (i = 0; i < 5; i++) { |
1156 | if ((err = device_create_file(dev, | 1651 | if (!(data->has_fan & (1 << i))) |
1157 | &sensor_dev_attr_fan1_input16.dev_attr)) | 1652 | continue; |
1158 | || (err = device_create_file(dev, | 1653 | err = sysfs_create_group(&dev->kobj, &fan_group[i]); |
1159 | &sensor_dev_attr_fan1_min16.dev_attr)) | 1654 | if (err) |
1160 | || (err = device_create_file(dev, | 1655 | goto ERROR4; |
1161 | &sensor_dev_attr_fan1_alarm.dev_attr))) | 1656 | |
1162 | goto ERROR4; | 1657 | if (sio_data->beep_pin) { |
1163 | } | 1658 | err = sysfs_create_file(&dev->kobj, |
1164 | if (data->has_fan & (1 << 1)) { | 1659 | it87_attributes_fan_beep[i]); |
1165 | if ((err = device_create_file(dev, | 1660 | if (err) |
1166 | &sensor_dev_attr_fan2_input16.dev_attr)) | ||
1167 | || (err = device_create_file(dev, | ||
1168 | &sensor_dev_attr_fan2_min16.dev_attr)) | ||
1169 | || (err = device_create_file(dev, | ||
1170 | &sensor_dev_attr_fan2_alarm.dev_attr))) | ||
1171 | goto ERROR4; | ||
1172 | } | ||
1173 | if (data->has_fan & (1 << 2)) { | ||
1174 | if ((err = device_create_file(dev, | ||
1175 | &sensor_dev_attr_fan3_input16.dev_attr)) | ||
1176 | || (err = device_create_file(dev, | ||
1177 | &sensor_dev_attr_fan3_min16.dev_attr)) | ||
1178 | || (err = device_create_file(dev, | ||
1179 | &sensor_dev_attr_fan3_alarm.dev_attr))) | ||
1180 | goto ERROR4; | ||
1181 | } | ||
1182 | if (data->has_fan & (1 << 3)) { | ||
1183 | if ((err = device_create_file(dev, | ||
1184 | &sensor_dev_attr_fan4_input16.dev_attr)) | ||
1185 | || (err = device_create_file(dev, | ||
1186 | &sensor_dev_attr_fan4_min16.dev_attr)) | ||
1187 | || (err = device_create_file(dev, | ||
1188 | &sensor_dev_attr_fan4_alarm.dev_attr))) | ||
1189 | goto ERROR4; | ||
1190 | } | ||
1191 | if (data->has_fan & (1 << 4)) { | ||
1192 | if ((err = device_create_file(dev, | ||
1193 | &sensor_dev_attr_fan5_input16.dev_attr)) | ||
1194 | || (err = device_create_file(dev, | ||
1195 | &sensor_dev_attr_fan5_min16.dev_attr)) | ||
1196 | || (err = device_create_file(dev, | ||
1197 | &sensor_dev_attr_fan5_alarm.dev_attr))) | ||
1198 | goto ERROR4; | ||
1199 | } | ||
1200 | } else { | ||
1201 | /* 8-bit tachometers with clock divider */ | ||
1202 | if (data->has_fan & (1 << 0)) { | ||
1203 | if ((err = device_create_file(dev, | ||
1204 | &sensor_dev_attr_fan1_input.dev_attr)) | ||
1205 | || (err = device_create_file(dev, | ||
1206 | &sensor_dev_attr_fan1_min.dev_attr)) | ||
1207 | || (err = device_create_file(dev, | ||
1208 | &sensor_dev_attr_fan1_div.dev_attr)) | ||
1209 | || (err = device_create_file(dev, | ||
1210 | &sensor_dev_attr_fan1_alarm.dev_attr))) | ||
1211 | goto ERROR4; | ||
1212 | } | ||
1213 | if (data->has_fan & (1 << 1)) { | ||
1214 | if ((err = device_create_file(dev, | ||
1215 | &sensor_dev_attr_fan2_input.dev_attr)) | ||
1216 | || (err = device_create_file(dev, | ||
1217 | &sensor_dev_attr_fan2_min.dev_attr)) | ||
1218 | || (err = device_create_file(dev, | ||
1219 | &sensor_dev_attr_fan2_div.dev_attr)) | ||
1220 | || (err = device_create_file(dev, | ||
1221 | &sensor_dev_attr_fan2_alarm.dev_attr))) | ||
1222 | goto ERROR4; | ||
1223 | } | ||
1224 | if (data->has_fan & (1 << 2)) { | ||
1225 | if ((err = device_create_file(dev, | ||
1226 | &sensor_dev_attr_fan3_input.dev_attr)) | ||
1227 | || (err = device_create_file(dev, | ||
1228 | &sensor_dev_attr_fan3_min.dev_attr)) | ||
1229 | || (err = device_create_file(dev, | ||
1230 | &sensor_dev_attr_fan3_div.dev_attr)) | ||
1231 | || (err = device_create_file(dev, | ||
1232 | &sensor_dev_attr_fan3_alarm.dev_attr))) | ||
1233 | goto ERROR4; | 1661 | goto ERROR4; |
1662 | if (!fan_beep_need_rw) | ||
1663 | continue; | ||
1664 | |||
1665 | /* As we have a single beep enable bit for all fans, | ||
1666 | * only the first enabled fan has a writable attribute | ||
1667 | * for it. */ | ||
1668 | if (sysfs_chmod_file(&dev->kobj, | ||
1669 | it87_attributes_fan_beep[i], | ||
1670 | S_IRUGO | S_IWUSR)) | ||
1671 | dev_dbg(dev, "chmod +w fan%d_beep failed\n", | ||
1672 | i + 1); | ||
1673 | fan_beep_need_rw = 0; | ||
1234 | } | 1674 | } |
1235 | } | 1675 | } |
1236 | 1676 | ||
1237 | if (enable_pwm_interface) { | 1677 | if (enable_pwm_interface) { |
1238 | if (!(sio_data->skip_pwm & (1 << 0))) { | 1678 | for (i = 0; i < 3; i++) { |
1239 | if ((err = device_create_file(dev, | 1679 | if (sio_data->skip_pwm & (1 << i)) |
1240 | &sensor_dev_attr_pwm1_enable.dev_attr)) | 1680 | continue; |
1241 | || (err = device_create_file(dev, | 1681 | err = sysfs_create_group(&dev->kobj, |
1242 | &sensor_dev_attr_pwm1.dev_attr)) | 1682 | &it87_group_pwm[i]); |
1243 | || (err = device_create_file(dev, | 1683 | if (err) |
1244 | &dev_attr_pwm1_freq))) | ||
1245 | goto ERROR4; | ||
1246 | } | ||
1247 | if (!(sio_data->skip_pwm & (1 << 1))) { | ||
1248 | if ((err = device_create_file(dev, | ||
1249 | &sensor_dev_attr_pwm2_enable.dev_attr)) | ||
1250 | || (err = device_create_file(dev, | ||
1251 | &sensor_dev_attr_pwm2.dev_attr)) | ||
1252 | || (err = device_create_file(dev, | ||
1253 | &dev_attr_pwm2_freq))) | ||
1254 | goto ERROR4; | 1684 | goto ERROR4; |
1255 | } | 1685 | |
1256 | if (!(sio_data->skip_pwm & (1 << 2))) { | 1686 | if (!has_old_autopwm(data)) |
1257 | if ((err = device_create_file(dev, | 1687 | continue; |
1258 | &sensor_dev_attr_pwm3_enable.dev_attr)) | 1688 | err = sysfs_create_group(&dev->kobj, |
1259 | || (err = device_create_file(dev, | 1689 | &it87_group_autopwm[i]); |
1260 | &sensor_dev_attr_pwm3.dev_attr)) | 1690 | if (err) |
1261 | || (err = device_create_file(dev, | ||
1262 | &dev_attr_pwm3_freq))) | ||
1263 | goto ERROR4; | 1691 | goto ERROR4; |
1264 | } | 1692 | } |
1265 | } | 1693 | } |
@@ -1268,10 +1696,8 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1268 | data->vrm = vid_which_vrm(); | 1696 | data->vrm = vid_which_vrm(); |
1269 | /* VID reading from Super-I/O config space if available */ | 1697 | /* VID reading from Super-I/O config space if available */ |
1270 | data->vid = sio_data->vid_value; | 1698 | data->vid = sio_data->vid_value; |
1271 | if ((err = device_create_file(dev, | 1699 | err = sysfs_create_group(&dev->kobj, &it87_group_vid); |
1272 | &dev_attr_vrm)) | 1700 | if (err) |
1273 | || (err = device_create_file(dev, | ||
1274 | &dev_attr_cpu0_vid))) | ||
1275 | goto ERROR4; | 1701 | goto ERROR4; |
1276 | } | 1702 | } |
1277 | 1703 | ||
@@ -1284,8 +1710,7 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1284 | return 0; | 1710 | return 0; |
1285 | 1711 | ||
1286 | ERROR4: | 1712 | ERROR4: |
1287 | sysfs_remove_group(&dev->kobj, &it87_group); | 1713 | it87_remove_files(dev); |
1288 | sysfs_remove_group(&dev->kobj, &it87_group_opt); | ||
1289 | ERROR2: | 1714 | ERROR2: |
1290 | platform_set_drvdata(pdev, NULL); | 1715 | platform_set_drvdata(pdev, NULL); |
1291 | kfree(data); | 1716 | kfree(data); |
@@ -1300,8 +1725,7 @@ static int __devexit it87_remove(struct platform_device *pdev) | |||
1300 | struct it87_data *data = platform_get_drvdata(pdev); | 1725 | struct it87_data *data = platform_get_drvdata(pdev); |
1301 | 1726 | ||
1302 | hwmon_device_unregister(data->hwmon_dev); | 1727 | hwmon_device_unregister(data->hwmon_dev); |
1303 | sysfs_remove_group(&pdev->dev.kobj, &it87_group); | 1728 | it87_remove_files(&pdev->dev); |
1304 | sysfs_remove_group(&pdev->dev.kobj, &it87_group_opt); | ||
1305 | 1729 | ||
1306 | release_region(data->addr, IT87_EC_EXTENT); | 1730 | release_region(data->addr, IT87_EC_EXTENT); |
1307 | platform_set_drvdata(pdev, NULL); | 1731 | platform_set_drvdata(pdev, NULL); |
@@ -1387,15 +1811,18 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
1387 | int tmp, i; | 1811 | int tmp, i; |
1388 | u8 mask; | 1812 | u8 mask; |
1389 | 1813 | ||
1390 | /* initialize to sane defaults: | 1814 | /* For each PWM channel: |
1391 | * - if the chip is in manual pwm mode, this will be overwritten with | 1815 | * - If it is in automatic mode, setting to manual mode should set |
1392 | * the actual settings on the chip (so in this case, initialization | 1816 | * the fan to full speed by default. |
1393 | * is not needed) | 1817 | * - If it is in manual mode, we need a mapping to temperature |
1394 | * - if in automatic or on/off mode, we could switch to manual mode, | 1818 | * channels to use when later setting to automatic mode later. |
1395 | * read the registers and set manual_pwm_ctl accordingly, but currently | 1819 | * Use a 1:1 mapping by default (we are clueless.) |
1396 | * this is not implemented, so we initialize to something sane */ | 1820 | * In both cases, the value can (and should) be changed by the user |
1821 | * prior to switching to a different mode. */ | ||
1397 | for (i = 0; i < 3; i++) { | 1822 | for (i = 0; i < 3; i++) { |
1398 | data->manual_pwm_ctl[i] = 0xff; | 1823 | data->pwm_temp_map[i] = i; |
1824 | data->pwm_duty[i] = 0x7f; /* Full speed */ | ||
1825 | data->auto_pwm[i][3] = 0x7f; /* Full speed, hard-coded */ | ||
1399 | } | 1826 | } |
1400 | 1827 | ||
1401 | /* Some chips seem to have default value 0xff for all limit | 1828 | /* Some chips seem to have default value 0xff for all limit |
@@ -1436,7 +1863,8 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
1436 | if ((data->fan_main_ctrl & mask) == 0) { | 1863 | if ((data->fan_main_ctrl & mask) == 0) { |
1437 | /* Enable all fan tachometers */ | 1864 | /* Enable all fan tachometers */ |
1438 | data->fan_main_ctrl |= mask; | 1865 | data->fan_main_ctrl |= mask; |
1439 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 1866 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, |
1867 | data->fan_main_ctrl); | ||
1440 | } | 1868 | } |
1441 | data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; | 1869 | data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; |
1442 | 1870 | ||
@@ -1461,30 +1889,32 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
1461 | /* Fan input pins may be used for alternative functions */ | 1889 | /* Fan input pins may be used for alternative functions */ |
1462 | data->has_fan &= ~sio_data->skip_fan; | 1890 | data->has_fan &= ~sio_data->skip_fan; |
1463 | 1891 | ||
1464 | /* Set current fan mode registers and the default settings for the | ||
1465 | * other mode registers */ | ||
1466 | for (i = 0; i < 3; i++) { | ||
1467 | if (data->fan_main_ctrl & (1 << i)) { | ||
1468 | /* pwm mode */ | ||
1469 | tmp = it87_read_value(data, IT87_REG_PWM(i)); | ||
1470 | if (tmp & 0x80) { | ||
1471 | /* automatic pwm - not yet implemented, but | ||
1472 | * leave the settings made by the BIOS alone | ||
1473 | * until a change is requested via the sysfs | ||
1474 | * interface */ | ||
1475 | } else { | ||
1476 | /* manual pwm */ | ||
1477 | data->manual_pwm_ctl[i] = PWM_FROM_REG(tmp); | ||
1478 | } | ||
1479 | } | ||
1480 | } | ||
1481 | |||
1482 | /* Start monitoring */ | 1892 | /* Start monitoring */ |
1483 | it87_write_value(data, IT87_REG_CONFIG, | 1893 | it87_write_value(data, IT87_REG_CONFIG, |
1484 | (it87_read_value(data, IT87_REG_CONFIG) & 0x36) | 1894 | (it87_read_value(data, IT87_REG_CONFIG) & 0x36) |
1485 | | (update_vbat ? 0x41 : 0x01)); | 1895 | | (update_vbat ? 0x41 : 0x01)); |
1486 | } | 1896 | } |
1487 | 1897 | ||
1898 | static void it87_update_pwm_ctrl(struct it87_data *data, int nr) | ||
1899 | { | ||
1900 | data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr)); | ||
1901 | if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ | ||
1902 | data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; | ||
1903 | else /* Manual mode */ | ||
1904 | data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f; | ||
1905 | |||
1906 | if (has_old_autopwm(data)) { | ||
1907 | int i; | ||
1908 | |||
1909 | for (i = 0; i < 5 ; i++) | ||
1910 | data->auto_temp[nr][i] = it87_read_value(data, | ||
1911 | IT87_REG_AUTO_TEMP(nr, i)); | ||
1912 | for (i = 0; i < 3 ; i++) | ||
1913 | data->auto_pwm[nr][i] = it87_read_value(data, | ||
1914 | IT87_REG_AUTO_PWM(nr, i)); | ||
1915 | } | ||
1916 | } | ||
1917 | |||
1488 | static struct it87_data *it87_update_device(struct device *dev) | 1918 | static struct it87_data *it87_update_device(struct device *dev) |
1489 | { | 1919 | { |
1490 | struct it87_data *data = dev_get_drvdata(dev); | 1920 | struct it87_data *data = dev_get_drvdata(dev); |
@@ -1494,24 +1924,22 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1494 | 1924 | ||
1495 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 1925 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) |
1496 | || !data->valid) { | 1926 | || !data->valid) { |
1497 | |||
1498 | if (update_vbat) { | 1927 | if (update_vbat) { |
1499 | /* Cleared after each update, so reenable. Value | 1928 | /* Cleared after each update, so reenable. Value |
1500 | returned by this read will be previous value */ | 1929 | returned by this read will be previous value */ |
1501 | it87_write_value(data, IT87_REG_CONFIG, | 1930 | it87_write_value(data, IT87_REG_CONFIG, |
1502 | it87_read_value(data, IT87_REG_CONFIG) | 0x40); | 1931 | it87_read_value(data, IT87_REG_CONFIG) | 0x40); |
1503 | } | 1932 | } |
1504 | for (i = 0; i <= 7; i++) { | 1933 | for (i = 0; i <= 7; i++) { |
1505 | data->in[i] = | 1934 | data->in[i] = |
1506 | it87_read_value(data, IT87_REG_VIN(i)); | 1935 | it87_read_value(data, IT87_REG_VIN(i)); |
1507 | data->in_min[i] = | 1936 | data->in_min[i] = |
1508 | it87_read_value(data, IT87_REG_VIN_MIN(i)); | 1937 | it87_read_value(data, IT87_REG_VIN_MIN(i)); |
1509 | data->in_max[i] = | 1938 | data->in_max[i] = |
1510 | it87_read_value(data, IT87_REG_VIN_MAX(i)); | 1939 | it87_read_value(data, IT87_REG_VIN_MAX(i)); |
1511 | } | 1940 | } |
1512 | /* in8 (battery) has no limit registers */ | 1941 | /* in8 (battery) has no limit registers */ |
1513 | data->in[8] = | 1942 | data->in[8] = it87_read_value(data, IT87_REG_VIN(8)); |
1514 | it87_read_value(data, IT87_REG_VIN(8)); | ||
1515 | 1943 | ||
1516 | for (i = 0; i < 5; i++) { | 1944 | for (i = 0; i < 5; i++) { |
1517 | /* Skip disabled fans */ | 1945 | /* Skip disabled fans */ |
@@ -1519,7 +1947,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1519 | continue; | 1947 | continue; |
1520 | 1948 | ||
1521 | data->fan_min[i] = | 1949 | data->fan_min[i] = |
1522 | it87_read_value(data, IT87_REG_FAN_MIN[i]); | 1950 | it87_read_value(data, IT87_REG_FAN_MIN[i]); |
1523 | data->fan[i] = it87_read_value(data, | 1951 | data->fan[i] = it87_read_value(data, |
1524 | IT87_REG_FAN[i]); | 1952 | IT87_REG_FAN[i]); |
1525 | /* Add high byte if in 16-bit mode */ | 1953 | /* Add high byte if in 16-bit mode */ |
@@ -1532,11 +1960,11 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1532 | } | 1960 | } |
1533 | for (i = 0; i < 3; i++) { | 1961 | for (i = 0; i < 3; i++) { |
1534 | data->temp[i] = | 1962 | data->temp[i] = |
1535 | it87_read_value(data, IT87_REG_TEMP(i)); | 1963 | it87_read_value(data, IT87_REG_TEMP(i)); |
1536 | data->temp_high[i] = | 1964 | data->temp_high[i] = |
1537 | it87_read_value(data, IT87_REG_TEMP_HIGH(i)); | 1965 | it87_read_value(data, IT87_REG_TEMP_HIGH(i)); |
1538 | data->temp_low[i] = | 1966 | data->temp_low[i] = |
1539 | it87_read_value(data, IT87_REG_TEMP_LOW(i)); | 1967 | it87_read_value(data, IT87_REG_TEMP_LOW(i)); |
1540 | } | 1968 | } |
1541 | 1969 | ||
1542 | /* Newer chips don't have clock dividers */ | 1970 | /* Newer chips don't have clock dividers */ |
@@ -1551,9 +1979,13 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1551 | it87_read_value(data, IT87_REG_ALARM1) | | 1979 | it87_read_value(data, IT87_REG_ALARM1) | |
1552 | (it87_read_value(data, IT87_REG_ALARM2) << 8) | | 1980 | (it87_read_value(data, IT87_REG_ALARM2) << 8) | |
1553 | (it87_read_value(data, IT87_REG_ALARM3) << 16); | 1981 | (it87_read_value(data, IT87_REG_ALARM3) << 16); |
1982 | data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); | ||
1983 | |||
1554 | data->fan_main_ctrl = it87_read_value(data, | 1984 | data->fan_main_ctrl = it87_read_value(data, |
1555 | IT87_REG_FAN_MAIN_CTRL); | 1985 | IT87_REG_FAN_MAIN_CTRL); |
1556 | data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); | 1986 | data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); |
1987 | for (i = 0; i < 3; i++) | ||
1988 | it87_update_pwm_ctrl(data, i); | ||
1557 | 1989 | ||
1558 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 1990 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
1559 | /* The 8705 does not have VID capability. | 1991 | /* The 8705 does not have VID capability. |
@@ -1628,7 +2060,7 @@ exit: | |||
1628 | static int __init sm_it87_init(void) | 2060 | static int __init sm_it87_init(void) |
1629 | { | 2061 | { |
1630 | int err; | 2062 | int err; |
1631 | unsigned short isa_address=0; | 2063 | unsigned short isa_address = 0; |
1632 | struct it87_sio_data sio_data; | 2064 | struct it87_sio_data sio_data; |
1633 | 2065 | ||
1634 | memset(&sio_data, 0, sizeof(struct it87_sio_data)); | 2066 | memset(&sio_data, 0, sizeof(struct it87_sio_data)); |
@@ -1640,7 +2072,7 @@ static int __init sm_it87_init(void) | |||
1640 | return err; | 2072 | return err; |
1641 | 2073 | ||
1642 | err = it87_device_add(isa_address, &sio_data); | 2074 | err = it87_device_add(isa_address, &sio_data); |
1643 | if (err){ | 2075 | if (err) { |
1644 | platform_driver_unregister(&it87_driver); | 2076 | platform_driver_unregister(&it87_driver); |
1645 | return err; | 2077 | return err; |
1646 | } | 2078 | } |
@@ -1661,7 +2093,8 @@ MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8720F/8726F, SiS950 driver"); | |||
1661 | module_param(update_vbat, bool, 0); | 2093 | module_param(update_vbat, bool, 0); |
1662 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); | 2094 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); |
1663 | module_param(fix_pwm_polarity, bool, 0); | 2095 | module_param(fix_pwm_polarity, bool, 0); |
1664 | MODULE_PARM_DESC(fix_pwm_polarity, "Force PWM polarity to active high (DANGEROUS)"); | 2096 | MODULE_PARM_DESC(fix_pwm_polarity, |
2097 | "Force PWM polarity to active high (DANGEROUS)"); | ||
1665 | MODULE_LICENSE("GPL"); | 2098 | MODULE_LICENSE("GPL"); |
1666 | 2099 | ||
1667 | module_init(sm_it87_init); | 2100 | module_init(sm_it87_init); |