diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/hwmon/it87.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/hwmon/it87.c')
-rw-r--r-- | drivers/hwmon/it87.c | 1012 |
1 files changed, 738 insertions, 274 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index a3749cb0f181..5be09c048c5f 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> |
@@ -124,8 +124,11 @@ superio_exit(void) | |||
124 | #define IT87_BASE_REG 0x60 | 124 | #define IT87_BASE_REG 0x60 |
125 | 125 | ||
126 | /* Logical device 7 registers (IT8712F and later) */ | 126 | /* Logical device 7 registers (IT8712F and later) */ |
127 | #define IT87_SIO_GPIO3_REG 0x27 | ||
128 | #define IT87_SIO_GPIO5_REG 0x29 | ||
127 | #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ | 129 | #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ |
128 | #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 */ | ||
129 | 132 | ||
130 | /* Update battery voltage after every reading if true */ | 133 | /* Update battery voltage after every reading if true */ |
131 | static int update_vbat; | 134 | static int update_vbat; |
@@ -185,9 +188,13 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; | |||
185 | 188 | ||
186 | #define IT87_REG_VIN_ENABLE 0x50 | 189 | #define IT87_REG_VIN_ENABLE 0x50 |
187 | #define IT87_REG_TEMP_ENABLE 0x51 | 190 | #define IT87_REG_TEMP_ENABLE 0x51 |
191 | #define IT87_REG_BEEP_ENABLE 0x5c | ||
188 | 192 | ||
189 | #define IT87_REG_CHIPID 0x58 | 193 | #define IT87_REG_CHIPID 0x58 |
190 | 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 | |||
191 | #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)) |
192 | #define IN_FROM_REG(val) ((val) * 16) | 199 | #define IN_FROM_REG(val) ((val) * 16) |
193 | 200 | ||
@@ -244,7 +251,10 @@ struct it87_sio_data { | |||
244 | /* Values read from Super-I/O config space */ | 251 | /* Values read from Super-I/O config space */ |
245 | u8 revision; | 252 | u8 revision; |
246 | u8 vid_value; | 253 | u8 vid_value; |
247 | /* Values set based on DMI strings */ | 254 | u8 beep_pin; |
255 | /* Features skipped based on config or DMI */ | ||
256 | u8 skip_vid; | ||
257 | u8 skip_fan; | ||
248 | u8 skip_pwm; | 258 | u8 skip_pwm; |
249 | }; | 259 | }; |
250 | 260 | ||
@@ -275,9 +285,21 @@ struct it87_data { | |||
275 | u8 vid; /* Register encoding, combined */ | 285 | u8 vid; /* Register encoding, combined */ |
276 | u8 vrm; | 286 | u8 vrm; |
277 | u32 alarms; /* Register encoding, combined */ | 287 | u32 alarms; /* Register encoding, combined */ |
288 | u8 beeps; /* Register encoding */ | ||
278 | u8 fan_main_ctrl; /* Register value */ | 289 | u8 fan_main_ctrl; /* Register value */ |
279 | u8 fan_ctl; /* Register value */ | 290 | u8 fan_ctl; /* Register value */ |
280 | 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 */ | ||
281 | }; | 303 | }; |
282 | 304 | ||
283 | static inline int has_16bit_fans(const struct it87_data *data) | 305 | static inline int has_16bit_fans(const struct it87_data *data) |
@@ -292,6 +314,15 @@ static inline int has_16bit_fans(const struct it87_data *data) | |||
292 | || data->type == it8720; | 314 | || data->type == it8720; |
293 | } | 315 | } |
294 | 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 | |||
295 | static int it87_probe(struct platform_device *pdev); | 326 | static int it87_probe(struct platform_device *pdev); |
296 | static int __devexit it87_remove(struct platform_device *pdev); | 327 | static int __devexit it87_remove(struct platform_device *pdev); |
297 | 328 | ||
@@ -348,7 +379,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, | |||
348 | int nr = sensor_attr->index; | 379 | int nr = sensor_attr->index; |
349 | 380 | ||
350 | struct it87_data *data = dev_get_drvdata(dev); | 381 | struct it87_data *data = dev_get_drvdata(dev); |
351 | unsigned long val = simple_strtoul(buf, NULL, 10); | 382 | unsigned long val; |
383 | |||
384 | if (strict_strtoul(buf, 10, &val) < 0) | ||
385 | return -EINVAL; | ||
352 | 386 | ||
353 | mutex_lock(&data->update_lock); | 387 | mutex_lock(&data->update_lock); |
354 | data->in_min[nr] = IN_TO_REG(val); | 388 | data->in_min[nr] = IN_TO_REG(val); |
@@ -364,7 +398,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, | |||
364 | int nr = sensor_attr->index; | 398 | int nr = sensor_attr->index; |
365 | 399 | ||
366 | struct it87_data *data = dev_get_drvdata(dev); | 400 | struct it87_data *data = dev_get_drvdata(dev); |
367 | unsigned long val = simple_strtoul(buf, NULL, 10); | 401 | unsigned long val; |
402 | |||
403 | if (strict_strtoul(buf, 10, &val) < 0) | ||
404 | return -EINVAL; | ||
368 | 405 | ||
369 | mutex_lock(&data->update_lock); | 406 | mutex_lock(&data->update_lock); |
370 | data->in_max[nr] = IN_TO_REG(val); | 407 | data->in_max[nr] = IN_TO_REG(val); |
@@ -437,7 +474,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, | |||
437 | int nr = sensor_attr->index; | 474 | int nr = sensor_attr->index; |
438 | 475 | ||
439 | struct it87_data *data = dev_get_drvdata(dev); | 476 | struct it87_data *data = dev_get_drvdata(dev); |
440 | int val = simple_strtol(buf, NULL, 10); | 477 | long val; |
478 | |||
479 | if (strict_strtol(buf, 10, &val) < 0) | ||
480 | return -EINVAL; | ||
441 | 481 | ||
442 | mutex_lock(&data->update_lock); | 482 | mutex_lock(&data->update_lock); |
443 | data->temp_high[nr] = TEMP_TO_REG(val); | 483 | data->temp_high[nr] = TEMP_TO_REG(val); |
@@ -452,7 +492,10 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, | |||
452 | int nr = sensor_attr->index; | 492 | int nr = sensor_attr->index; |
453 | 493 | ||
454 | struct it87_data *data = dev_get_drvdata(dev); | 494 | struct it87_data *data = dev_get_drvdata(dev); |
455 | int val = simple_strtol(buf, NULL, 10); | 495 | long val; |
496 | |||
497 | if (strict_strtol(buf, 10, &val) < 0) | ||
498 | return -EINVAL; | ||
456 | 499 | ||
457 | mutex_lock(&data->update_lock); | 500 | mutex_lock(&data->update_lock); |
458 | data->temp_low[nr] = TEMP_TO_REG(val); | 501 | data->temp_low[nr] = TEMP_TO_REG(val); |
@@ -479,8 +522,9 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *attr, | |||
479 | int nr = sensor_attr->index; | 522 | int nr = sensor_attr->index; |
480 | 523 | ||
481 | struct it87_data *data = it87_update_device(dev); | 524 | struct it87_data *data = it87_update_device(dev); |
482 | 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 |
483 | 526 | we use it */ | |
527 | |||
484 | if (reg & (1 << nr)) | 528 | if (reg & (1 << nr)) |
485 | return sprintf(buf, "3\n"); /* thermal diode */ | 529 | return sprintf(buf, "3\n"); /* thermal diode */ |
486 | if (reg & (8 << nr)) | 530 | if (reg & (8 << nr)) |
@@ -494,12 +538,15 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, | |||
494 | int nr = sensor_attr->index; | 538 | int nr = sensor_attr->index; |
495 | 539 | ||
496 | struct it87_data *data = dev_get_drvdata(dev); | 540 | struct it87_data *data = dev_get_drvdata(dev); |
497 | int val = simple_strtol(buf, NULL, 10); | 541 | long val; |
542 | u8 reg; | ||
498 | 543 | ||
499 | mutex_lock(&data->update_lock); | 544 | if (strict_strtol(buf, 10, &val) < 0) |
545 | return -EINVAL; | ||
500 | 546 | ||
501 | data->sensor &= ~(1 << nr); | 547 | reg = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
502 | data->sensor &= ~(8 << nr); | 548 | reg &= ~(1 << nr); |
549 | reg &= ~(8 << nr); | ||
503 | if (val == 2) { /* backwards compatibility */ | 550 | if (val == 2) { /* backwards compatibility */ |
504 | dev_warn(dev, "Sensor type 2 is deprecated, please use 4 " | 551 | dev_warn(dev, "Sensor type 2 is deprecated, please use 4 " |
505 | "instead\n"); | 552 | "instead\n"); |
@@ -507,14 +554,16 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, | |||
507 | } | 554 | } |
508 | /* 3 = thermal diode; 4 = thermistor; 0 = disabled */ | 555 | /* 3 = thermal diode; 4 = thermistor; 0 = disabled */ |
509 | if (val == 3) | 556 | if (val == 3) |
510 | data->sensor |= 1 << nr; | 557 | reg |= 1 << nr; |
511 | else if (val == 4) | 558 | else if (val == 4) |
512 | data->sensor |= 8 << nr; | 559 | reg |= 8 << nr; |
513 | else if (val != 0) { | 560 | else if (val != 0) |
514 | mutex_unlock(&data->update_lock); | ||
515 | return -EINVAL; | 561 | return -EINVAL; |
516 | } | 562 | |
563 | mutex_lock(&data->update_lock); | ||
564 | data->sensor = reg; | ||
517 | it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); | 565 | it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); |
566 | data->valid = 0; /* Force cache refresh */ | ||
518 | mutex_unlock(&data->update_lock); | 567 | mutex_unlock(&data->update_lock); |
519 | return count; | 568 | return count; |
520 | } | 569 | } |
@@ -527,6 +576,19 @@ show_sensor_offset(2); | |||
527 | show_sensor_offset(3); | 576 | show_sensor_offset(3); |
528 | 577 | ||
529 | /* 3 Fans */ | 578 | /* 3 Fans */ |
579 | |||
580 | static int pwm_mode(const struct it87_data *data, int nr) | ||
581 | { | ||
582 | int ctrl = data->fan_main_ctrl & (1 << nr); | ||
583 | |||
584 | if (ctrl == 0) /* Full speed */ | ||
585 | return 0; | ||
586 | if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ | ||
587 | return 2; | ||
588 | else /* Manual mode */ | ||
589 | return 1; | ||
590 | } | ||
591 | |||
530 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, | 592 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, |
531 | char *buf) | 593 | char *buf) |
532 | { | 594 | { |
@@ -534,7 +596,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, | |||
534 | int nr = sensor_attr->index; | 596 | int nr = sensor_attr->index; |
535 | 597 | ||
536 | struct it87_data *data = it87_update_device(dev); | 598 | struct it87_data *data = it87_update_device(dev); |
537 | return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], | 599 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], |
538 | DIV_FROM_REG(data->fan_div[nr]))); | 600 | DIV_FROM_REG(data->fan_div[nr]))); |
539 | } | 601 | } |
540 | static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, | 602 | static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, |
@@ -544,8 +606,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, | |||
544 | int nr = sensor_attr->index; | 606 | int nr = sensor_attr->index; |
545 | 607 | ||
546 | struct it87_data *data = it87_update_device(dev); | 608 | struct it87_data *data = it87_update_device(dev); |
547 | return sprintf(buf,"%d\n", | 609 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], |
548 | FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]))); | 610 | DIV_FROM_REG(data->fan_div[nr]))); |
549 | } | 611 | } |
550 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, | 612 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, |
551 | char *buf) | 613 | char *buf) |
@@ -556,14 +618,14 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, | |||
556 | struct it87_data *data = it87_update_device(dev); | 618 | struct it87_data *data = it87_update_device(dev); |
557 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); | 619 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); |
558 | } | 620 | } |
559 | static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, | 621 | static ssize_t show_pwm_enable(struct device *dev, |
560 | char *buf) | 622 | struct device_attribute *attr, char *buf) |
561 | { | 623 | { |
562 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 624 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
563 | int nr = sensor_attr->index; | 625 | int nr = sensor_attr->index; |
564 | 626 | ||
565 | struct it87_data *data = it87_update_device(dev); | 627 | struct it87_data *data = it87_update_device(dev); |
566 | return sprintf(buf,"%d\n", (data->fan_main_ctrl & (1 << nr)) ? 1 : 0); | 628 | return sprintf(buf, "%d\n", pwm_mode(data, nr)); |
567 | } | 629 | } |
568 | static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | 630 | static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, |
569 | char *buf) | 631 | char *buf) |
@@ -572,7 +634,7 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | |||
572 | int nr = sensor_attr->index; | 634 | int nr = sensor_attr->index; |
573 | 635 | ||
574 | struct it87_data *data = it87_update_device(dev); | 636 | struct it87_data *data = it87_update_device(dev); |
575 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); | 637 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm_duty[nr])); |
576 | } | 638 | } |
577 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, | 639 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, |
578 | char *buf) | 640 | char *buf) |
@@ -589,15 +651,24 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | |||
589 | int nr = sensor_attr->index; | 651 | int nr = sensor_attr->index; |
590 | 652 | ||
591 | struct it87_data *data = dev_get_drvdata(dev); | 653 | struct it87_data *data = dev_get_drvdata(dev); |
592 | int val = simple_strtol(buf, NULL, 10); | 654 | long val; |
593 | u8 reg; | 655 | u8 reg; |
594 | 656 | ||
657 | if (strict_strtol(buf, 10, &val) < 0) | ||
658 | return -EINVAL; | ||
659 | |||
595 | mutex_lock(&data->update_lock); | 660 | mutex_lock(&data->update_lock); |
596 | reg = it87_read_value(data, IT87_REG_FAN_DIV); | 661 | reg = it87_read_value(data, IT87_REG_FAN_DIV); |
597 | switch (nr) { | 662 | switch (nr) { |
598 | case 0: data->fan_div[nr] = reg & 0x07; break; | 663 | case 0: |
599 | case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; | 664 | data->fan_div[nr] = reg & 0x07; |
600 | case 2: data->fan_div[nr] = (reg & 0x40) ? 3 : 1; break; | 665 | break; |
666 | case 1: | ||
667 | data->fan_div[nr] = (reg >> 3) & 0x07; | ||
668 | break; | ||
669 | case 2: | ||
670 | data->fan_div[nr] = (reg & 0x40) ? 3 : 1; | ||
671 | break; | ||
601 | } | 672 | } |
602 | 673 | ||
603 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); | 674 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); |
@@ -612,10 +683,13 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | |||
612 | int nr = sensor_attr->index; | 683 | int nr = sensor_attr->index; |
613 | 684 | ||
614 | struct it87_data *data = dev_get_drvdata(dev); | 685 | struct it87_data *data = dev_get_drvdata(dev); |
615 | unsigned long val = simple_strtoul(buf, NULL, 10); | 686 | unsigned long val; |
616 | int min; | 687 | int min; |
617 | u8 old; | 688 | u8 old; |
618 | 689 | ||
690 | if (strict_strtoul(buf, 10, &val) < 0) | ||
691 | return -EINVAL; | ||
692 | |||
619 | mutex_lock(&data->update_lock); | 693 | mutex_lock(&data->update_lock); |
620 | old = it87_read_value(data, IT87_REG_FAN_DIV); | 694 | old = it87_read_value(data, IT87_REG_FAN_DIV); |
621 | 695 | ||
@@ -647,6 +721,32 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | |||
647 | mutex_unlock(&data->update_lock); | 721 | mutex_unlock(&data->update_lock); |
648 | return count; | 722 | return count; |
649 | } | 723 | } |
724 | |||
725 | /* Returns 0 if OK, -EINVAL otherwise */ | ||
726 | static int check_trip_points(struct device *dev, int nr) | ||
727 | { | ||
728 | const struct it87_data *data = dev_get_drvdata(dev); | ||
729 | int i, err = 0; | ||
730 | |||
731 | if (has_old_autopwm(data)) { | ||
732 | for (i = 0; i < 3; i++) { | ||
733 | if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1]) | ||
734 | err = -EINVAL; | ||
735 | } | ||
736 | for (i = 0; i < 2; i++) { | ||
737 | if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1]) | ||
738 | err = -EINVAL; | ||
739 | } | ||
740 | } | ||
741 | |||
742 | if (err) { | ||
743 | dev_err(dev, "Inconsistent trip points, not switching to " | ||
744 | "automatic mode\n"); | ||
745 | dev_err(dev, "Adjust the trip points and try again\n"); | ||
746 | } | ||
747 | return err; | ||
748 | } | ||
749 | |||
650 | static ssize_t set_pwm_enable(struct device *dev, | 750 | static ssize_t set_pwm_enable(struct device *dev, |
651 | struct device_attribute *attr, const char *buf, size_t count) | 751 | struct device_attribute *attr, const char *buf, size_t count) |
652 | { | 752 | { |
@@ -654,7 +754,16 @@ static ssize_t set_pwm_enable(struct device *dev, | |||
654 | int nr = sensor_attr->index; | 754 | int nr = sensor_attr->index; |
655 | 755 | ||
656 | struct it87_data *data = dev_get_drvdata(dev); | 756 | struct it87_data *data = dev_get_drvdata(dev); |
657 | int val = simple_strtol(buf, NULL, 10); | 757 | long val; |
758 | |||
759 | if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 2) | ||
760 | return -EINVAL; | ||
761 | |||
762 | /* Check trip points before switching to automatic mode */ | ||
763 | if (val == 2) { | ||
764 | if (check_trip_points(dev, nr) < 0) | ||
765 | return -EINVAL; | ||
766 | } | ||
658 | 767 | ||
659 | mutex_lock(&data->update_lock); | 768 | mutex_lock(&data->update_lock); |
660 | 769 | ||
@@ -665,16 +774,18 @@ static ssize_t set_pwm_enable(struct device *dev, | |||
665 | it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr)); | 774 | it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr)); |
666 | /* set on/off mode */ | 775 | /* set on/off mode */ |
667 | data->fan_main_ctrl &= ~(1 << nr); | 776 | data->fan_main_ctrl &= ~(1 << nr); |
668 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 777 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, |
669 | } else if (val == 1) { | 778 | data->fan_main_ctrl); |
779 | } else { | ||
780 | if (val == 1) /* Manual mode */ | ||
781 | data->pwm_ctrl[nr] = data->pwm_duty[nr]; | ||
782 | else /* Automatic mode */ | ||
783 | data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; | ||
784 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); | ||
670 | /* set SmartGuardian mode */ | 785 | /* set SmartGuardian mode */ |
671 | data->fan_main_ctrl |= (1 << nr); | 786 | data->fan_main_ctrl |= (1 << nr); |
672 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 787 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, |
673 | /* set saved pwm value, clear FAN_CTLX PWM mode bit */ | 788 | data->fan_main_ctrl); |
674 | it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); | ||
675 | } else { | ||
676 | mutex_unlock(&data->update_lock); | ||
677 | return -EINVAL; | ||
678 | } | 789 | } |
679 | 790 | ||
680 | mutex_unlock(&data->update_lock); | 791 | mutex_unlock(&data->update_lock); |
@@ -687,15 +798,19 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
687 | int nr = sensor_attr->index; | 798 | int nr = sensor_attr->index; |
688 | 799 | ||
689 | struct it87_data *data = dev_get_drvdata(dev); | 800 | struct it87_data *data = dev_get_drvdata(dev); |
690 | int val = simple_strtol(buf, NULL, 10); | 801 | long val; |
691 | 802 | ||
692 | if (val < 0 || val > 255) | 803 | if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 255) |
693 | return -EINVAL; | 804 | return -EINVAL; |
694 | 805 | ||
695 | mutex_lock(&data->update_lock); | 806 | mutex_lock(&data->update_lock); |
696 | data->manual_pwm_ctl[nr] = val; | 807 | data->pwm_duty[nr] = PWM_TO_REG(val); |
697 | if (data->fan_main_ctrl & (1 << nr)) | 808 | /* If we are in manual mode, write the duty cycle immediately; |
698 | it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); | 809 | * otherwise, just store it for later use. */ |
810 | if (!(data->pwm_ctrl[nr] & 0x80)) { | ||
811 | data->pwm_ctrl[nr] = data->pwm_duty[nr]; | ||
812 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); | ||
813 | } | ||
699 | mutex_unlock(&data->update_lock); | 814 | mutex_unlock(&data->update_lock); |
700 | return count; | 815 | return count; |
701 | } | 816 | } |
@@ -703,9 +818,12 @@ static ssize_t set_pwm_freq(struct device *dev, | |||
703 | struct device_attribute *attr, const char *buf, size_t count) | 818 | struct device_attribute *attr, const char *buf, size_t count) |
704 | { | 819 | { |
705 | struct it87_data *data = dev_get_drvdata(dev); | 820 | struct it87_data *data = dev_get_drvdata(dev); |
706 | unsigned long val = simple_strtoul(buf, NULL, 10); | 821 | unsigned long val; |
707 | int i; | 822 | int i; |
708 | 823 | ||
824 | if (strict_strtoul(buf, 10, &val) < 0) | ||
825 | return -EINVAL; | ||
826 | |||
709 | /* Search for the nearest available frequency */ | 827 | /* Search for the nearest available frequency */ |
710 | for (i = 0; i < 7; i++) { | 828 | for (i = 0; i < 7; i++) { |
711 | if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) | 829 | if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) |
@@ -720,6 +838,132 @@ static ssize_t set_pwm_freq(struct device *dev, | |||
720 | 838 | ||
721 | return count; | 839 | return count; |
722 | } | 840 | } |
841 | static ssize_t show_pwm_temp_map(struct device *dev, | ||
842 | struct device_attribute *attr, char *buf) | ||
843 | { | ||
844 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
845 | int nr = sensor_attr->index; | ||
846 | |||
847 | struct it87_data *data = it87_update_device(dev); | ||
848 | int map; | ||
849 | |||
850 | if (data->pwm_temp_map[nr] < 3) | ||
851 | map = 1 << data->pwm_temp_map[nr]; | ||
852 | else | ||
853 | map = 0; /* Should never happen */ | ||
854 | return sprintf(buf, "%d\n", map); | ||
855 | } | ||
856 | static ssize_t set_pwm_temp_map(struct device *dev, | ||
857 | struct device_attribute *attr, const char *buf, size_t count) | ||
858 | { | ||
859 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
860 | int nr = sensor_attr->index; | ||
861 | |||
862 | struct it87_data *data = dev_get_drvdata(dev); | ||
863 | long val; | ||
864 | u8 reg; | ||
865 | |||
866 | /* This check can go away if we ever support automatic fan speed | ||
867 | control on newer chips. */ | ||
868 | if (!has_old_autopwm(data)) { | ||
869 | dev_notice(dev, "Mapping change disabled for safety reasons\n"); | ||
870 | return -EINVAL; | ||
871 | } | ||
872 | |||
873 | if (strict_strtol(buf, 10, &val) < 0) | ||
874 | return -EINVAL; | ||
875 | |||
876 | switch (val) { | ||
877 | case (1 << 0): | ||
878 | reg = 0x00; | ||
879 | break; | ||
880 | case (1 << 1): | ||
881 | reg = 0x01; | ||
882 | break; | ||
883 | case (1 << 2): | ||
884 | reg = 0x02; | ||
885 | break; | ||
886 | default: | ||
887 | return -EINVAL; | ||
888 | } | ||
889 | |||
890 | mutex_lock(&data->update_lock); | ||
891 | data->pwm_temp_map[nr] = reg; | ||
892 | /* If we are in automatic mode, write the temp mapping immediately; | ||
893 | * otherwise, just store it for later use. */ | ||
894 | if (data->pwm_ctrl[nr] & 0x80) { | ||
895 | data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; | ||
896 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); | ||
897 | } | ||
898 | mutex_unlock(&data->update_lock); | ||
899 | return count; | ||
900 | } | ||
901 | |||
902 | static ssize_t show_auto_pwm(struct device *dev, | ||
903 | struct device_attribute *attr, char *buf) | ||
904 | { | ||
905 | struct it87_data *data = it87_update_device(dev); | ||
906 | struct sensor_device_attribute_2 *sensor_attr = | ||
907 | to_sensor_dev_attr_2(attr); | ||
908 | int nr = sensor_attr->nr; | ||
909 | int point = sensor_attr->index; | ||
910 | |||
911 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->auto_pwm[nr][point])); | ||
912 | } | ||
913 | |||
914 | static ssize_t set_auto_pwm(struct device *dev, | ||
915 | struct device_attribute *attr, const char *buf, size_t count) | ||
916 | { | ||
917 | struct it87_data *data = dev_get_drvdata(dev); | ||
918 | struct sensor_device_attribute_2 *sensor_attr = | ||
919 | to_sensor_dev_attr_2(attr); | ||
920 | int nr = sensor_attr->nr; | ||
921 | int point = sensor_attr->index; | ||
922 | long val; | ||
923 | |||
924 | if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 255) | ||
925 | return -EINVAL; | ||
926 | |||
927 | mutex_lock(&data->update_lock); | ||
928 | data->auto_pwm[nr][point] = PWM_TO_REG(val); | ||
929 | it87_write_value(data, IT87_REG_AUTO_PWM(nr, point), | ||
930 | data->auto_pwm[nr][point]); | ||
931 | mutex_unlock(&data->update_lock); | ||
932 | return count; | ||
933 | } | ||
934 | |||
935 | static ssize_t show_auto_temp(struct device *dev, | ||
936 | struct device_attribute *attr, char *buf) | ||
937 | { | ||
938 | struct it87_data *data = it87_update_device(dev); | ||
939 | struct sensor_device_attribute_2 *sensor_attr = | ||
940 | to_sensor_dev_attr_2(attr); | ||
941 | int nr = sensor_attr->nr; | ||
942 | int point = sensor_attr->index; | ||
943 | |||
944 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->auto_temp[nr][point])); | ||
945 | } | ||
946 | |||
947 | static ssize_t set_auto_temp(struct device *dev, | ||
948 | struct device_attribute *attr, const char *buf, size_t count) | ||
949 | { | ||
950 | struct it87_data *data = dev_get_drvdata(dev); | ||
951 | struct sensor_device_attribute_2 *sensor_attr = | ||
952 | to_sensor_dev_attr_2(attr); | ||
953 | int nr = sensor_attr->nr; | ||
954 | int point = sensor_attr->index; | ||
955 | long val; | ||
956 | |||
957 | if (strict_strtol(buf, 10, &val) < 0 || val < -128000 || val > 127000) | ||
958 | return -EINVAL; | ||
959 | |||
960 | mutex_lock(&data->update_lock); | ||
961 | data->auto_temp[nr][point] = TEMP_TO_REG(val); | ||
962 | it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point), | ||
963 | data->auto_temp[nr][point]); | ||
964 | mutex_unlock(&data->update_lock); | ||
965 | return count; | ||
966 | } | ||
723 | 967 | ||
724 | #define show_fan_offset(offset) \ | 968 | #define show_fan_offset(offset) \ |
725 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ | 969 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ |
@@ -740,7 +984,36 @@ static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | |||
740 | show_pwm, set_pwm, offset - 1); \ | 984 | show_pwm, set_pwm, offset - 1); \ |
741 | static DEVICE_ATTR(pwm##offset##_freq, \ | 985 | static DEVICE_ATTR(pwm##offset##_freq, \ |
742 | (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ | 986 | (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ |
743 | show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); | 987 | show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); \ |
988 | static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels_temp, \ | ||
989 | S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, \ | ||
990 | offset - 1); \ | ||
991 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_pwm, \ | ||
992 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | ||
993 | offset - 1, 0); \ | ||
994 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_pwm, \ | ||
995 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | ||
996 | offset - 1, 1); \ | ||
997 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_pwm, \ | ||
998 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | ||
999 | offset - 1, 2); \ | ||
1000 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_pwm, \ | ||
1001 | S_IRUGO, show_auto_pwm, NULL, offset - 1, 3); \ | ||
1002 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp, \ | ||
1003 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
1004 | offset - 1, 1); \ | ||
1005 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp_hyst, \ | ||
1006 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
1007 | offset - 1, 0); \ | ||
1008 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_temp, \ | ||
1009 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
1010 | offset - 1, 2); \ | ||
1011 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_temp, \ | ||
1012 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
1013 | offset - 1, 3); \ | ||
1014 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_temp, \ | ||
1015 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
1016 | offset - 1, 4); | ||
744 | 1017 | ||
745 | show_pwm_offset(1); | 1018 | show_pwm_offset(1); |
746 | show_pwm_offset(2); | 1019 | show_pwm_offset(2); |
@@ -771,7 +1044,10 @@ static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr, | |||
771 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 1044 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
772 | int nr = sensor_attr->index; | 1045 | int nr = sensor_attr->index; |
773 | struct it87_data *data = dev_get_drvdata(dev); | 1046 | struct it87_data *data = dev_get_drvdata(dev); |
774 | int val = simple_strtol(buf, NULL, 10); | 1047 | long val; |
1048 | |||
1049 | if (strict_strtol(buf, 10, &val) < 0) | ||
1050 | return -EINVAL; | ||
775 | 1051 | ||
776 | mutex_lock(&data->update_lock); | 1052 | mutex_lock(&data->update_lock); |
777 | data->fan_min[nr] = FAN16_TO_REG(val); | 1053 | data->fan_min[nr] = FAN16_TO_REG(val); |
@@ -801,7 +1077,8 @@ show_fan16_offset(4); | |||
801 | show_fan16_offset(5); | 1077 | show_fan16_offset(5); |
802 | 1078 | ||
803 | /* Alarms */ | 1079 | /* Alarms */ |
804 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 1080 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, |
1081 | char *buf) | ||
805 | { | 1082 | { |
806 | struct it87_data *data = it87_update_device(dev); | 1083 | struct it87_data *data = it87_update_device(dev); |
807 | return sprintf(buf, "%u\n", data->alarms); | 1084 | return sprintf(buf, "%u\n", data->alarms); |
@@ -832,27 +1109,78 @@ static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16); | |||
832 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17); | 1109 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17); |
833 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18); | 1110 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18); |
834 | 1111 | ||
835 | static ssize_t | 1112 | static ssize_t show_beep(struct device *dev, struct device_attribute *attr, |
836 | show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) | 1113 | char *buf) |
1114 | { | ||
1115 | int bitnr = to_sensor_dev_attr(attr)->index; | ||
1116 | struct it87_data *data = it87_update_device(dev); | ||
1117 | return sprintf(buf, "%u\n", (data->beeps >> bitnr) & 1); | ||
1118 | } | ||
1119 | static ssize_t set_beep(struct device *dev, struct device_attribute *attr, | ||
1120 | const char *buf, size_t count) | ||
1121 | { | ||
1122 | int bitnr = to_sensor_dev_attr(attr)->index; | ||
1123 | struct it87_data *data = dev_get_drvdata(dev); | ||
1124 | long val; | ||
1125 | |||
1126 | if (strict_strtol(buf, 10, &val) < 0 | ||
1127 | || (val != 0 && val != 1)) | ||
1128 | return -EINVAL; | ||
1129 | |||
1130 | mutex_lock(&data->update_lock); | ||
1131 | data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); | ||
1132 | if (val) | ||
1133 | data->beeps |= (1 << bitnr); | ||
1134 | else | ||
1135 | data->beeps &= ~(1 << bitnr); | ||
1136 | it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps); | ||
1137 | mutex_unlock(&data->update_lock); | ||
1138 | return count; | ||
1139 | } | ||
1140 | |||
1141 | static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, | ||
1142 | show_beep, set_beep, 1); | ||
1143 | static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO, show_beep, NULL, 1); | ||
1144 | static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO, show_beep, NULL, 1); | ||
1145 | static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO, show_beep, NULL, 1); | ||
1146 | static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO, show_beep, NULL, 1); | ||
1147 | static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO, show_beep, NULL, 1); | ||
1148 | static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO, show_beep, NULL, 1); | ||
1149 | static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO, show_beep, NULL, 1); | ||
1150 | /* fanX_beep writability is set later */ | ||
1151 | static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO, show_beep, set_beep, 0); | ||
1152 | static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO, show_beep, set_beep, 0); | ||
1153 | static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO, show_beep, set_beep, 0); | ||
1154 | static SENSOR_DEVICE_ATTR(fan4_beep, S_IRUGO, show_beep, set_beep, 0); | ||
1155 | static SENSOR_DEVICE_ATTR(fan5_beep, S_IRUGO, show_beep, set_beep, 0); | ||
1156 | static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, | ||
1157 | show_beep, set_beep, 2); | ||
1158 | static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO, show_beep, NULL, 2); | ||
1159 | static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, show_beep, NULL, 2); | ||
1160 | |||
1161 | static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, | ||
1162 | char *buf) | ||
837 | { | 1163 | { |
838 | struct it87_data *data = dev_get_drvdata(dev); | 1164 | struct it87_data *data = dev_get_drvdata(dev); |
839 | return sprintf(buf, "%u\n", data->vrm); | 1165 | return sprintf(buf, "%u\n", data->vrm); |
840 | } | 1166 | } |
841 | static ssize_t | 1167 | static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, |
842 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1168 | const char *buf, size_t count) |
843 | { | 1169 | { |
844 | struct it87_data *data = dev_get_drvdata(dev); | 1170 | struct it87_data *data = dev_get_drvdata(dev); |
845 | u32 val; | 1171 | unsigned long val; |
1172 | |||
1173 | if (strict_strtoul(buf, 10, &val) < 0) | ||
1174 | return -EINVAL; | ||
846 | 1175 | ||
847 | val = simple_strtoul(buf, NULL, 10); | ||
848 | data->vrm = val; | 1176 | data->vrm = val; |
849 | 1177 | ||
850 | return count; | 1178 | return count; |
851 | } | 1179 | } |
852 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); | 1180 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); |
853 | 1181 | ||
854 | static ssize_t | 1182 | static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, |
855 | show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) | 1183 | char *buf) |
856 | { | 1184 | { |
857 | struct it87_data *data = it87_update_device(dev); | 1185 | struct it87_data *data = it87_update_device(dev); |
858 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); | 1186 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); |
@@ -927,51 +1255,176 @@ static const struct attribute_group it87_group = { | |||
927 | .attrs = it87_attributes, | 1255 | .attrs = it87_attributes, |
928 | }; | 1256 | }; |
929 | 1257 | ||
930 | static struct attribute *it87_attributes_opt[] = { | 1258 | static struct attribute *it87_attributes_beep[] = { |
1259 | &sensor_dev_attr_in0_beep.dev_attr.attr, | ||
1260 | &sensor_dev_attr_in1_beep.dev_attr.attr, | ||
1261 | &sensor_dev_attr_in2_beep.dev_attr.attr, | ||
1262 | &sensor_dev_attr_in3_beep.dev_attr.attr, | ||
1263 | &sensor_dev_attr_in4_beep.dev_attr.attr, | ||
1264 | &sensor_dev_attr_in5_beep.dev_attr.attr, | ||
1265 | &sensor_dev_attr_in6_beep.dev_attr.attr, | ||
1266 | &sensor_dev_attr_in7_beep.dev_attr.attr, | ||
1267 | |||
1268 | &sensor_dev_attr_temp1_beep.dev_attr.attr, | ||
1269 | &sensor_dev_attr_temp2_beep.dev_attr.attr, | ||
1270 | &sensor_dev_attr_temp3_beep.dev_attr.attr, | ||
1271 | NULL | ||
1272 | }; | ||
1273 | |||
1274 | static const struct attribute_group it87_group_beep = { | ||
1275 | .attrs = it87_attributes_beep, | ||
1276 | }; | ||
1277 | |||
1278 | static struct attribute *it87_attributes_fan16[5][3+1] = { { | ||
931 | &sensor_dev_attr_fan1_input16.dev_attr.attr, | 1279 | &sensor_dev_attr_fan1_input16.dev_attr.attr, |
932 | &sensor_dev_attr_fan1_min16.dev_attr.attr, | 1280 | &sensor_dev_attr_fan1_min16.dev_attr.attr, |
1281 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
1282 | NULL | ||
1283 | }, { | ||
933 | &sensor_dev_attr_fan2_input16.dev_attr.attr, | 1284 | &sensor_dev_attr_fan2_input16.dev_attr.attr, |
934 | &sensor_dev_attr_fan2_min16.dev_attr.attr, | 1285 | &sensor_dev_attr_fan2_min16.dev_attr.attr, |
1286 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
1287 | NULL | ||
1288 | }, { | ||
935 | &sensor_dev_attr_fan3_input16.dev_attr.attr, | 1289 | &sensor_dev_attr_fan3_input16.dev_attr.attr, |
936 | &sensor_dev_attr_fan3_min16.dev_attr.attr, | 1290 | &sensor_dev_attr_fan3_min16.dev_attr.attr, |
1291 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | ||
1292 | NULL | ||
1293 | }, { | ||
937 | &sensor_dev_attr_fan4_input16.dev_attr.attr, | 1294 | &sensor_dev_attr_fan4_input16.dev_attr.attr, |
938 | &sensor_dev_attr_fan4_min16.dev_attr.attr, | 1295 | &sensor_dev_attr_fan4_min16.dev_attr.attr, |
1296 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, | ||
1297 | NULL | ||
1298 | }, { | ||
939 | &sensor_dev_attr_fan5_input16.dev_attr.attr, | 1299 | &sensor_dev_attr_fan5_input16.dev_attr.attr, |
940 | &sensor_dev_attr_fan5_min16.dev_attr.attr, | 1300 | &sensor_dev_attr_fan5_min16.dev_attr.attr, |
1301 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, | ||
1302 | NULL | ||
1303 | } }; | ||
1304 | |||
1305 | static const struct attribute_group it87_group_fan16[5] = { | ||
1306 | { .attrs = it87_attributes_fan16[0] }, | ||
1307 | { .attrs = it87_attributes_fan16[1] }, | ||
1308 | { .attrs = it87_attributes_fan16[2] }, | ||
1309 | { .attrs = it87_attributes_fan16[3] }, | ||
1310 | { .attrs = it87_attributes_fan16[4] }, | ||
1311 | }; | ||
941 | 1312 | ||
1313 | static struct attribute *it87_attributes_fan[3][4+1] = { { | ||
942 | &sensor_dev_attr_fan1_input.dev_attr.attr, | 1314 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
943 | &sensor_dev_attr_fan1_min.dev_attr.attr, | 1315 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
944 | &sensor_dev_attr_fan1_div.dev_attr.attr, | 1316 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
1317 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
1318 | NULL | ||
1319 | }, { | ||
945 | &sensor_dev_attr_fan2_input.dev_attr.attr, | 1320 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
946 | &sensor_dev_attr_fan2_min.dev_attr.attr, | 1321 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
947 | &sensor_dev_attr_fan2_div.dev_attr.attr, | 1322 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
1323 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
1324 | NULL | ||
1325 | }, { | ||
948 | &sensor_dev_attr_fan3_input.dev_attr.attr, | 1326 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
949 | &sensor_dev_attr_fan3_min.dev_attr.attr, | 1327 | &sensor_dev_attr_fan3_min.dev_attr.attr, |
950 | &sensor_dev_attr_fan3_div.dev_attr.attr, | 1328 | &sensor_dev_attr_fan3_div.dev_attr.attr, |
951 | |||
952 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
953 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
954 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | 1329 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, |
955 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, | 1330 | NULL |
956 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, | 1331 | } }; |
1332 | |||
1333 | static const struct attribute_group it87_group_fan[3] = { | ||
1334 | { .attrs = it87_attributes_fan[0] }, | ||
1335 | { .attrs = it87_attributes_fan[1] }, | ||
1336 | { .attrs = it87_attributes_fan[2] }, | ||
1337 | }; | ||
1338 | |||
1339 | static const struct attribute_group * | ||
1340 | it87_get_fan_group(const struct it87_data *data) | ||
1341 | { | ||
1342 | return has_16bit_fans(data) ? it87_group_fan16 : it87_group_fan; | ||
1343 | } | ||
957 | 1344 | ||
1345 | static struct attribute *it87_attributes_pwm[3][4+1] = { { | ||
958 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | 1346 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, |
959 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
960 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
961 | &sensor_dev_attr_pwm1.dev_attr.attr, | 1347 | &sensor_dev_attr_pwm1.dev_attr.attr, |
962 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
963 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
964 | &dev_attr_pwm1_freq.attr, | 1348 | &dev_attr_pwm1_freq.attr, |
1349 | &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, | ||
1350 | NULL | ||
1351 | }, { | ||
1352 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
1353 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
965 | &dev_attr_pwm2_freq.attr, | 1354 | &dev_attr_pwm2_freq.attr, |
1355 | &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, | ||
1356 | NULL | ||
1357 | }, { | ||
1358 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
1359 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
966 | &dev_attr_pwm3_freq.attr, | 1360 | &dev_attr_pwm3_freq.attr, |
1361 | &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, | ||
1362 | NULL | ||
1363 | } }; | ||
1364 | |||
1365 | static const struct attribute_group it87_group_pwm[3] = { | ||
1366 | { .attrs = it87_attributes_pwm[0] }, | ||
1367 | { .attrs = it87_attributes_pwm[1] }, | ||
1368 | { .attrs = it87_attributes_pwm[2] }, | ||
1369 | }; | ||
1370 | |||
1371 | static struct attribute *it87_attributes_autopwm[3][9+1] = { { | ||
1372 | &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, | ||
1373 | &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, | ||
1374 | &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, | ||
1375 | &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr, | ||
1376 | &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, | ||
1377 | &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr, | ||
1378 | &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, | ||
1379 | &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, | ||
1380 | &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr, | ||
1381 | NULL | ||
1382 | }, { | ||
1383 | &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, | ||
1384 | &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, | ||
1385 | &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr, | ||
1386 | &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr, | ||
1387 | &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr, | ||
1388 | &sensor_dev_attr_pwm2_auto_point1_temp_hyst.dev_attr.attr, | ||
1389 | &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, | ||
1390 | &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr, | ||
1391 | &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr, | ||
1392 | NULL | ||
1393 | }, { | ||
1394 | &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, | ||
1395 | &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, | ||
1396 | &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr, | ||
1397 | &sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr, | ||
1398 | &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr, | ||
1399 | &sensor_dev_attr_pwm3_auto_point1_temp_hyst.dev_attr.attr, | ||
1400 | &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, | ||
1401 | &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr, | ||
1402 | &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr, | ||
1403 | NULL | ||
1404 | } }; | ||
1405 | |||
1406 | static const struct attribute_group it87_group_autopwm[3] = { | ||
1407 | { .attrs = it87_attributes_autopwm[0] }, | ||
1408 | { .attrs = it87_attributes_autopwm[1] }, | ||
1409 | { .attrs = it87_attributes_autopwm[2] }, | ||
1410 | }; | ||
1411 | |||
1412 | static struct attribute *it87_attributes_fan_beep[] = { | ||
1413 | &sensor_dev_attr_fan1_beep.dev_attr.attr, | ||
1414 | &sensor_dev_attr_fan2_beep.dev_attr.attr, | ||
1415 | &sensor_dev_attr_fan3_beep.dev_attr.attr, | ||
1416 | &sensor_dev_attr_fan4_beep.dev_attr.attr, | ||
1417 | &sensor_dev_attr_fan5_beep.dev_attr.attr, | ||
1418 | }; | ||
967 | 1419 | ||
1420 | static struct attribute *it87_attributes_vid[] = { | ||
968 | &dev_attr_vrm.attr, | 1421 | &dev_attr_vrm.attr, |
969 | &dev_attr_cpu0_vid.attr, | 1422 | &dev_attr_cpu0_vid.attr, |
970 | NULL | 1423 | NULL |
971 | }; | 1424 | }; |
972 | 1425 | ||
973 | static const struct attribute_group it87_group_opt = { | 1426 | static const struct attribute_group it87_group_vid = { |
974 | .attrs = it87_attributes_opt, | 1427 | .attrs = it87_attributes_vid, |
975 | }; | 1428 | }; |
976 | 1429 | ||
977 | /* SuperIO detection - will change isa_address if a chip is found */ | 1430 | /* SuperIO detection - will change isa_address if a chip is found */ |
@@ -1028,11 +1481,39 @@ static int __init it87_find(unsigned short *address, | |||
1028 | chip_type, *address, sio_data->revision); | 1481 | chip_type, *address, sio_data->revision); |
1029 | 1482 | ||
1030 | /* Read GPIO config and VID value from LDN 7 (GPIO) */ | 1483 | /* Read GPIO config and VID value from LDN 7 (GPIO) */ |
1031 | if (sio_data->type != it87) { | 1484 | if (sio_data->type == it87) { |
1485 | /* The IT8705F doesn't have VID pins at all */ | ||
1486 | sio_data->skip_vid = 1; | ||
1487 | |||
1488 | /* The IT8705F has a different LD number for GPIO */ | ||
1489 | superio_select(5); | ||
1490 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
1491 | } else { | ||
1032 | int reg; | 1492 | int reg; |
1033 | 1493 | ||
1034 | superio_select(GPIO); | 1494 | superio_select(GPIO); |
1035 | if (sio_data->type == it8718 || sio_data->type == it8720) | 1495 | /* We need at least 4 VID pins */ |
1496 | reg = superio_inb(IT87_SIO_GPIO3_REG); | ||
1497 | if (reg & 0x0f) { | ||
1498 | pr_info("it87: VID is disabled (pins used for GPIO)\n"); | ||
1499 | sio_data->skip_vid = 1; | ||
1500 | } | ||
1501 | |||
1502 | /* Check if fan3 is there or not */ | ||
1503 | if (reg & (1 << 6)) | ||
1504 | sio_data->skip_pwm |= (1 << 2); | ||
1505 | if (reg & (1 << 7)) | ||
1506 | sio_data->skip_fan |= (1 << 2); | ||
1507 | |||
1508 | /* Check if fan2 is there or not */ | ||
1509 | reg = superio_inb(IT87_SIO_GPIO5_REG); | ||
1510 | if (reg & (1 << 1)) | ||
1511 | sio_data->skip_pwm |= (1 << 1); | ||
1512 | if (reg & (1 << 2)) | ||
1513 | sio_data->skip_fan |= (1 << 1); | ||
1514 | |||
1515 | if ((sio_data->type == it8718 || sio_data->type == it8720) | ||
1516 | && !(sio_data->skip_vid)) | ||
1036 | sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); | 1517 | sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); |
1037 | 1518 | ||
1038 | reg = superio_inb(IT87_SIO_PINX2_REG); | 1519 | reg = superio_inb(IT87_SIO_PINX2_REG); |
@@ -1040,7 +1521,11 @@ static int __init it87_find(unsigned short *address, | |||
1040 | pr_info("it87: in3 is VCC (+5V)\n"); | 1521 | pr_info("it87: in3 is VCC (+5V)\n"); |
1041 | if (reg & (1 << 1)) | 1522 | if (reg & (1 << 1)) |
1042 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); | 1523 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); |
1524 | |||
1525 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
1043 | } | 1526 | } |
1527 | if (sio_data->beep_pin) | ||
1528 | pr_info("it87: Beeping is supported\n"); | ||
1044 | 1529 | ||
1045 | /* Disable specific features based on DMI strings */ | 1530 | /* Disable specific features based on DMI strings */ |
1046 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | 1531 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); |
@@ -1065,14 +1550,46 @@ exit: | |||
1065 | return err; | 1550 | return err; |
1066 | } | 1551 | } |
1067 | 1552 | ||
1553 | static void it87_remove_files(struct device *dev) | ||
1554 | { | ||
1555 | struct it87_data *data = platform_get_drvdata(pdev); | ||
1556 | struct it87_sio_data *sio_data = dev->platform_data; | ||
1557 | const struct attribute_group *fan_group = it87_get_fan_group(data); | ||
1558 | int i; | ||
1559 | |||
1560 | sysfs_remove_group(&dev->kobj, &it87_group); | ||
1561 | if (sio_data->beep_pin) | ||
1562 | sysfs_remove_group(&dev->kobj, &it87_group_beep); | ||
1563 | for (i = 0; i < 5; i++) { | ||
1564 | if (!(data->has_fan & (1 << i))) | ||
1565 | continue; | ||
1566 | sysfs_remove_group(&dev->kobj, &fan_group[i]); | ||
1567 | if (sio_data->beep_pin) | ||
1568 | sysfs_remove_file(&dev->kobj, | ||
1569 | it87_attributes_fan_beep[i]); | ||
1570 | } | ||
1571 | for (i = 0; i < 3; i++) { | ||
1572 | if (sio_data->skip_pwm & (1 << 0)) | ||
1573 | continue; | ||
1574 | sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]); | ||
1575 | if (has_old_autopwm(data)) | ||
1576 | sysfs_remove_group(&dev->kobj, | ||
1577 | &it87_group_autopwm[i]); | ||
1578 | } | ||
1579 | if (!sio_data->skip_vid) | ||
1580 | sysfs_remove_group(&dev->kobj, &it87_group_vid); | ||
1581 | } | ||
1582 | |||
1068 | static int __devinit it87_probe(struct platform_device *pdev) | 1583 | static int __devinit it87_probe(struct platform_device *pdev) |
1069 | { | 1584 | { |
1070 | struct it87_data *data; | 1585 | struct it87_data *data; |
1071 | struct resource *res; | 1586 | struct resource *res; |
1072 | struct device *dev = &pdev->dev; | 1587 | struct device *dev = &pdev->dev; |
1073 | struct it87_sio_data *sio_data = dev->platform_data; | 1588 | struct it87_sio_data *sio_data = dev->platform_data; |
1074 | int err = 0; | 1589 | const struct attribute_group *fan_group; |
1590 | int err = 0, i; | ||
1075 | int enable_pwm_interface; | 1591 | int enable_pwm_interface; |
1592 | int fan_beep_need_rw; | ||
1076 | static const char *names[] = { | 1593 | static const char *names[] = { |
1077 | "it87", | 1594 | "it87", |
1078 | "it8712", | 1595 | "it8712", |
@@ -1090,7 +1607,8 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1090 | goto ERROR0; | 1607 | goto ERROR0; |
1091 | } | 1608 | } |
1092 | 1609 | ||
1093 | if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) { | 1610 | data = kzalloc(sizeof(struct it87_data), GFP_KERNEL); |
1611 | if (!data) { | ||
1094 | err = -ENOMEM; | 1612 | err = -ENOMEM; |
1095 | goto ERROR1; | 1613 | goto ERROR1; |
1096 | } | 1614 | } |
@@ -1118,133 +1636,70 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1118 | it87_init_device(pdev); | 1636 | it87_init_device(pdev); |
1119 | 1637 | ||
1120 | /* Register sysfs hooks */ | 1638 | /* Register sysfs hooks */ |
1121 | if ((err = sysfs_create_group(&dev->kobj, &it87_group))) | 1639 | err = sysfs_create_group(&dev->kobj, &it87_group); |
1640 | if (err) | ||
1122 | goto ERROR2; | 1641 | goto ERROR2; |
1123 | 1642 | ||
1643 | if (sio_data->beep_pin) { | ||
1644 | err = sysfs_create_group(&dev->kobj, &it87_group_beep); | ||
1645 | if (err) | ||
1646 | goto ERROR4; | ||
1647 | } | ||
1648 | |||
1124 | /* Do not create fan files for disabled fans */ | 1649 | /* Do not create fan files for disabled fans */ |
1125 | if (has_16bit_fans(data)) { | 1650 | fan_group = it87_get_fan_group(data); |
1126 | /* 16-bit tachometers */ | 1651 | fan_beep_need_rw = 1; |
1127 | if (data->has_fan & (1 << 0)) { | 1652 | for (i = 0; i < 5; i++) { |
1128 | if ((err = device_create_file(dev, | 1653 | if (!(data->has_fan & (1 << i))) |
1129 | &sensor_dev_attr_fan1_input16.dev_attr)) | 1654 | continue; |
1130 | || (err = device_create_file(dev, | 1655 | err = sysfs_create_group(&dev->kobj, &fan_group[i]); |
1131 | &sensor_dev_attr_fan1_min16.dev_attr)) | 1656 | if (err) |
1132 | || (err = device_create_file(dev, | 1657 | goto ERROR4; |
1133 | &sensor_dev_attr_fan1_alarm.dev_attr))) | 1658 | |
1134 | goto ERROR4; | 1659 | if (sio_data->beep_pin) { |
1135 | } | 1660 | err = sysfs_create_file(&dev->kobj, |
1136 | if (data->has_fan & (1 << 1)) { | 1661 | it87_attributes_fan_beep[i]); |
1137 | if ((err = device_create_file(dev, | 1662 | if (err) |
1138 | &sensor_dev_attr_fan2_input16.dev_attr)) | ||
1139 | || (err = device_create_file(dev, | ||
1140 | &sensor_dev_attr_fan2_min16.dev_attr)) | ||
1141 | || (err = device_create_file(dev, | ||
1142 | &sensor_dev_attr_fan2_alarm.dev_attr))) | ||
1143 | goto ERROR4; | ||
1144 | } | ||
1145 | if (data->has_fan & (1 << 2)) { | ||
1146 | if ((err = device_create_file(dev, | ||
1147 | &sensor_dev_attr_fan3_input16.dev_attr)) | ||
1148 | || (err = device_create_file(dev, | ||
1149 | &sensor_dev_attr_fan3_min16.dev_attr)) | ||
1150 | || (err = device_create_file(dev, | ||
1151 | &sensor_dev_attr_fan3_alarm.dev_attr))) | ||
1152 | goto ERROR4; | ||
1153 | } | ||
1154 | if (data->has_fan & (1 << 3)) { | ||
1155 | if ((err = device_create_file(dev, | ||
1156 | &sensor_dev_attr_fan4_input16.dev_attr)) | ||
1157 | || (err = device_create_file(dev, | ||
1158 | &sensor_dev_attr_fan4_min16.dev_attr)) | ||
1159 | || (err = device_create_file(dev, | ||
1160 | &sensor_dev_attr_fan4_alarm.dev_attr))) | ||
1161 | goto ERROR4; | ||
1162 | } | ||
1163 | if (data->has_fan & (1 << 4)) { | ||
1164 | if ((err = device_create_file(dev, | ||
1165 | &sensor_dev_attr_fan5_input16.dev_attr)) | ||
1166 | || (err = device_create_file(dev, | ||
1167 | &sensor_dev_attr_fan5_min16.dev_attr)) | ||
1168 | || (err = device_create_file(dev, | ||
1169 | &sensor_dev_attr_fan5_alarm.dev_attr))) | ||
1170 | goto ERROR4; | ||
1171 | } | ||
1172 | } else { | ||
1173 | /* 8-bit tachometers with clock divider */ | ||
1174 | if (data->has_fan & (1 << 0)) { | ||
1175 | if ((err = device_create_file(dev, | ||
1176 | &sensor_dev_attr_fan1_input.dev_attr)) | ||
1177 | || (err = device_create_file(dev, | ||
1178 | &sensor_dev_attr_fan1_min.dev_attr)) | ||
1179 | || (err = device_create_file(dev, | ||
1180 | &sensor_dev_attr_fan1_div.dev_attr)) | ||
1181 | || (err = device_create_file(dev, | ||
1182 | &sensor_dev_attr_fan1_alarm.dev_attr))) | ||
1183 | goto ERROR4; | ||
1184 | } | ||
1185 | if (data->has_fan & (1 << 1)) { | ||
1186 | if ((err = device_create_file(dev, | ||
1187 | &sensor_dev_attr_fan2_input.dev_attr)) | ||
1188 | || (err = device_create_file(dev, | ||
1189 | &sensor_dev_attr_fan2_min.dev_attr)) | ||
1190 | || (err = device_create_file(dev, | ||
1191 | &sensor_dev_attr_fan2_div.dev_attr)) | ||
1192 | || (err = device_create_file(dev, | ||
1193 | &sensor_dev_attr_fan2_alarm.dev_attr))) | ||
1194 | goto ERROR4; | ||
1195 | } | ||
1196 | if (data->has_fan & (1 << 2)) { | ||
1197 | if ((err = device_create_file(dev, | ||
1198 | &sensor_dev_attr_fan3_input.dev_attr)) | ||
1199 | || (err = device_create_file(dev, | ||
1200 | &sensor_dev_attr_fan3_min.dev_attr)) | ||
1201 | || (err = device_create_file(dev, | ||
1202 | &sensor_dev_attr_fan3_div.dev_attr)) | ||
1203 | || (err = device_create_file(dev, | ||
1204 | &sensor_dev_attr_fan3_alarm.dev_attr))) | ||
1205 | goto ERROR4; | 1663 | goto ERROR4; |
1664 | if (!fan_beep_need_rw) | ||
1665 | continue; | ||
1666 | |||
1667 | /* As we have a single beep enable bit for all fans, | ||
1668 | * only the first enabled fan has a writable attribute | ||
1669 | * for it. */ | ||
1670 | if (sysfs_chmod_file(&dev->kobj, | ||
1671 | it87_attributes_fan_beep[i], | ||
1672 | S_IRUGO | S_IWUSR)) | ||
1673 | dev_dbg(dev, "chmod +w fan%d_beep failed\n", | ||
1674 | i + 1); | ||
1675 | fan_beep_need_rw = 0; | ||
1206 | } | 1676 | } |
1207 | } | 1677 | } |
1208 | 1678 | ||
1209 | if (enable_pwm_interface) { | 1679 | if (enable_pwm_interface) { |
1210 | if (!(sio_data->skip_pwm & (1 << 0))) { | 1680 | for (i = 0; i < 3; i++) { |
1211 | if ((err = device_create_file(dev, | 1681 | if (sio_data->skip_pwm & (1 << i)) |
1212 | &sensor_dev_attr_pwm1_enable.dev_attr)) | 1682 | continue; |
1213 | || (err = device_create_file(dev, | 1683 | err = sysfs_create_group(&dev->kobj, |
1214 | &sensor_dev_attr_pwm1.dev_attr)) | 1684 | &it87_group_pwm[i]); |
1215 | || (err = device_create_file(dev, | 1685 | if (err) |
1216 | &dev_attr_pwm1_freq))) | ||
1217 | goto ERROR4; | ||
1218 | } | ||
1219 | if (!(sio_data->skip_pwm & (1 << 1))) { | ||
1220 | if ((err = device_create_file(dev, | ||
1221 | &sensor_dev_attr_pwm2_enable.dev_attr)) | ||
1222 | || (err = device_create_file(dev, | ||
1223 | &sensor_dev_attr_pwm2.dev_attr)) | ||
1224 | || (err = device_create_file(dev, | ||
1225 | &dev_attr_pwm2_freq))) | ||
1226 | goto ERROR4; | 1686 | goto ERROR4; |
1227 | } | 1687 | |
1228 | if (!(sio_data->skip_pwm & (1 << 2))) { | 1688 | if (!has_old_autopwm(data)) |
1229 | if ((err = device_create_file(dev, | 1689 | continue; |
1230 | &sensor_dev_attr_pwm3_enable.dev_attr)) | 1690 | err = sysfs_create_group(&dev->kobj, |
1231 | || (err = device_create_file(dev, | 1691 | &it87_group_autopwm[i]); |
1232 | &sensor_dev_attr_pwm3.dev_attr)) | 1692 | if (err) |
1233 | || (err = device_create_file(dev, | ||
1234 | &dev_attr_pwm3_freq))) | ||
1235 | goto ERROR4; | 1693 | goto ERROR4; |
1236 | } | 1694 | } |
1237 | } | 1695 | } |
1238 | 1696 | ||
1239 | if (data->type == it8712 || data->type == it8716 | 1697 | if (!sio_data->skip_vid) { |
1240 | || data->type == it8718 || data->type == it8720) { | ||
1241 | data->vrm = vid_which_vrm(); | 1698 | data->vrm = vid_which_vrm(); |
1242 | /* VID reading from Super-I/O config space if available */ | 1699 | /* VID reading from Super-I/O config space if available */ |
1243 | data->vid = sio_data->vid_value; | 1700 | data->vid = sio_data->vid_value; |
1244 | if ((err = device_create_file(dev, | 1701 | err = sysfs_create_group(&dev->kobj, &it87_group_vid); |
1245 | &dev_attr_vrm)) | 1702 | if (err) |
1246 | || (err = device_create_file(dev, | ||
1247 | &dev_attr_cpu0_vid))) | ||
1248 | goto ERROR4; | 1703 | goto ERROR4; |
1249 | } | 1704 | } |
1250 | 1705 | ||
@@ -1257,8 +1712,7 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1257 | return 0; | 1712 | return 0; |
1258 | 1713 | ||
1259 | ERROR4: | 1714 | ERROR4: |
1260 | sysfs_remove_group(&dev->kobj, &it87_group); | 1715 | it87_remove_files(dev); |
1261 | sysfs_remove_group(&dev->kobj, &it87_group_opt); | ||
1262 | ERROR2: | 1716 | ERROR2: |
1263 | platform_set_drvdata(pdev, NULL); | 1717 | platform_set_drvdata(pdev, NULL); |
1264 | kfree(data); | 1718 | kfree(data); |
@@ -1273,8 +1727,7 @@ static int __devexit it87_remove(struct platform_device *pdev) | |||
1273 | struct it87_data *data = platform_get_drvdata(pdev); | 1727 | struct it87_data *data = platform_get_drvdata(pdev); |
1274 | 1728 | ||
1275 | hwmon_device_unregister(data->hwmon_dev); | 1729 | hwmon_device_unregister(data->hwmon_dev); |
1276 | sysfs_remove_group(&pdev->dev.kobj, &it87_group); | 1730 | it87_remove_files(&pdev->dev); |
1277 | sysfs_remove_group(&pdev->dev.kobj, &it87_group_opt); | ||
1278 | 1731 | ||
1279 | release_region(data->addr, IT87_EC_EXTENT); | 1732 | release_region(data->addr, IT87_EC_EXTENT); |
1280 | platform_set_drvdata(pdev, NULL); | 1733 | platform_set_drvdata(pdev, NULL); |
@@ -1355,18 +1808,23 @@ static int __devinit it87_check_pwm(struct device *dev) | |||
1355 | /* Called when we have found a new IT87. */ | 1808 | /* Called when we have found a new IT87. */ |
1356 | static void __devinit it87_init_device(struct platform_device *pdev) | 1809 | static void __devinit it87_init_device(struct platform_device *pdev) |
1357 | { | 1810 | { |
1811 | struct it87_sio_data *sio_data = pdev->dev.platform_data; | ||
1358 | struct it87_data *data = platform_get_drvdata(pdev); | 1812 | struct it87_data *data = platform_get_drvdata(pdev); |
1359 | int tmp, i; | 1813 | int tmp, i; |
1360 | 1814 | u8 mask; | |
1361 | /* initialize to sane defaults: | 1815 | |
1362 | * - if the chip is in manual pwm mode, this will be overwritten with | 1816 | /* For each PWM channel: |
1363 | * the actual settings on the chip (so in this case, initialization | 1817 | * - If it is in automatic mode, setting to manual mode should set |
1364 | * is not needed) | 1818 | * the fan to full speed by default. |
1365 | * - if in automatic or on/off mode, we could switch to manual mode, | 1819 | * - If it is in manual mode, we need a mapping to temperature |
1366 | * read the registers and set manual_pwm_ctl accordingly, but currently | 1820 | * channels to use when later setting to automatic mode later. |
1367 | * this is not implemented, so we initialize to something sane */ | 1821 | * Use a 1:1 mapping by default (we are clueless.) |
1822 | * In both cases, the value can (and should) be changed by the user | ||
1823 | * prior to switching to a different mode. */ | ||
1368 | for (i = 0; i < 3; i++) { | 1824 | for (i = 0; i < 3; i++) { |
1369 | data->manual_pwm_ctl[i] = 0xff; | 1825 | data->pwm_temp_map[i] = i; |
1826 | data->pwm_duty[i] = 0x7f; /* Full speed */ | ||
1827 | data->auto_pwm[i][3] = 0x7f; /* Full speed, hard-coded */ | ||
1370 | } | 1828 | } |
1371 | 1829 | ||
1372 | /* Some chips seem to have default value 0xff for all limit | 1830 | /* Some chips seem to have default value 0xff for all limit |
@@ -1385,14 +1843,10 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
1385 | it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); | 1843 | it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); |
1386 | } | 1844 | } |
1387 | 1845 | ||
1388 | /* Check if temperature channels are reset manually or by some reason */ | 1846 | /* Temperature channels are not forcibly enabled, as they can be |
1389 | tmp = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 1847 | * set to two different sensor types and we can't guess which one |
1390 | if ((tmp & 0x3f) == 0) { | 1848 | * is correct for a given system. These channels can be enabled at |
1391 | /* Temp1,Temp3=thermistor; Temp2=thermal diode */ | 1849 | * run-time through the temp{1-3}_type sysfs accessors if needed. */ |
1392 | tmp = (tmp & 0xc0) | 0x2a; | ||
1393 | it87_write_value(data, IT87_REG_TEMP_ENABLE, tmp); | ||
1394 | } | ||
1395 | data->sensor = tmp; | ||
1396 | 1850 | ||
1397 | /* Check if voltage monitors are reset manually or by some reason */ | 1851 | /* Check if voltage monitors are reset manually or by some reason */ |
1398 | tmp = it87_read_value(data, IT87_REG_VIN_ENABLE); | 1852 | tmp = it87_read_value(data, IT87_REG_VIN_ENABLE); |
@@ -1402,11 +1856,13 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
1402 | } | 1856 | } |
1403 | 1857 | ||
1404 | /* Check if tachometers are reset manually or by some reason */ | 1858 | /* Check if tachometers are reset manually or by some reason */ |
1859 | mask = 0x70 & ~(sio_data->skip_fan << 4); | ||
1405 | data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); | 1860 | data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); |
1406 | if ((data->fan_main_ctrl & 0x70) == 0) { | 1861 | if ((data->fan_main_ctrl & mask) == 0) { |
1407 | /* Enable all fan tachometers */ | 1862 | /* Enable all fan tachometers */ |
1408 | data->fan_main_ctrl |= 0x70; | 1863 | data->fan_main_ctrl |= mask; |
1409 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 1864 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, |
1865 | data->fan_main_ctrl); | ||
1410 | } | 1866 | } |
1411 | data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; | 1867 | data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; |
1412 | 1868 | ||
@@ -1428,23 +1884,8 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
1428 | } | 1884 | } |
1429 | } | 1885 | } |
1430 | 1886 | ||
1431 | /* Set current fan mode registers and the default settings for the | 1887 | /* Fan input pins may be used for alternative functions */ |
1432 | * other mode registers */ | 1888 | data->has_fan &= ~sio_data->skip_fan; |
1433 | for (i = 0; i < 3; i++) { | ||
1434 | if (data->fan_main_ctrl & (1 << i)) { | ||
1435 | /* pwm mode */ | ||
1436 | tmp = it87_read_value(data, IT87_REG_PWM(i)); | ||
1437 | if (tmp & 0x80) { | ||
1438 | /* automatic pwm - not yet implemented, but | ||
1439 | * leave the settings made by the BIOS alone | ||
1440 | * until a change is requested via the sysfs | ||
1441 | * interface */ | ||
1442 | } else { | ||
1443 | /* manual pwm */ | ||
1444 | data->manual_pwm_ctl[i] = PWM_FROM_REG(tmp); | ||
1445 | } | ||
1446 | } | ||
1447 | } | ||
1448 | 1889 | ||
1449 | /* Start monitoring */ | 1890 | /* Start monitoring */ |
1450 | it87_write_value(data, IT87_REG_CONFIG, | 1891 | it87_write_value(data, IT87_REG_CONFIG, |
@@ -1452,6 +1893,26 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
1452 | | (update_vbat ? 0x41 : 0x01)); | 1893 | | (update_vbat ? 0x41 : 0x01)); |
1453 | } | 1894 | } |
1454 | 1895 | ||
1896 | static void it87_update_pwm_ctrl(struct it87_data *data, int nr) | ||
1897 | { | ||
1898 | data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr)); | ||
1899 | if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ | ||
1900 | data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; | ||
1901 | else /* Manual mode */ | ||
1902 | data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f; | ||
1903 | |||
1904 | if (has_old_autopwm(data)) { | ||
1905 | int i; | ||
1906 | |||
1907 | for (i = 0; i < 5 ; i++) | ||
1908 | data->auto_temp[nr][i] = it87_read_value(data, | ||
1909 | IT87_REG_AUTO_TEMP(nr, i)); | ||
1910 | for (i = 0; i < 3 ; i++) | ||
1911 | data->auto_pwm[nr][i] = it87_read_value(data, | ||
1912 | IT87_REG_AUTO_PWM(nr, i)); | ||
1913 | } | ||
1914 | } | ||
1915 | |||
1455 | static struct it87_data *it87_update_device(struct device *dev) | 1916 | static struct it87_data *it87_update_device(struct device *dev) |
1456 | { | 1917 | { |
1457 | struct it87_data *data = dev_get_drvdata(dev); | 1918 | struct it87_data *data = dev_get_drvdata(dev); |
@@ -1461,24 +1922,22 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1461 | 1922 | ||
1462 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 1923 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) |
1463 | || !data->valid) { | 1924 | || !data->valid) { |
1464 | |||
1465 | if (update_vbat) { | 1925 | if (update_vbat) { |
1466 | /* Cleared after each update, so reenable. Value | 1926 | /* Cleared after each update, so reenable. Value |
1467 | returned by this read will be previous value */ | 1927 | returned by this read will be previous value */ |
1468 | it87_write_value(data, IT87_REG_CONFIG, | 1928 | it87_write_value(data, IT87_REG_CONFIG, |
1469 | it87_read_value(data, IT87_REG_CONFIG) | 0x40); | 1929 | it87_read_value(data, IT87_REG_CONFIG) | 0x40); |
1470 | } | 1930 | } |
1471 | for (i = 0; i <= 7; i++) { | 1931 | for (i = 0; i <= 7; i++) { |
1472 | data->in[i] = | 1932 | data->in[i] = |
1473 | it87_read_value(data, IT87_REG_VIN(i)); | 1933 | it87_read_value(data, IT87_REG_VIN(i)); |
1474 | data->in_min[i] = | 1934 | data->in_min[i] = |
1475 | it87_read_value(data, IT87_REG_VIN_MIN(i)); | 1935 | it87_read_value(data, IT87_REG_VIN_MIN(i)); |
1476 | data->in_max[i] = | 1936 | data->in_max[i] = |
1477 | it87_read_value(data, IT87_REG_VIN_MAX(i)); | 1937 | it87_read_value(data, IT87_REG_VIN_MAX(i)); |
1478 | } | 1938 | } |
1479 | /* in8 (battery) has no limit registers */ | 1939 | /* in8 (battery) has no limit registers */ |
1480 | data->in[8] = | 1940 | data->in[8] = it87_read_value(data, IT87_REG_VIN(8)); |
1481 | it87_read_value(data, IT87_REG_VIN(8)); | ||
1482 | 1941 | ||
1483 | for (i = 0; i < 5; i++) { | 1942 | for (i = 0; i < 5; i++) { |
1484 | /* Skip disabled fans */ | 1943 | /* Skip disabled fans */ |
@@ -1486,7 +1945,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1486 | continue; | 1945 | continue; |
1487 | 1946 | ||
1488 | data->fan_min[i] = | 1947 | data->fan_min[i] = |
1489 | it87_read_value(data, IT87_REG_FAN_MIN[i]); | 1948 | it87_read_value(data, IT87_REG_FAN_MIN[i]); |
1490 | data->fan[i] = it87_read_value(data, | 1949 | data->fan[i] = it87_read_value(data, |
1491 | IT87_REG_FAN[i]); | 1950 | IT87_REG_FAN[i]); |
1492 | /* Add high byte if in 16-bit mode */ | 1951 | /* Add high byte if in 16-bit mode */ |
@@ -1499,11 +1958,11 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1499 | } | 1958 | } |
1500 | for (i = 0; i < 3; i++) { | 1959 | for (i = 0; i < 3; i++) { |
1501 | data->temp[i] = | 1960 | data->temp[i] = |
1502 | it87_read_value(data, IT87_REG_TEMP(i)); | 1961 | it87_read_value(data, IT87_REG_TEMP(i)); |
1503 | data->temp_high[i] = | 1962 | data->temp_high[i] = |
1504 | it87_read_value(data, IT87_REG_TEMP_HIGH(i)); | 1963 | it87_read_value(data, IT87_REG_TEMP_HIGH(i)); |
1505 | data->temp_low[i] = | 1964 | data->temp_low[i] = |
1506 | it87_read_value(data, IT87_REG_TEMP_LOW(i)); | 1965 | it87_read_value(data, IT87_REG_TEMP_LOW(i)); |
1507 | } | 1966 | } |
1508 | 1967 | ||
1509 | /* Newer chips don't have clock dividers */ | 1968 | /* Newer chips don't have clock dividers */ |
@@ -1518,9 +1977,13 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1518 | it87_read_value(data, IT87_REG_ALARM1) | | 1977 | it87_read_value(data, IT87_REG_ALARM1) | |
1519 | (it87_read_value(data, IT87_REG_ALARM2) << 8) | | 1978 | (it87_read_value(data, IT87_REG_ALARM2) << 8) | |
1520 | (it87_read_value(data, IT87_REG_ALARM3) << 16); | 1979 | (it87_read_value(data, IT87_REG_ALARM3) << 16); |
1980 | data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); | ||
1981 | |||
1521 | data->fan_main_ctrl = it87_read_value(data, | 1982 | data->fan_main_ctrl = it87_read_value(data, |
1522 | IT87_REG_FAN_MAIN_CTRL); | 1983 | IT87_REG_FAN_MAIN_CTRL); |
1523 | data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); | 1984 | data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); |
1985 | for (i = 0; i < 3; i++) | ||
1986 | it87_update_pwm_ctrl(data, i); | ||
1524 | 1987 | ||
1525 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 1988 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
1526 | /* The 8705 does not have VID capability. | 1989 | /* The 8705 does not have VID capability. |
@@ -1595,7 +2058,7 @@ exit: | |||
1595 | static int __init sm_it87_init(void) | 2058 | static int __init sm_it87_init(void) |
1596 | { | 2059 | { |
1597 | int err; | 2060 | int err; |
1598 | unsigned short isa_address=0; | 2061 | unsigned short isa_address = 0; |
1599 | struct it87_sio_data sio_data; | 2062 | struct it87_sio_data sio_data; |
1600 | 2063 | ||
1601 | memset(&sio_data, 0, sizeof(struct it87_sio_data)); | 2064 | memset(&sio_data, 0, sizeof(struct it87_sio_data)); |
@@ -1607,7 +2070,7 @@ static int __init sm_it87_init(void) | |||
1607 | return err; | 2070 | return err; |
1608 | 2071 | ||
1609 | err = it87_device_add(isa_address, &sio_data); | 2072 | err = it87_device_add(isa_address, &sio_data); |
1610 | if (err){ | 2073 | if (err) { |
1611 | platform_driver_unregister(&it87_driver); | 2074 | platform_driver_unregister(&it87_driver); |
1612 | return err; | 2075 | return err; |
1613 | } | 2076 | } |
@@ -1628,7 +2091,8 @@ MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8720F/8726F, SiS950 driver"); | |||
1628 | module_param(update_vbat, bool, 0); | 2091 | module_param(update_vbat, bool, 0); |
1629 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); | 2092 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); |
1630 | module_param(fix_pwm_polarity, bool, 0); | 2093 | module_param(fix_pwm_polarity, bool, 0); |
1631 | MODULE_PARM_DESC(fix_pwm_polarity, "Force PWM polarity to active high (DANGEROUS)"); | 2094 | MODULE_PARM_DESC(fix_pwm_polarity, |
2095 | "Force PWM polarity to active high (DANGEROUS)"); | ||
1632 | MODULE_LICENSE("GPL"); | 2096 | MODULE_LICENSE("GPL"); |
1633 | 2097 | ||
1634 | module_init(sm_it87_init); | 2098 | module_init(sm_it87_init); |