diff options
| -rw-r--r-- | Documentation/hwmon/emc2103 | 33 | ||||
| -rw-r--r-- | Documentation/hwmon/ltc4245 | 24 | ||||
| -rw-r--r-- | Documentation/hwmon/pc87427 | 27 | ||||
| -rw-r--r-- | Documentation/hwmon/sysfs-interface | 29 | ||||
| -rw-r--r-- | Documentation/hwmon/w83627ehf | 15 | ||||
| -rw-r--r-- | MAINTAINERS | 14 | ||||
| -rw-r--r-- | drivers/hwmon/Kconfig | 14 | ||||
| -rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
| -rw-r--r-- | drivers/hwmon/asc7621.c | 9 | ||||
| -rw-r--r-- | drivers/hwmon/emc1403.c | 33 | ||||
| -rw-r--r-- | drivers/hwmon/emc2103.c | 740 | ||||
| -rw-r--r-- | drivers/hwmon/it87.c | 46 | ||||
| -rw-r--r-- | drivers/hwmon/k8temp.c | 3 | ||||
| -rw-r--r-- | drivers/hwmon/lm75.c | 39 | ||||
| -rw-r--r-- | drivers/hwmon/lm75.h | 1 | ||||
| -rw-r--r-- | drivers/hwmon/ltc4245.c | 177 | ||||
| -rw-r--r-- | drivers/hwmon/pc87360.c | 31 | ||||
| -rw-r--r-- | drivers/hwmon/pc87427.c | 862 | ||||
| -rw-r--r-- | drivers/hwmon/via-cputemp.c | 2 | ||||
| -rw-r--r-- | drivers/hwmon/w83627ehf.c | 97 | ||||
| -rw-r--r-- | include/linux/i2c/ltc4245.h | 21 |
21 files changed, 2085 insertions, 133 deletions
diff --git a/Documentation/hwmon/emc2103 b/Documentation/hwmon/emc2103 new file mode 100644 index 000000000000..a12b2c127140 --- /dev/null +++ b/Documentation/hwmon/emc2103 | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | Kernel driver emc2103 | ||
| 2 | ====================== | ||
| 3 | |||
| 4 | Supported chips: | ||
| 5 | * SMSC EMC2103 | ||
| 6 | Addresses scanned: I2C 0x2e | ||
| 7 | Prefix: 'emc2103' | ||
| 8 | Datasheet: Not public | ||
| 9 | |||
| 10 | Authors: | ||
| 11 | Steve Glendinning <steve.glendinning@smsc.com> | ||
| 12 | |||
| 13 | Description | ||
| 14 | ----------- | ||
| 15 | |||
| 16 | The Standard Microsystems Corporation (SMSC) EMC2103 chips | ||
| 17 | contain up to 4 temperature sensors and a single fan controller. | ||
| 18 | |||
| 19 | Fan rotation speeds are reported in RPM (rotations per minute). An alarm is | ||
| 20 | triggered if the rotation speed has dropped below a programmable limit. Fan | ||
| 21 | readings can be divided by a programmable divider (1, 2, 4 or 8) to give | ||
| 22 | the readings more range or accuracy. Not all RPM values can accurately be | ||
| 23 | represented, so some rounding is done. With a divider of 1, the lowest | ||
| 24 | representable value is 480 RPM. | ||
| 25 | |||
| 26 | This driver supports RPM based control, to use this a fan target | ||
| 27 | should be written to fan1_target and pwm1_enable should be set to 3. | ||
| 28 | |||
| 29 | The 2103-2 and 2103-4 variants have a third temperature sensor, which can | ||
| 30 | be connected to two anti-parallel diodes. These values can be read | ||
| 31 | as temp3 and temp4. If only one diode is attached to this channel, temp4 | ||
| 32 | will show as "fault". The module parameter "apd=0" can be used to suppress | ||
| 33 | this 4th channel when anti-parallel diodes are not fitted. | ||
diff --git a/Documentation/hwmon/ltc4245 b/Documentation/hwmon/ltc4245 index 86b5880d8502..b478b0864965 100644 --- a/Documentation/hwmon/ltc4245 +++ b/Documentation/hwmon/ltc4245 | |||
| @@ -72,9 +72,31 @@ in6_min_alarm 5v output undervoltage alarm | |||
| 72 | in7_min_alarm 3v output undervoltage alarm | 72 | in7_min_alarm 3v output undervoltage alarm |
| 73 | in8_min_alarm Vee (-12v) output undervoltage alarm | 73 | in8_min_alarm Vee (-12v) output undervoltage alarm |
| 74 | 74 | ||
| 75 | in9_input GPIO voltage data | 75 | in9_input GPIO voltage data (see note 1) |
| 76 | in10_input GPIO voltage data (see note 1) | ||
| 77 | in11_input GPIO voltage data (see note 1) | ||
| 76 | 78 | ||
| 77 | power1_input 12v power usage (mW) | 79 | power1_input 12v power usage (mW) |
| 78 | power2_input 5v power usage (mW) | 80 | power2_input 5v power usage (mW) |
| 79 | power3_input 3v power usage (mW) | 81 | power3_input 3v power usage (mW) |
| 80 | power4_input Vee (-12v) power usage (mW) | 82 | power4_input Vee (-12v) power usage (mW) |
| 83 | |||
| 84 | |||
| 85 | Note 1 | ||
| 86 | ------ | ||
| 87 | |||
| 88 | If you have NOT configured the driver to sample all GPIO pins as analog | ||
| 89 | voltages, then the in10_input and in11_input sysfs attributes will not be | ||
| 90 | created. The driver will sample the GPIO pin that is currently connected to the | ||
| 91 | ADC as an analog voltage, and report the value in in9_input. | ||
| 92 | |||
| 93 | If you have configured the driver to sample all GPIO pins as analog voltages, | ||
| 94 | then they will be sampled in round-robin fashion. If userspace reads too | ||
| 95 | slowly, -EAGAIN will be returned when you read the sysfs attribute containing | ||
| 96 | the sensor reading. | ||
| 97 | |||
| 98 | The LTC4245 chip can be configured to sample all GPIO pins with two methods: | ||
| 99 | 1) platform data -- see include/linux/i2c/ltc4245.h | ||
| 100 | 2) OF device tree -- add the "ltc4245,use-extra-gpios" property to each chip | ||
| 101 | |||
| 102 | The default mode of operation is to sample a single GPIO pin. | ||
diff --git a/Documentation/hwmon/pc87427 b/Documentation/hwmon/pc87427 index db5cc1227a83..8fdd08c9e48b 100644 --- a/Documentation/hwmon/pc87427 +++ b/Documentation/hwmon/pc87427 | |||
| @@ -18,10 +18,11 @@ Description | |||
| 18 | 18 | ||
| 19 | The National Semiconductor Super I/O chip includes complete hardware | 19 | The National Semiconductor Super I/O chip includes complete hardware |
| 20 | monitoring capabilities. It can monitor up to 18 voltages, 8 fans and | 20 | monitoring capabilities. It can monitor up to 18 voltages, 8 fans and |
| 21 | 6 temperature sensors. Only the fans are supported at the moment. | 21 | 6 temperature sensors. Only the fans and temperatures are supported at |
| 22 | the moment, voltages aren't. | ||
| 22 | 23 | ||
| 23 | This chip also has fan controlling features, which are not yet supported | 24 | This chip also has fan controlling features (up to 4 PWM outputs), |
| 24 | by this driver either. | 25 | which are partly supported by this driver. |
| 25 | 26 | ||
| 26 | The driver assumes that no more than one chip is present, which seems | 27 | The driver assumes that no more than one chip is present, which seems |
| 27 | reasonable. | 28 | reasonable. |
| @@ -36,3 +37,23 @@ signal. Speeds down to 83 RPM can be measured. | |||
| 36 | An alarm is triggered if the rotation speed drops below a programmable | 37 | An alarm is triggered if the rotation speed drops below a programmable |
| 37 | limit. Another alarm is triggered if the speed is too low to be measured | 38 | limit. Another alarm is triggered if the speed is too low to be measured |
| 38 | (including stalled or missing fan). | 39 | (including stalled or missing fan). |
| 40 | |||
| 41 | |||
| 42 | Fan Speed Control | ||
| 43 | ----------------- | ||
| 44 | |||
| 45 | Fan speed can be controlled by PWM outputs. There are 4 possible modes: | ||
| 46 | always off, always on, manual and automatic. The latter isn't supported | ||
| 47 | by the driver: you can only return to that mode if it was the original | ||
| 48 | setting, and the configuration interface is missing. | ||
| 49 | |||
| 50 | |||
| 51 | Temperature Monitoring | ||
| 52 | ---------------------- | ||
| 53 | |||
| 54 | The PC87427 relies on external sensors (following the SensorPath | ||
| 55 | standard), so the resolution and range depend on the type of sensor | ||
| 56 | connected. The integer part can be 8-bit or 9-bit, and can be signed or | ||
| 57 | not. I couldn't find a way to figure out the external sensor data | ||
| 58 | temperature format, so user-space adjustment (typically by a factor 2) | ||
| 59 | may be required. | ||
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index d4e2917c6f18..ff45d1f837c8 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface | |||
| @@ -107,10 +107,24 @@ in[0-*]_min Voltage min value. | |||
| 107 | Unit: millivolt | 107 | Unit: millivolt |
| 108 | RW | 108 | RW |
| 109 | 109 | ||
| 110 | in[0-*]_lcrit Voltage critical min value. | ||
| 111 | Unit: millivolt | ||
| 112 | RW | ||
| 113 | If voltage drops to or below this limit, the system may | ||
| 114 | take drastic action such as power down or reset. At the very | ||
| 115 | least, it should report a fault. | ||
| 116 | |||
| 110 | in[0-*]_max Voltage max value. | 117 | in[0-*]_max Voltage max value. |
| 111 | Unit: millivolt | 118 | Unit: millivolt |
| 112 | RW | 119 | RW |
| 113 | 120 | ||
| 121 | in[0-*]_crit Voltage critical max value. | ||
| 122 | Unit: millivolt | ||
| 123 | RW | ||
| 124 | If voltage reaches or exceeds this limit, the system may | ||
| 125 | take drastic action such as power down or reset. At the very | ||
| 126 | least, it should report a fault. | ||
| 127 | |||
| 114 | in[0-*]_input Voltage input value. | 128 | in[0-*]_input Voltage input value. |
| 115 | Unit: millivolt | 129 | Unit: millivolt |
| 116 | RO | 130 | RO |
| @@ -284,7 +298,7 @@ temp[1-*]_input Temperature input value. | |||
| 284 | Unit: millidegree Celsius | 298 | Unit: millidegree Celsius |
| 285 | RO | 299 | RO |
| 286 | 300 | ||
| 287 | temp[1-*]_crit Temperature critical value, typically greater than | 301 | temp[1-*]_crit Temperature critical max value, typically greater than |
| 288 | corresponding temp_max values. | 302 | corresponding temp_max values. |
| 289 | Unit: millidegree Celsius | 303 | Unit: millidegree Celsius |
| 290 | RW | 304 | RW |
| @@ -296,6 +310,11 @@ temp[1-*]_crit_hyst | |||
| 296 | from the critical value. | 310 | from the critical value. |
| 297 | RW | 311 | RW |
| 298 | 312 | ||
| 313 | temp[1-*]_lcrit Temperature critical min value, typically lower than | ||
| 314 | corresponding temp_min values. | ||
| 315 | Unit: millidegree Celsius | ||
| 316 | RW | ||
| 317 | |||
| 299 | temp[1-*]_offset | 318 | temp[1-*]_offset |
| 300 | Temperature offset which is added to the temperature reading | 319 | Temperature offset which is added to the temperature reading |
| 301 | by the chip. | 320 | by the chip. |
| @@ -344,9 +363,6 @@ Also see the Alarms section for status flags associated with temperatures. | |||
| 344 | * Currents * | 363 | * Currents * |
| 345 | ************ | 364 | ************ |
| 346 | 365 | ||
| 347 | Note that no known chip provides current measurements as of writing, | ||
| 348 | so this part is theoretical, so to say. | ||
| 349 | |||
| 350 | curr[1-*]_max Current max value | 366 | curr[1-*]_max Current max value |
| 351 | Unit: milliampere | 367 | Unit: milliampere |
| 352 | RW | 368 | RW |
| @@ -471,6 +487,7 @@ limit-related alarms, not both. The driver should just reflect the hardware | |||
| 471 | implementation. | 487 | implementation. |
| 472 | 488 | ||
| 473 | in[0-*]_alarm | 489 | in[0-*]_alarm |
| 490 | curr[1-*]_alarm | ||
| 474 | fan[1-*]_alarm | 491 | fan[1-*]_alarm |
| 475 | temp[1-*]_alarm | 492 | temp[1-*]_alarm |
| 476 | Channel alarm | 493 | Channel alarm |
| @@ -482,6 +499,8 @@ OR | |||
| 482 | 499 | ||
| 483 | in[0-*]_min_alarm | 500 | in[0-*]_min_alarm |
| 484 | in[0-*]_max_alarm | 501 | in[0-*]_max_alarm |
| 502 | curr[1-*]_min_alarm | ||
| 503 | curr[1-*]_max_alarm | ||
| 485 | fan[1-*]_min_alarm | 504 | fan[1-*]_min_alarm |
| 486 | fan[1-*]_max_alarm | 505 | fan[1-*]_max_alarm |
| 487 | temp[1-*]_min_alarm | 506 | temp[1-*]_min_alarm |
| @@ -497,7 +516,6 @@ to notify open diodes, unconnected fans etc. where the hardware | |||
| 497 | supports it. When this boolean has value 1, the measurement for that | 516 | supports it. When this boolean has value 1, the measurement for that |
| 498 | channel should not be trusted. | 517 | channel should not be trusted. |
| 499 | 518 | ||
| 500 | in[0-*]_fault | ||
| 501 | fan[1-*]_fault | 519 | fan[1-*]_fault |
| 502 | temp[1-*]_fault | 520 | temp[1-*]_fault |
| 503 | Input fault condition | 521 | Input fault condition |
| @@ -513,6 +531,7 @@ beep_enable Master beep enable | |||
| 513 | RW | 531 | RW |
| 514 | 532 | ||
| 515 | in[0-*]_beep | 533 | in[0-*]_beep |
| 534 | curr[1-*]_beep | ||
| 516 | fan[1-*]_beep | 535 | fan[1-*]_beep |
| 517 | temp[1-*]_beep | 536 | temp[1-*]_beep |
| 518 | Channel beep | 537 | Channel beep |
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf index b7e42ec4b26b..13d556112fc0 100644 --- a/Documentation/hwmon/w83627ehf +++ b/Documentation/hwmon/w83627ehf | |||
| @@ -20,6 +20,10 @@ Supported chips: | |||
| 20 | Prefix: 'w83667hg' | 20 | Prefix: 'w83667hg' |
| 21 | Addresses scanned: ISA address retrieved from Super I/O registers | 21 | Addresses scanned: ISA address retrieved from Super I/O registers |
| 22 | Datasheet: not available | 22 | Datasheet: not available |
| 23 | * Winbond W83667HG-B | ||
| 24 | Prefix: 'w83667hg' | ||
| 25 | Addresses scanned: ISA address retrieved from Super I/O registers | ||
| 26 | Datasheet: Available from Nuvoton upon request | ||
| 23 | 27 | ||
| 24 | Authors: | 28 | Authors: |
| 25 | Jean Delvare <khali@linux-fr.org> | 29 | Jean Delvare <khali@linux-fr.org> |
| @@ -32,8 +36,8 @@ Description | |||
| 32 | ----------- | 36 | ----------- |
| 33 | 37 | ||
| 34 | This driver implements support for the Winbond W83627EHF, W83627EHG, | 38 | This driver implements support for the Winbond W83627EHF, W83627EHG, |
| 35 | W83627DHG, W83627DHG-P and W83667HG super I/O chips. We will refer to them | 39 | W83627DHG, W83627DHG-P, W83667HG and W83667HG-B super I/O chips. |
| 36 | collectively as Winbond chips. | 40 | We will refer to them collectively as Winbond chips. |
| 37 | 41 | ||
| 38 | The chips implement three temperature sensors, five fan rotation | 42 | The chips implement three temperature sensors, five fan rotation |
| 39 | speed sensors, ten analog voltage sensors (only nine for the 627DHG), one | 43 | speed sensors, ten analog voltage sensors (only nine for the 627DHG), one |
| @@ -68,14 +72,15 @@ follows: | |||
| 68 | temp1 -> pwm1 | 72 | temp1 -> pwm1 |
| 69 | temp2 -> pwm2 | 73 | temp2 -> pwm2 |
| 70 | temp3 -> pwm3 | 74 | temp3 -> pwm3 |
| 71 | prog -> pwm4 (not on 667HG; the programmable setting is not supported by | 75 | prog -> pwm4 (not on 667HG and 667HG-B; the programmable setting is not |
| 72 | the driver) | 76 | supported by the driver) |
| 73 | 77 | ||
| 74 | /sys files | 78 | /sys files |
| 75 | ---------- | 79 | ---------- |
| 76 | 80 | ||
| 77 | name - this is a standard hwmon device entry. For the W83627EHF and W83627EHG, | 81 | name - this is a standard hwmon device entry. For the W83627EHF and W83627EHG, |
| 78 | it is set to "w83627ehf" and for the W83627DHG it is set to "w83627dhg" | 82 | it is set to "w83627ehf", for the W83627DHG it is set to "w83627dhg", |
| 83 | and for the W83667HG it is set to "w83667hg". | ||
| 79 | 84 | ||
| 80 | pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range: | 85 | pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range: |
| 81 | 0 (stop) to 255 (full) | 86 | 0 (stop) to 255 (full) |
diff --git a/MAINTAINERS b/MAINTAINERS index 39d8c5ce9913..99b6f8203a50 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -4402,6 +4402,13 @@ M: Jim Cromie <jim.cromie@gmail.com> | |||
| 4402 | S: Maintained | 4402 | S: Maintained |
| 4403 | F: drivers/char/pc8736x_gpio.c | 4403 | F: drivers/char/pc8736x_gpio.c |
| 4404 | 4404 | ||
| 4405 | PC87427 HARDWARE MONITORING DRIVER | ||
| 4406 | M: Jean Delvare <khali@linux-fr.org> | ||
| 4407 | L: lm-sensors@lm-sensors.org | ||
| 4408 | S: Maintained | ||
| 4409 | F: Documentation/hwmon/pc87427 | ||
| 4410 | F: drivers/hwmon/pc87427.c | ||
| 4411 | |||
| 4405 | PCA9532 LED DRIVER | 4412 | PCA9532 LED DRIVER |
| 4406 | M: Riku Voipio <riku.voipio@iki.fi> | 4413 | M: Riku Voipio <riku.voipio@iki.fi> |
| 4407 | S: Maintained | 4414 | S: Maintained |
| @@ -5279,6 +5286,13 @@ S: Maintained | |||
| 5279 | F: Documentation/hwmon/smm665 | 5286 | F: Documentation/hwmon/smm665 |
| 5280 | F: drivers/hwmon/smm665.c | 5287 | F: drivers/hwmon/smm665.c |
| 5281 | 5288 | ||
| 5289 | SMSC EMC2103 HARDWARE MONITOR DRIVER | ||
| 5290 | M: Steve Glendinning <steve.glendinning@smsc.com> | ||
| 5291 | L: lm-sensors@lm-sensors.org | ||
| 5292 | S: Supported | ||
| 5293 | F: Documentation/hwmon/emc2103 | ||
| 5294 | F: drivers/hwmon/emc2103.c | ||
| 5295 | |||
| 5282 | SMSC47B397 HARDWARE MONITOR DRIVER | 5296 | SMSC47B397 HARDWARE MONITOR DRIVER |
| 5283 | M: "Mark M. Hoffman" <mhoffman@lightlink.com> | 5297 | M: "Mark M. Hoffman" <mhoffman@lightlink.com> |
| 5284 | L: lm-sensors@lm-sensors.org | 5298 | L: lm-sensors@lm-sensors.org |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index f3adf18bfa05..0fba82943125 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
| @@ -465,6 +465,7 @@ config SENSORS_JZ4740 | |||
| 465 | 465 | ||
| 466 | config SENSORS_JC42 | 466 | config SENSORS_JC42 |
| 467 | tristate "JEDEC JC42.4 compliant temperature sensors" | 467 | tristate "JEDEC JC42.4 compliant temperature sensors" |
| 468 | depends on I2C | ||
| 468 | help | 469 | help |
| 469 | If you say yes here you get support for Jedec JC42.4 compliant | 470 | If you say yes here you get support for Jedec JC42.4 compliant |
| 470 | temperature sensors. Support will include, but not be limited to, | 471 | temperature sensors. Support will include, but not be limited to, |
| @@ -711,7 +712,8 @@ config SENSORS_PC87427 | |||
| 711 | functions of the National Semiconductor PC87427 Super-I/O chip. | 712 | functions of the National Semiconductor PC87427 Super-I/O chip. |
| 712 | The chip has two distinct logical devices, one for fan speed | 713 | The chip has two distinct logical devices, one for fan speed |
| 713 | monitoring and control, and one for voltage and temperature | 714 | monitoring and control, and one for voltage and temperature |
| 714 | monitoring. Only fan speed monitoring is supported right now. | 715 | monitoring. Fan speed monitoring and control are supported, as |
| 716 | well as temperature monitoring. Voltages aren't supported yet. | ||
| 715 | 717 | ||
| 716 | This driver can also be built as a module. If so, the module | 718 | This driver can also be built as a module. If so, the module |
| 717 | will be called pc87427. | 719 | will be called pc87427. |
| @@ -804,6 +806,16 @@ config SENSORS_EMC1403 | |||
| 804 | Threshold values can be configured using sysfs. | 806 | Threshold values can be configured using sysfs. |
| 805 | Data from the different diodes are accessible via sysfs. | 807 | Data from the different diodes are accessible via sysfs. |
| 806 | 808 | ||
| 809 | config SENSORS_EMC2103 | ||
| 810 | tristate "SMSC EMC2103" | ||
| 811 | depends on I2C | ||
| 812 | help | ||
| 813 | If you say yes here you get support for the temperature | ||
| 814 | and fan sensors of the SMSC EMC2103 chips. | ||
| 815 | |||
| 816 | This driver can also be built as a module. If so, the module | ||
| 817 | will be called emc2103. | ||
| 818 | |||
| 807 | config SENSORS_SMSC47M1 | 819 | config SENSORS_SMSC47M1 |
| 808 | tristate "SMSC LPC47M10x and compatibles" | 820 | tristate "SMSC LPC47M10x and compatibles" |
| 809 | help | 821 | help |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 13d913e34dbf..e3c2484f6c5f 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
| @@ -43,6 +43,7 @@ obj-$(CONFIG_SENSORS_PKGTEMP) += pkgtemp.o | |||
| 43 | obj-$(CONFIG_SENSORS_DME1737) += dme1737.o | 43 | obj-$(CONFIG_SENSORS_DME1737) += dme1737.o |
| 44 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o | 44 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o |
| 45 | obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o | 45 | obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o |
| 46 | obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o | ||
| 46 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o | 47 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o |
| 47 | obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o | 48 | obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o |
| 48 | obj-$(CONFIG_SENSORS_F75375S) += f75375s.o | 49 | obj-$(CONFIG_SENSORS_F75375S) += f75375s.o |
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c index 3b973f30b1f6..89b4f3babe87 100644 --- a/drivers/hwmon/asc7621.c +++ b/drivers/hwmon/asc7621.c | |||
| @@ -1150,9 +1150,6 @@ static int asc7621_detect(struct i2c_client *client, | |||
| 1150 | { | 1150 | { |
| 1151 | struct i2c_adapter *adapter = client->adapter; | 1151 | struct i2c_adapter *adapter = client->adapter; |
| 1152 | int company, verstep, chip_index; | 1152 | int company, verstep, chip_index; |
| 1153 | struct device *dev; | ||
| 1154 | |||
| 1155 | dev = &client->dev; | ||
| 1156 | 1153 | ||
| 1157 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 1154 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
| 1158 | return -ENODEV; | 1155 | return -ENODEV; |
| @@ -1169,13 +1166,11 @@ static int asc7621_detect(struct i2c_client *client, | |||
| 1169 | 1166 | ||
| 1170 | if (company == asc7621_chips[chip_index].company_id && | 1167 | if (company == asc7621_chips[chip_index].company_id && |
| 1171 | verstep == asc7621_chips[chip_index].verstep_id) { | 1168 | verstep == asc7621_chips[chip_index].verstep_id) { |
| 1172 | strlcpy(client->name, asc7621_chips[chip_index].name, | ||
| 1173 | I2C_NAME_SIZE); | ||
| 1174 | strlcpy(info->type, asc7621_chips[chip_index].name, | 1169 | strlcpy(info->type, asc7621_chips[chip_index].name, |
| 1175 | I2C_NAME_SIZE); | 1170 | I2C_NAME_SIZE); |
| 1176 | 1171 | ||
| 1177 | dev_info(&adapter->dev, "Matched %s\n", | 1172 | dev_info(&adapter->dev, "Matched %s at 0x%02x\n", |
| 1178 | asc7621_chips[chip_index].name); | 1173 | asc7621_chips[chip_index].name, client->addr); |
| 1179 | return 0; | 1174 | return 0; |
| 1180 | } | 1175 | } |
| 1181 | } | 1176 | } |
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 0e4b5642638d..5b58b20dead1 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c | |||
| @@ -89,6 +89,35 @@ static ssize_t store_temp(struct device *dev, | |||
| 89 | return count; | 89 | return count; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | static ssize_t store_bit(struct device *dev, | ||
| 93 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 94 | { | ||
| 95 | struct i2c_client *client = to_i2c_client(dev); | ||
| 96 | struct thermal_data *data = i2c_get_clientdata(client); | ||
| 97 | struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); | ||
| 98 | unsigned long val; | ||
| 99 | int retval; | ||
| 100 | |||
| 101 | if (strict_strtoul(buf, 10, &val)) | ||
| 102 | return -EINVAL; | ||
| 103 | |||
| 104 | mutex_lock(&data->mutex); | ||
| 105 | retval = i2c_smbus_read_byte_data(client, sda->nr); | ||
| 106 | if (retval < 0) | ||
| 107 | goto fail; | ||
| 108 | |||
| 109 | retval &= ~sda->index; | ||
| 110 | if (val) | ||
| 111 | retval |= sda->index; | ||
| 112 | |||
| 113 | retval = i2c_smbus_write_byte_data(client, sda->index, retval); | ||
| 114 | if (retval == 0) | ||
| 115 | retval = count; | ||
| 116 | fail: | ||
| 117 | mutex_unlock(&data->mutex); | ||
| 118 | return retval; | ||
| 119 | } | ||
| 120 | |||
| 92 | static ssize_t show_hyst(struct device *dev, | 121 | static ssize_t show_hyst(struct device *dev, |
| 93 | struct device_attribute *attr, char *buf) | 122 | struct device_attribute *attr, char *buf) |
| 94 | { | 123 | { |
| @@ -200,6 +229,9 @@ static SENSOR_DEVICE_ATTR_2(temp3_crit_alarm, S_IRUGO, | |||
| 200 | static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR, | 229 | static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR, |
| 201 | show_hyst, store_hyst, 0x1A); | 230 | show_hyst, store_hyst, 0x1A); |
| 202 | 231 | ||
| 232 | static SENSOR_DEVICE_ATTR_2(power_state, S_IRUGO | S_IWUSR, | ||
| 233 | show_bit, store_bit, 0x03, 0x40); | ||
| 234 | |||
| 203 | static struct attribute *mid_att_thermal[] = { | 235 | static struct attribute *mid_att_thermal[] = { |
| 204 | &sensor_dev_attr_temp1_min.dev_attr.attr, | 236 | &sensor_dev_attr_temp1_min.dev_attr.attr, |
| 205 | &sensor_dev_attr_temp1_max.dev_attr.attr, | 237 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
| @@ -225,6 +257,7 @@ static struct attribute *mid_att_thermal[] = { | |||
| 225 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, | 257 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, |
| 226 | &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, | 258 | &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, |
| 227 | &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, | 259 | &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, |
| 260 | &sensor_dev_attr_power_state.dev_attr.attr, | ||
| 228 | NULL | 261 | NULL |
| 229 | }; | 262 | }; |
| 230 | 263 | ||
diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c new file mode 100644 index 000000000000..af914ad93ece --- /dev/null +++ b/drivers/hwmon/emc2103.c | |||
| @@ -0,0 +1,740 @@ | |||
| 1 | /* | ||
| 2 | emc2103.c - Support for SMSC EMC2103 | ||
| 3 | Copyright (c) 2010 SMSC | ||
| 4 | |||
| 5 | This program is free software; you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 2 of the License, or | ||
| 8 | (at your option) any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program; if not, write to the Free Software | ||
| 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | #include <linux/jiffies.h> | ||
| 24 | #include <linux/i2c.h> | ||
| 25 | #include <linux/hwmon.h> | ||
| 26 | #include <linux/hwmon-sysfs.h> | ||
| 27 | #include <linux/err.h> | ||
| 28 | #include <linux/mutex.h> | ||
| 29 | |||
| 30 | /* Addresses scanned */ | ||
| 31 | static const unsigned short normal_i2c[] = { 0x2E, I2C_CLIENT_END }; | ||
| 32 | |||
| 33 | static const u8 REG_TEMP[4] = { 0x00, 0x02, 0x04, 0x06 }; | ||
| 34 | static const u8 REG_TEMP_MIN[4] = { 0x3c, 0x38, 0x39, 0x3a }; | ||
| 35 | static const u8 REG_TEMP_MAX[4] = { 0x34, 0x30, 0x31, 0x32 }; | ||
| 36 | |||
| 37 | #define REG_CONF1 0x20 | ||
| 38 | #define REG_TEMP_MAX_ALARM 0x24 | ||
| 39 | #define REG_TEMP_MIN_ALARM 0x25 | ||
| 40 | #define REG_FAN_CONF1 0x42 | ||
| 41 | #define REG_FAN_TARGET_LO 0x4c | ||
| 42 | #define REG_FAN_TARGET_HI 0x4d | ||
| 43 | #define REG_FAN_TACH_HI 0x4e | ||
| 44 | #define REG_FAN_TACH_LO 0x4f | ||
| 45 | #define REG_PRODUCT_ID 0xfd | ||
| 46 | #define REG_MFG_ID 0xfe | ||
| 47 | |||
| 48 | /* equation 4 from datasheet: rpm = (3932160 * multipler) / count */ | ||
| 49 | #define FAN_RPM_FACTOR 3932160 | ||
| 50 | |||
| 51 | /* 2103-2 and 2103-4's 3rd temperature sensor can be connected to two diodes | ||
| 52 | * in anti-parallel mode, and in this configuration both can be read | ||
| 53 | * independently (so we have 4 temperature inputs). The device can't | ||
| 54 | * detect if it's connected in this mode, so we have to manually enable | ||
| 55 | * it. Default is to leave the device in the state it's already in (-1). | ||
| 56 | * This parameter allows APD mode to be optionally forced on or off */ | ||
| 57 | static int apd = -1; | ||
| 58 | module_param(apd, bool, 0); | ||
| 59 | MODULE_PARM_DESC(init, "Set to zero to disable anti-parallel diode mode"); | ||
| 60 | |||
| 61 | struct temperature { | ||
| 62 | s8 degrees; | ||
| 63 | u8 fraction; /* 0-7 multiples of 0.125 */ | ||
| 64 | }; | ||
| 65 | |||
| 66 | struct emc2103_data { | ||
| 67 | struct device *hwmon_dev; | ||
| 68 | struct mutex update_lock; | ||
| 69 | bool valid; /* registers are valid */ | ||
| 70 | bool fan_rpm_control; | ||
| 71 | int temp_count; /* num of temp sensors */ | ||
| 72 | unsigned long last_updated; /* in jiffies */ | ||
| 73 | struct temperature temp[4]; /* internal + 3 external */ | ||
| 74 | s8 temp_min[4]; /* no fractional part */ | ||
| 75 | s8 temp_max[4]; /* no fractional part */ | ||
| 76 | u8 temp_min_alarm; | ||
| 77 | u8 temp_max_alarm; | ||
| 78 | u8 fan_multiplier; | ||
| 79 | u16 fan_tach; | ||
| 80 | u16 fan_target; | ||
| 81 | }; | ||
| 82 | |||
| 83 | static int read_u8_from_i2c(struct i2c_client *client, u8 i2c_reg, u8 *output) | ||
| 84 | { | ||
| 85 | int status = i2c_smbus_read_byte_data(client, i2c_reg); | ||
| 86 | if (status < 0) { | ||
| 87 | dev_warn(&client->dev, "reg 0x%02x, err %d\n", | ||
| 88 | i2c_reg, status); | ||
| 89 | } else { | ||
| 90 | *output = status; | ||
| 91 | } | ||
| 92 | return status; | ||
| 93 | } | ||
| 94 | |||
| 95 | static void read_temp_from_i2c(struct i2c_client *client, u8 i2c_reg, | ||
| 96 | struct temperature *temp) | ||
| 97 | { | ||
| 98 | u8 degrees, fractional; | ||
| 99 | |||
| 100 | if (read_u8_from_i2c(client, i2c_reg, °rees) < 0) | ||
| 101 | return; | ||
| 102 | |||
| 103 | if (read_u8_from_i2c(client, i2c_reg + 1, &fractional) < 0) | ||
| 104 | return; | ||
| 105 | |||
| 106 | temp->degrees = degrees; | ||
| 107 | temp->fraction = (fractional & 0xe0) >> 5; | ||
| 108 | } | ||
| 109 | |||
| 110 | static void read_fan_from_i2c(struct i2c_client *client, u16 *output, | ||
| 111 | u8 hi_addr, u8 lo_addr) | ||
| 112 | { | ||
| 113 | u8 high_byte, lo_byte; | ||
| 114 | |||
| 115 | if (read_u8_from_i2c(client, hi_addr, &high_byte) < 0) | ||
| 116 | return; | ||
| 117 | |||
| 118 | if (read_u8_from_i2c(client, lo_addr, &lo_byte) < 0) | ||
| 119 | return; | ||
| 120 | |||
| 121 | *output = ((u16)high_byte << 5) | (lo_byte >> 3); | ||
| 122 | } | ||
| 123 | |||
| 124 | static void write_fan_target_to_i2c(struct i2c_client *client, u16 new_target) | ||
| 125 | { | ||
| 126 | u8 high_byte = (new_target & 0x1fe0) >> 5; | ||
| 127 | u8 low_byte = (new_target & 0x001f) << 3; | ||
| 128 | i2c_smbus_write_byte_data(client, REG_FAN_TARGET_LO, low_byte); | ||
| 129 | i2c_smbus_write_byte_data(client, REG_FAN_TARGET_HI, high_byte); | ||
| 130 | } | ||
| 131 | |||
| 132 | static void read_fan_config_from_i2c(struct i2c_client *client) | ||
| 133 | |||
| 134 | { | ||
| 135 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
| 136 | u8 conf1; | ||
| 137 | |||
| 138 | if (read_u8_from_i2c(client, REG_FAN_CONF1, &conf1) < 0) | ||
| 139 | return; | ||
| 140 | |||
| 141 | data->fan_multiplier = 1 << ((conf1 & 0x60) >> 5); | ||
| 142 | data->fan_rpm_control = (conf1 & 0x80) != 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static struct emc2103_data *emc2103_update_device(struct device *dev) | ||
| 146 | { | ||
| 147 | struct i2c_client *client = to_i2c_client(dev); | ||
| 148 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
| 149 | |||
| 150 | mutex_lock(&data->update_lock); | ||
| 151 | |||
| 152 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | ||
| 153 | || !data->valid) { | ||
| 154 | int i; | ||
| 155 | |||
| 156 | for (i = 0; i < data->temp_count; i++) { | ||
| 157 | read_temp_from_i2c(client, REG_TEMP[i], &data->temp[i]); | ||
| 158 | read_u8_from_i2c(client, REG_TEMP_MIN[i], | ||
| 159 | &data->temp_min[i]); | ||
| 160 | read_u8_from_i2c(client, REG_TEMP_MAX[i], | ||
| 161 | &data->temp_max[i]); | ||
| 162 | } | ||
| 163 | |||
| 164 | read_u8_from_i2c(client, REG_TEMP_MIN_ALARM, | ||
| 165 | &data->temp_min_alarm); | ||
| 166 | read_u8_from_i2c(client, REG_TEMP_MAX_ALARM, | ||
| 167 | &data->temp_max_alarm); | ||
| 168 | |||
| 169 | read_fan_from_i2c(client, &data->fan_tach, | ||
| 170 | REG_FAN_TACH_HI, REG_FAN_TACH_LO); | ||
| 171 | read_fan_from_i2c(client, &data->fan_target, | ||
| 172 | REG_FAN_TARGET_HI, REG_FAN_TARGET_LO); | ||
| 173 | read_fan_config_from_i2c(client); | ||
| 174 | |||
| 175 | data->last_updated = jiffies; | ||
| 176 | data->valid = true; | ||
| 177 | } | ||
| 178 | |||
| 179 | mutex_unlock(&data->update_lock); | ||
| 180 | |||
| 181 | return data; | ||
| 182 | } | ||
| 183 | |||
| 184 | static ssize_t | ||
| 185 | show_temp(struct device *dev, struct device_attribute *da, char *buf) | ||
| 186 | { | ||
| 187 | int nr = to_sensor_dev_attr(da)->index; | ||
| 188 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 189 | int millidegrees = data->temp[nr].degrees * 1000 | ||
| 190 | + data->temp[nr].fraction * 125; | ||
| 191 | return sprintf(buf, "%d\n", millidegrees); | ||
| 192 | } | ||
| 193 | |||
| 194 | static ssize_t | ||
| 195 | show_temp_min(struct device *dev, struct device_attribute *da, char *buf) | ||
| 196 | { | ||
| 197 | int nr = to_sensor_dev_attr(da)->index; | ||
| 198 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 199 | int millidegrees = data->temp_min[nr] * 1000; | ||
| 200 | return sprintf(buf, "%d\n", millidegrees); | ||
| 201 | } | ||
| 202 | |||
| 203 | static ssize_t | ||
| 204 | show_temp_max(struct device *dev, struct device_attribute *da, char *buf) | ||
| 205 | { | ||
| 206 | int nr = to_sensor_dev_attr(da)->index; | ||
| 207 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 208 | int millidegrees = data->temp_max[nr] * 1000; | ||
| 209 | return sprintf(buf, "%d\n", millidegrees); | ||
| 210 | } | ||
| 211 | |||
| 212 | static ssize_t | ||
| 213 | show_temp_fault(struct device *dev, struct device_attribute *da, char *buf) | ||
| 214 | { | ||
| 215 | int nr = to_sensor_dev_attr(da)->index; | ||
| 216 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 217 | bool fault = (data->temp[nr].degrees == -128); | ||
| 218 | return sprintf(buf, "%d\n", fault ? 1 : 0); | ||
| 219 | } | ||
| 220 | |||
| 221 | static ssize_t | ||
| 222 | show_temp_min_alarm(struct device *dev, struct device_attribute *da, char *buf) | ||
| 223 | { | ||
| 224 | int nr = to_sensor_dev_attr(da)->index; | ||
| 225 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 226 | bool alarm = data->temp_min_alarm & (1 << nr); | ||
| 227 | return sprintf(buf, "%d\n", alarm ? 1 : 0); | ||
| 228 | } | ||
| 229 | |||
| 230 | static ssize_t | ||
| 231 | show_temp_max_alarm(struct device *dev, struct device_attribute *da, char *buf) | ||
| 232 | { | ||
| 233 | int nr = to_sensor_dev_attr(da)->index; | ||
| 234 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 235 | bool alarm = data->temp_max_alarm & (1 << nr); | ||
| 236 | return sprintf(buf, "%d\n", alarm ? 1 : 0); | ||
| 237 | } | ||
| 238 | |||
| 239 | static ssize_t set_temp_min(struct device *dev, struct device_attribute *da, | ||
| 240 | const char *buf, size_t count) | ||
| 241 | { | ||
| 242 | int nr = to_sensor_dev_attr(da)->index; | ||
| 243 | struct i2c_client *client = to_i2c_client(dev); | ||
| 244 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
| 245 | long val; | ||
| 246 | |||
| 247 | int result = strict_strtol(buf, 10, &val); | ||
| 248 | if (result < 0) | ||
| 249 | return -EINVAL; | ||
| 250 | |||
| 251 | val = DIV_ROUND_CLOSEST(val, 1000); | ||
| 252 | if ((val < -63) || (val > 127)) | ||
| 253 | return -EINVAL; | ||
| 254 | |||
| 255 | mutex_lock(&data->update_lock); | ||
| 256 | data->temp_min[nr] = val; | ||
| 257 | i2c_smbus_write_byte_data(client, REG_TEMP_MIN[nr], val); | ||
| 258 | mutex_unlock(&data->update_lock); | ||
| 259 | |||
| 260 | return count; | ||
| 261 | } | ||
| 262 | |||
| 263 | static ssize_t set_temp_max(struct device *dev, struct device_attribute *da, | ||
| 264 | const char *buf, size_t count) | ||
| 265 | { | ||
| 266 | int nr = to_sensor_dev_attr(da)->index; | ||
| 267 | struct i2c_client *client = to_i2c_client(dev); | ||
| 268 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
| 269 | long val; | ||
| 270 | |||
| 271 | int result = strict_strtol(buf, 10, &val); | ||
| 272 | if (result < 0) | ||
| 273 | return -EINVAL; | ||
| 274 | |||
| 275 | val = DIV_ROUND_CLOSEST(val, 1000); | ||
| 276 | if ((val < -63) || (val > 127)) | ||
| 277 | return -EINVAL; | ||
| 278 | |||
| 279 | mutex_lock(&data->update_lock); | ||
| 280 | data->temp_max[nr] = val; | ||
| 281 | i2c_smbus_write_byte_data(client, REG_TEMP_MAX[nr], val); | ||
| 282 | mutex_unlock(&data->update_lock); | ||
| 283 | |||
| 284 | return count; | ||
| 285 | } | ||
| 286 | |||
| 287 | static ssize_t | ||
| 288 | show_fan(struct device *dev, struct device_attribute *da, char *buf) | ||
| 289 | { | ||
| 290 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 291 | int rpm = 0; | ||
| 292 | if (data->fan_tach != 0) | ||
| 293 | rpm = (FAN_RPM_FACTOR * data->fan_multiplier) / data->fan_tach; | ||
| 294 | return sprintf(buf, "%d\n", rpm); | ||
| 295 | } | ||
| 296 | |||
| 297 | static ssize_t | ||
| 298 | show_fan_div(struct device *dev, struct device_attribute *da, char *buf) | ||
| 299 | { | ||
| 300 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 301 | int fan_div = 8 / data->fan_multiplier; | ||
| 302 | return sprintf(buf, "%d\n", fan_div); | ||
| 303 | } | ||
| 304 | |||
| 305 | /* Note: we also update the fan target here, because its value is | ||
| 306 | determined in part by the fan clock divider. This follows the principle | ||
| 307 | of least surprise; the user doesn't expect the fan target to change just | ||
| 308 | because the divider changed. */ | ||
| 309 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, | ||
| 310 | const char *buf, size_t count) | ||
| 311 | { | ||
| 312 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 313 | struct i2c_client *client = to_i2c_client(dev); | ||
| 314 | int new_range_bits, old_div = 8 / data->fan_multiplier; | ||
| 315 | long new_div; | ||
| 316 | |||
| 317 | int status = strict_strtol(buf, 10, &new_div); | ||
| 318 | if (status < 0) | ||
| 319 | return -EINVAL; | ||
| 320 | |||
| 321 | if (new_div == old_div) /* No change */ | ||
| 322 | return count; | ||
| 323 | |||
| 324 | switch (new_div) { | ||
| 325 | case 1: | ||
| 326 | new_range_bits = 3; | ||
| 327 | break; | ||
| 328 | case 2: | ||
| 329 | new_range_bits = 2; | ||
| 330 | break; | ||
| 331 | case 4: | ||
| 332 | new_range_bits = 1; | ||
| 333 | break; | ||
| 334 | case 8: | ||
| 335 | new_range_bits = 0; | ||
| 336 | break; | ||
| 337 | default: | ||
| 338 | return -EINVAL; | ||
| 339 | } | ||
| 340 | |||
| 341 | mutex_lock(&data->update_lock); | ||
| 342 | |||
| 343 | status = i2c_smbus_read_byte_data(client, REG_FAN_CONF1); | ||
| 344 | if (status < 0) { | ||
| 345 | dev_dbg(&client->dev, "reg 0x%02x, err %d\n", | ||
| 346 | REG_FAN_CONF1, status); | ||
| 347 | mutex_unlock(&data->update_lock); | ||
| 348 | return -EIO; | ||
| 349 | } | ||
| 350 | status &= 0x9F; | ||
| 351 | status |= (new_range_bits << 5); | ||
| 352 | i2c_smbus_write_byte_data(client, REG_FAN_CONF1, status); | ||
| 353 | |||
| 354 | data->fan_multiplier = 8 / new_div; | ||
| 355 | |||
| 356 | /* update fan target if high byte is not disabled */ | ||
| 357 | if ((data->fan_target & 0x1fe0) != 0x1fe0) { | ||
| 358 | u16 new_target = (data->fan_target * old_div) / new_div; | ||
| 359 | data->fan_target = min(new_target, (u16)0x1fff); | ||
| 360 | write_fan_target_to_i2c(client, data->fan_target); | ||
| 361 | } | ||
| 362 | |||
| 363 | /* invalidate data to force re-read from hardware */ | ||
| 364 | data->valid = false; | ||
| 365 | |||
| 366 | mutex_unlock(&data->update_lock); | ||
| 367 | return count; | ||
| 368 | } | ||
| 369 | |||
| 370 | static ssize_t | ||
| 371 | show_fan_target(struct device *dev, struct device_attribute *da, char *buf) | ||
| 372 | { | ||
| 373 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 374 | int rpm = 0; | ||
| 375 | |||
| 376 | /* high byte of 0xff indicates disabled so return 0 */ | ||
| 377 | if ((data->fan_target != 0) && ((data->fan_target & 0x1fe0) != 0x1fe0)) | ||
| 378 | rpm = (FAN_RPM_FACTOR * data->fan_multiplier) | ||
| 379 | / data->fan_target; | ||
| 380 | |||
| 381 | return sprintf(buf, "%d\n", rpm); | ||
| 382 | } | ||
| 383 | |||
| 384 | static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, | ||
| 385 | const char *buf, size_t count) | ||
| 386 | { | ||
| 387 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 388 | struct i2c_client *client = to_i2c_client(dev); | ||
| 389 | long rpm_target; | ||
| 390 | |||
| 391 | int result = strict_strtol(buf, 10, &rpm_target); | ||
| 392 | if (result < 0) | ||
| 393 | return -EINVAL; | ||
| 394 | |||
| 395 | /* Datasheet states 16384 as maximum RPM target (table 3.2) */ | ||
| 396 | if ((rpm_target < 0) || (rpm_target > 16384)) | ||
| 397 | return -EINVAL; | ||
| 398 | |||
| 399 | mutex_lock(&data->update_lock); | ||
| 400 | |||
| 401 | if (rpm_target == 0) | ||
| 402 | data->fan_target = 0x1fff; | ||
| 403 | else | ||
| 404 | data->fan_target = SENSORS_LIMIT( | ||
| 405 | (FAN_RPM_FACTOR * data->fan_multiplier) / rpm_target, | ||
| 406 | 0, 0x1fff); | ||
| 407 | |||
| 408 | write_fan_target_to_i2c(client, data->fan_target); | ||
| 409 | |||
| 410 | mutex_unlock(&data->update_lock); | ||
| 411 | return count; | ||
| 412 | } | ||
| 413 | |||
| 414 | static ssize_t | ||
| 415 | show_fan_fault(struct device *dev, struct device_attribute *da, char *buf) | ||
| 416 | { | ||
| 417 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 418 | bool fault = ((data->fan_tach & 0x1fe0) == 0x1fe0); | ||
| 419 | return sprintf(buf, "%d\n", fault ? 1 : 0); | ||
| 420 | } | ||
| 421 | |||
| 422 | static ssize_t | ||
| 423 | show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf) | ||
| 424 | { | ||
| 425 | struct emc2103_data *data = emc2103_update_device(dev); | ||
| 426 | return sprintf(buf, "%d\n", data->fan_rpm_control ? 3 : 0); | ||
| 427 | } | ||
| 428 | |||
| 429 | static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, | ||
| 430 | const char *buf, size_t count) | ||
| 431 | { | ||
| 432 | struct i2c_client *client = to_i2c_client(dev); | ||
| 433 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
| 434 | long new_value; | ||
| 435 | u8 conf_reg; | ||
| 436 | |||
| 437 | int result = strict_strtol(buf, 10, &new_value); | ||
| 438 | if (result < 0) | ||
| 439 | return -EINVAL; | ||
| 440 | |||
| 441 | mutex_lock(&data->update_lock); | ||
| 442 | switch (new_value) { | ||
| 443 | case 0: | ||
| 444 | data->fan_rpm_control = false; | ||
| 445 | break; | ||
| 446 | case 3: | ||
| 447 | data->fan_rpm_control = true; | ||
| 448 | break; | ||
| 449 | default: | ||
| 450 | mutex_unlock(&data->update_lock); | ||
| 451 | return -EINVAL; | ||
| 452 | } | ||
| 453 | |||
| 454 | read_u8_from_i2c(client, REG_FAN_CONF1, &conf_reg); | ||
| 455 | |||
| 456 | if (data->fan_rpm_control) | ||
| 457 | conf_reg |= 0x80; | ||
| 458 | else | ||
| 459 | conf_reg &= ~0x80; | ||
| 460 | |||
| 461 | i2c_smbus_write_byte_data(client, REG_FAN_CONF1, conf_reg); | ||
| 462 | |||
| 463 | mutex_unlock(&data->update_lock); | ||
| 464 | return count; | ||
| 465 | } | ||
| 466 | |||
| 467 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
| 468 | static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, show_temp_min, | ||
| 469 | set_temp_min, 0); | ||
| 470 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp_max, | ||
| 471 | set_temp_max, 0); | ||
| 472 | static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); | ||
| 473 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_temp_min_alarm, | ||
| 474 | NULL, 0); | ||
| 475 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm, | ||
| 476 | NULL, 0); | ||
| 477 | |||
| 478 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); | ||
| 479 | static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, show_temp_min, | ||
| 480 | set_temp_min, 1); | ||
| 481 | static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max, | ||
| 482 | set_temp_max, 1); | ||
| 483 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); | ||
| 484 | static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm, | ||
| 485 | NULL, 1); | ||
| 486 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm, | ||
| 487 | NULL, 1); | ||
| 488 | |||
| 489 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); | ||
| 490 | static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO | S_IWUSR, show_temp_min, | ||
| 491 | set_temp_min, 2); | ||
| 492 | static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max, | ||
| 493 | set_temp_max, 2); | ||
| 494 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2); | ||
| 495 | static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm, | ||
| 496 | NULL, 2); | ||
| 497 | static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm, | ||
| 498 | NULL, 2); | ||
| 499 | |||
| 500 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); | ||
| 501 | static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO | S_IWUSR, show_temp_min, | ||
| 502 | set_temp_min, 3); | ||
| 503 | static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO | S_IWUSR, show_temp_max, | ||
| 504 | set_temp_max, 3); | ||
| 505 | static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3); | ||
| 506 | static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_temp_min_alarm, | ||
| 507 | NULL, 3); | ||
| 508 | static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_temp_max_alarm, | ||
| 509 | NULL, 3); | ||
| 510 | |||
| 511 | static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL); | ||
| 512 | static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, show_fan_div, set_fan_div); | ||
| 513 | static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_fan_target, | ||
| 514 | set_fan_target); | ||
| 515 | static DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL); | ||
| 516 | |||
| 517 | static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, | ||
| 518 | set_pwm_enable); | ||
| 519 | |||
| 520 | /* sensors present on all models */ | ||
| 521 | static struct attribute *emc2103_attributes[] = { | ||
| 522 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
| 523 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
| 524 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
| 525 | &sensor_dev_attr_temp1_fault.dev_attr.attr, | ||
| 526 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | ||
| 527 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
| 528 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
| 529 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
| 530 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
| 531 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | ||
| 532 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | ||
| 533 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | ||
| 534 | &dev_attr_fan1_input.attr, | ||
| 535 | &dev_attr_fan1_div.attr, | ||
| 536 | &dev_attr_fan1_target.attr, | ||
| 537 | &dev_attr_fan1_fault.attr, | ||
| 538 | &dev_attr_pwm1_enable.attr, | ||
| 539 | NULL | ||
| 540 | }; | ||
| 541 | |||
| 542 | /* extra temperature sensors only present on 2103-2 and 2103-4 */ | ||
| 543 | static struct attribute *emc2103_attributes_temp3[] = { | ||
| 544 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
| 545 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
| 546 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
| 547 | &sensor_dev_attr_temp3_fault.dev_attr.attr, | ||
| 548 | &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, | ||
| 549 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, | ||
| 550 | NULL | ||
| 551 | }; | ||
| 552 | |||
| 553 | /* extra temperature sensors only present on 2103-2 and 2103-4 in APD mode */ | ||
| 554 | static struct attribute *emc2103_attributes_temp4[] = { | ||
| 555 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
| 556 | &sensor_dev_attr_temp4_min.dev_attr.attr, | ||
| 557 | &sensor_dev_attr_temp4_max.dev_attr.attr, | ||
| 558 | &sensor_dev_attr_temp4_fault.dev_attr.attr, | ||
| 559 | &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, | ||
| 560 | &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, | ||
| 561 | NULL | ||
| 562 | }; | ||
| 563 | |||
| 564 | static const struct attribute_group emc2103_group = { | ||
| 565 | .attrs = emc2103_attributes, | ||
| 566 | }; | ||
| 567 | |||
| 568 | static const struct attribute_group emc2103_temp3_group = { | ||
| 569 | .attrs = emc2103_attributes_temp3, | ||
| 570 | }; | ||
| 571 | |||
| 572 | static const struct attribute_group emc2103_temp4_group = { | ||
| 573 | .attrs = emc2103_attributes_temp4, | ||
| 574 | }; | ||
| 575 | |||
| 576 | static int | ||
| 577 | emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
| 578 | { | ||
| 579 | struct emc2103_data *data; | ||
| 580 | int status; | ||
| 581 | |||
| 582 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 583 | return -EIO; | ||
| 584 | |||
| 585 | data = kzalloc(sizeof(struct emc2103_data), GFP_KERNEL); | ||
| 586 | if (!data) | ||
| 587 | return -ENOMEM; | ||
| 588 | |||
| 589 | i2c_set_clientdata(client, data); | ||
| 590 | mutex_init(&data->update_lock); | ||
| 591 | |||
| 592 | /* 2103-2 and 2103-4 have 3 external diodes, 2103-1 has 1 */ | ||
| 593 | status = i2c_smbus_read_byte_data(client, REG_PRODUCT_ID); | ||
| 594 | if (status == 0x24) { | ||
| 595 | /* 2103-1 only has 1 external diode */ | ||
| 596 | data->temp_count = 2; | ||
| 597 | } else { | ||
| 598 | /* 2103-2 and 2103-4 have 3 or 4 external diodes */ | ||
| 599 | status = i2c_smbus_read_byte_data(client, REG_CONF1); | ||
| 600 | if (status < 0) { | ||
| 601 | dev_dbg(&client->dev, "reg 0x%02x, err %d\n", REG_CONF1, | ||
| 602 | status); | ||
| 603 | goto exit_free; | ||
| 604 | } | ||
| 605 | |||
| 606 | /* detect current state of hardware */ | ||
| 607 | data->temp_count = (status & 0x01) ? 4 : 3; | ||
| 608 | |||
| 609 | /* force APD state if module parameter is set */ | ||
| 610 | if (apd == 0) { | ||
| 611 | /* force APD mode off */ | ||
| 612 | data->temp_count = 3; | ||
| 613 | status &= ~(0x01); | ||
| 614 | i2c_smbus_write_byte_data(client, REG_CONF1, status); | ||
| 615 | } else if (apd == 1) { | ||
| 616 | /* force APD mode on */ | ||
| 617 | data->temp_count = 4; | ||
| 618 | status |= 0x01; | ||
| 619 | i2c_smbus_write_byte_data(client, REG_CONF1, status); | ||
| 620 | } | ||
| 621 | } | ||
| 622 | |||
| 623 | /* Register sysfs hooks */ | ||
| 624 | status = sysfs_create_group(&client->dev.kobj, &emc2103_group); | ||
| 625 | if (status) | ||
| 626 | goto exit_free; | ||
| 627 | |||
| 628 | if (data->temp_count >= 3) { | ||
| 629 | status = sysfs_create_group(&client->dev.kobj, | ||
| 630 | &emc2103_temp3_group); | ||
| 631 | if (status) | ||
| 632 | goto exit_remove; | ||
| 633 | } | ||
| 634 | |||
| 635 | if (data->temp_count == 4) { | ||
| 636 | status = sysfs_create_group(&client->dev.kobj, | ||
| 637 | &emc2103_temp4_group); | ||
| 638 | if (status) | ||
| 639 | goto exit_remove_temp3; | ||
| 640 | } | ||
| 641 | |||
| 642 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
| 643 | if (IS_ERR(data->hwmon_dev)) { | ||
| 644 | status = PTR_ERR(data->hwmon_dev); | ||
| 645 | goto exit_remove_temp4; | ||
| 646 | } | ||
| 647 | |||
| 648 | dev_info(&client->dev, "%s: sensor '%s'\n", | ||
| 649 | dev_name(data->hwmon_dev), client->name); | ||
| 650 | |||
| 651 | return 0; | ||
| 652 | |||
| 653 | exit_remove_temp4: | ||
| 654 | if (data->temp_count == 4) | ||
| 655 | sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group); | ||
| 656 | exit_remove_temp3: | ||
| 657 | if (data->temp_count >= 3) | ||
| 658 | sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); | ||
| 659 | exit_remove: | ||
| 660 | sysfs_remove_group(&client->dev.kobj, &emc2103_group); | ||
| 661 | exit_free: | ||
| 662 | kfree(data); | ||
| 663 | return status; | ||
| 664 | } | ||
| 665 | |||
| 666 | static int emc2103_remove(struct i2c_client *client) | ||
| 667 | { | ||
| 668 | struct emc2103_data *data = i2c_get_clientdata(client); | ||
| 669 | |||
| 670 | hwmon_device_unregister(data->hwmon_dev); | ||
| 671 | |||
| 672 | if (data->temp_count == 4) | ||
| 673 | sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group); | ||
| 674 | |||
| 675 | if (data->temp_count >= 3) | ||
| 676 | sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); | ||
| 677 | |||
| 678 | sysfs_remove_group(&client->dev.kobj, &emc2103_group); | ||
| 679 | |||
| 680 | kfree(data); | ||
| 681 | return 0; | ||
| 682 | } | ||
| 683 | |||
| 684 | static const struct i2c_device_id emc2103_ids[] = { | ||
| 685 | { "emc2103", 0, }, | ||
| 686 | { /* LIST END */ } | ||
| 687 | }; | ||
| 688 | MODULE_DEVICE_TABLE(i2c, emc2103_ids); | ||
| 689 | |||
| 690 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
| 691 | static int | ||
| 692 | emc2103_detect(struct i2c_client *new_client, struct i2c_board_info *info) | ||
| 693 | { | ||
| 694 | struct i2c_adapter *adapter = new_client->adapter; | ||
| 695 | int manufacturer, product; | ||
| 696 | |||
| 697 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 698 | return -ENODEV; | ||
| 699 | |||
| 700 | manufacturer = i2c_smbus_read_byte_data(new_client, REG_MFG_ID); | ||
| 701 | if (manufacturer != 0x5D) | ||
| 702 | return -ENODEV; | ||
| 703 | |||
| 704 | product = i2c_smbus_read_byte_data(new_client, REG_PRODUCT_ID); | ||
| 705 | if ((product != 0x24) && (product != 0x26)) | ||
| 706 | return -ENODEV; | ||
| 707 | |||
| 708 | strlcpy(info->type, "emc2103", I2C_NAME_SIZE); | ||
| 709 | |||
| 710 | return 0; | ||
| 711 | } | ||
| 712 | |||
| 713 | static struct i2c_driver emc2103_driver = { | ||
| 714 | .class = I2C_CLASS_HWMON, | ||
| 715 | .driver = { | ||
| 716 | .name = "emc2103", | ||
| 717 | }, | ||
| 718 | .probe = emc2103_probe, | ||
| 719 | .remove = emc2103_remove, | ||
| 720 | .id_table = emc2103_ids, | ||
| 721 | .detect = emc2103_detect, | ||
| 722 | .address_list = normal_i2c, | ||
| 723 | }; | ||
| 724 | |||
| 725 | static int __init sensors_emc2103_init(void) | ||
| 726 | { | ||
| 727 | return i2c_add_driver(&emc2103_driver); | ||
| 728 | } | ||
| 729 | |||
| 730 | static void __exit sensors_emc2103_exit(void) | ||
| 731 | { | ||
| 732 | i2c_del_driver(&emc2103_driver); | ||
| 733 | } | ||
| 734 | |||
| 735 | MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>"); | ||
| 736 | MODULE_DESCRIPTION("SMSC EMC2103 hwmon driver"); | ||
| 737 | MODULE_LICENSE("GPL"); | ||
| 738 | |||
| 739 | module_init(sensors_emc2103_init); | ||
| 740 | module_exit(sensors_emc2103_exit); | ||
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 25763d2223b6..f7701295937d 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
| @@ -259,6 +259,7 @@ struct it87_sio_data { | |||
| 259 | u8 revision; | 259 | u8 revision; |
| 260 | u8 vid_value; | 260 | u8 vid_value; |
| 261 | u8 beep_pin; | 261 | u8 beep_pin; |
| 262 | u8 internal; /* Internal sensors can be labeled */ | ||
| 262 | /* Features skipped based on config or DMI */ | 263 | /* Features skipped based on config or DMI */ |
| 263 | u8 skip_vid; | 264 | u8 skip_vid; |
| 264 | u8 skip_fan; | 265 | u8 skip_fan; |
| @@ -1194,6 +1195,22 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, | |||
| 1194 | } | 1195 | } |
| 1195 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); | 1196 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); |
| 1196 | 1197 | ||
| 1198 | static ssize_t show_label(struct device *dev, struct device_attribute *attr, | ||
| 1199 | char *buf) | ||
| 1200 | { | ||
| 1201 | static const char *labels[] = { | ||
| 1202 | "+5V", | ||
| 1203 | "5VSB", | ||
| 1204 | "Vbat", | ||
| 1205 | }; | ||
| 1206 | int nr = to_sensor_dev_attr(attr)->index; | ||
| 1207 | |||
| 1208 | return sprintf(buf, "%s\n", labels[nr]); | ||
| 1209 | } | ||
| 1210 | static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0); | ||
| 1211 | static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1); | ||
| 1212 | static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2); | ||
| 1213 | |||
| 1197 | static ssize_t show_name(struct device *dev, struct device_attribute | 1214 | static ssize_t show_name(struct device *dev, struct device_attribute |
| 1198 | *devattr, char *buf) | 1215 | *devattr, char *buf) |
| 1199 | { | 1216 | { |
| @@ -1434,6 +1451,17 @@ static const struct attribute_group it87_group_vid = { | |||
| 1434 | .attrs = it87_attributes_vid, | 1451 | .attrs = it87_attributes_vid, |
| 1435 | }; | 1452 | }; |
| 1436 | 1453 | ||
| 1454 | static struct attribute *it87_attributes_label[] = { | ||
| 1455 | &sensor_dev_attr_in3_label.dev_attr.attr, | ||
| 1456 | &sensor_dev_attr_in7_label.dev_attr.attr, | ||
| 1457 | &sensor_dev_attr_in8_label.dev_attr.attr, | ||
| 1458 | NULL | ||
| 1459 | }; | ||
| 1460 | |||
| 1461 | static const struct attribute_group it87_group_label = { | ||
| 1462 | .attrs = it87_attributes_vid, | ||
| 1463 | }; | ||
| 1464 | |||
| 1437 | /* SuperIO detection - will change isa_address if a chip is found */ | 1465 | /* SuperIO detection - will change isa_address if a chip is found */ |
| 1438 | static int __init it87_find(unsigned short *address, | 1466 | static int __init it87_find(unsigned short *address, |
| 1439 | struct it87_sio_data *sio_data) | 1467 | struct it87_sio_data *sio_data) |
| @@ -1487,6 +1515,9 @@ static int __init it87_find(unsigned short *address, | |||
| 1487 | pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", | 1515 | pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", |
| 1488 | chip_type, *address, sio_data->revision); | 1516 | chip_type, *address, sio_data->revision); |
| 1489 | 1517 | ||
| 1518 | /* in8 (Vbat) is always internal */ | ||
| 1519 | sio_data->internal = (1 << 2); | ||
| 1520 | |||
| 1490 | /* Read GPIO config and VID value from LDN 7 (GPIO) */ | 1521 | /* Read GPIO config and VID value from LDN 7 (GPIO) */ |
| 1491 | if (sio_data->type == it87) { | 1522 | if (sio_data->type == it87) { |
| 1492 | /* The IT8705F doesn't have VID pins at all */ | 1523 | /* The IT8705F doesn't have VID pins at all */ |
| @@ -1540,9 +1571,9 @@ static int __init it87_find(unsigned short *address, | |||
| 1540 | pr_notice("it87: Routing internal VCCH to in7\n"); | 1571 | pr_notice("it87: Routing internal VCCH to in7\n"); |
| 1541 | } | 1572 | } |
| 1542 | if (reg & (1 << 0)) | 1573 | if (reg & (1 << 0)) |
| 1543 | pr_info("it87: in3 is VCC (+5V)\n"); | 1574 | sio_data->internal |= (1 << 0); |
| 1544 | if (reg & (1 << 1)) | 1575 | if (reg & (1 << 1)) |
| 1545 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); | 1576 | sio_data->internal |= (1 << 1); |
| 1546 | 1577 | ||
| 1547 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | 1578 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; |
| 1548 | } | 1579 | } |
| @@ -1600,6 +1631,7 @@ static void it87_remove_files(struct device *dev) | |||
| 1600 | } | 1631 | } |
| 1601 | if (!sio_data->skip_vid) | 1632 | if (!sio_data->skip_vid) |
| 1602 | sysfs_remove_group(&dev->kobj, &it87_group_vid); | 1633 | sysfs_remove_group(&dev->kobj, &it87_group_vid); |
| 1634 | sysfs_remove_group(&dev->kobj, &it87_group_label); | ||
| 1603 | } | 1635 | } |
| 1604 | 1636 | ||
| 1605 | static int __devinit it87_probe(struct platform_device *pdev) | 1637 | static int __devinit it87_probe(struct platform_device *pdev) |
| @@ -1725,6 +1757,16 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
| 1725 | goto ERROR4; | 1757 | goto ERROR4; |
| 1726 | } | 1758 | } |
| 1727 | 1759 | ||
| 1760 | /* Export labels for internal sensors */ | ||
| 1761 | for (i = 0; i < 3; i++) { | ||
| 1762 | if (!(sio_data->internal & (1 << i))) | ||
| 1763 | continue; | ||
| 1764 | err = sysfs_create_file(&dev->kobj, | ||
| 1765 | it87_attributes_label[i]); | ||
| 1766 | if (err) | ||
| 1767 | goto ERROR4; | ||
| 1768 | } | ||
| 1769 | |||
| 1728 | data->hwmon_dev = hwmon_device_register(dev); | 1770 | data->hwmon_dev = hwmon_device_register(dev); |
| 1729 | if (IS_ERR(data->hwmon_dev)) { | 1771 | if (IS_ERR(data->hwmon_dev)) { |
| 1730 | err = PTR_ERR(data->hwmon_dev); | 1772 | err = PTR_ERR(data->hwmon_dev); |
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index 8bdf80d91598..b9bb3e0ca530 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c | |||
| @@ -252,12 +252,13 @@ static int __devinit k8temp_probe(struct pci_dev *pdev, | |||
| 252 | &sensor_dev_attr_temp3_input.dev_attr); | 252 | &sensor_dev_attr_temp3_input.dev_attr); |
| 253 | if (err) | 253 | if (err) |
| 254 | goto exit_remove; | 254 | goto exit_remove; |
| 255 | if (data->sensorsp & SEL_PLACE) | 255 | if (data->sensorsp & SEL_PLACE) { |
| 256 | err = device_create_file(&pdev->dev, | 256 | err = device_create_file(&pdev->dev, |
| 257 | &sensor_dev_attr_temp4_input. | 257 | &sensor_dev_attr_temp4_input. |
| 258 | dev_attr); | 258 | dev_attr); |
| 259 | if (err) | 259 | if (err) |
| 260 | goto exit_remove; | 260 | goto exit_remove; |
| 261 | } | ||
| 261 | } | 262 | } |
| 262 | 263 | ||
| 263 | err = device_create_file(&pdev->dev, &dev_attr_name); | 264 | err = device_create_file(&pdev->dev, &dev_attr_name); |
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 393f354f92a4..ab5b87a81677 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c | |||
| @@ -280,10 +280,49 @@ static int lm75_detect(struct i2c_client *new_client, | |||
| 280 | return 0; | 280 | return 0; |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | #ifdef CONFIG_PM | ||
| 284 | static int lm75_suspend(struct device *dev) | ||
| 285 | { | ||
| 286 | int status; | ||
| 287 | struct i2c_client *client = to_i2c_client(dev); | ||
| 288 | status = lm75_read_value(client, LM75_REG_CONF); | ||
| 289 | if (status < 0) { | ||
| 290 | dev_dbg(&client->dev, "Can't read config? %d\n", status); | ||
| 291 | return status; | ||
| 292 | } | ||
| 293 | status = status | LM75_SHUTDOWN; | ||
| 294 | lm75_write_value(client, LM75_REG_CONF, status); | ||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | |||
| 298 | static int lm75_resume(struct device *dev) | ||
| 299 | { | ||
| 300 | int status; | ||
| 301 | struct i2c_client *client = to_i2c_client(dev); | ||
| 302 | status = lm75_read_value(client, LM75_REG_CONF); | ||
| 303 | if (status < 0) { | ||
| 304 | dev_dbg(&client->dev, "Can't read config? %d\n", status); | ||
| 305 | return status; | ||
| 306 | } | ||
| 307 | status = status & ~LM75_SHUTDOWN; | ||
| 308 | lm75_write_value(client, LM75_REG_CONF, status); | ||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | static const struct dev_pm_ops lm75_dev_pm_ops = { | ||
| 313 | .suspend = lm75_suspend, | ||
| 314 | .resume = lm75_resume, | ||
| 315 | }; | ||
| 316 | #define LM75_DEV_PM_OPS (&lm75_dev_pm_ops) | ||
| 317 | #else | ||
| 318 | #define LM75_DEV_PM_OPS NULL | ||
| 319 | #endif /* CONFIG_PM */ | ||
| 320 | |||
| 283 | static struct i2c_driver lm75_driver = { | 321 | static struct i2c_driver lm75_driver = { |
| 284 | .class = I2C_CLASS_HWMON, | 322 | .class = I2C_CLASS_HWMON, |
| 285 | .driver = { | 323 | .driver = { |
| 286 | .name = "lm75", | 324 | .name = "lm75", |
| 325 | .pm = LM75_DEV_PM_OPS, | ||
| 287 | }, | 326 | }, |
| 288 | .probe = lm75_probe, | 327 | .probe = lm75_probe, |
| 289 | .remove = lm75_remove, | 328 | .remove = lm75_remove, |
diff --git a/drivers/hwmon/lm75.h b/drivers/hwmon/lm75.h index 7c93454bb4e3..e547a3eb4de3 100644 --- a/drivers/hwmon/lm75.h +++ b/drivers/hwmon/lm75.h | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | /* straight from the datasheet */ | 30 | /* straight from the datasheet */ |
| 31 | #define LM75_TEMP_MIN (-55000) | 31 | #define LM75_TEMP_MIN (-55000) |
| 32 | #define LM75_TEMP_MAX 125000 | 32 | #define LM75_TEMP_MAX 125000 |
| 33 | #define LM75_SHUTDOWN 0x01 | ||
| 33 | 34 | ||
| 34 | /* TEMP: 0.001C/bit (-55C to +125C) | 35 | /* TEMP: 0.001C/bit (-55C to +125C) |
| 35 | REG: (0.5C/bit, two's complement) << 7 */ | 36 | REG: (0.5C/bit, two's complement) << 7 */ |
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c index 21d201befc2c..659308329308 100644 --- a/drivers/hwmon/ltc4245.c +++ b/drivers/hwmon/ltc4245.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
| 22 | #include <linux/hwmon.h> | 22 | #include <linux/hwmon.h> |
| 23 | #include <linux/hwmon-sysfs.h> | 23 | #include <linux/hwmon-sysfs.h> |
| 24 | #include <linux/i2c/ltc4245.h> | ||
| 24 | 25 | ||
| 25 | /* Here are names of the chip's registers (a.k.a. commands) */ | 26 | /* Here are names of the chip's registers (a.k.a. commands) */ |
| 26 | enum ltc4245_cmd { | 27 | enum ltc4245_cmd { |
| @@ -60,8 +61,72 @@ struct ltc4245_data { | |||
| 60 | 61 | ||
| 61 | /* Voltage registers */ | 62 | /* Voltage registers */ |
| 62 | u8 vregs[0x0d]; | 63 | u8 vregs[0x0d]; |
| 64 | |||
| 65 | /* GPIO ADC registers */ | ||
| 66 | bool use_extra_gpios; | ||
| 67 | int gpios[3]; | ||
| 63 | }; | 68 | }; |
| 64 | 69 | ||
| 70 | /* | ||
| 71 | * Update the readings from the GPIO pins. If the driver has been configured to | ||
| 72 | * sample all GPIO's as analog voltages, a round-robin sampling method is used. | ||
| 73 | * Otherwise, only the configured GPIO pin is sampled. | ||
| 74 | * | ||
| 75 | * LOCKING: must hold data->update_lock | ||
| 76 | */ | ||
| 77 | static void ltc4245_update_gpios(struct device *dev) | ||
| 78 | { | ||
| 79 | struct i2c_client *client = to_i2c_client(dev); | ||
| 80 | struct ltc4245_data *data = i2c_get_clientdata(client); | ||
| 81 | u8 gpio_curr, gpio_next, gpio_reg; | ||
| 82 | int i; | ||
| 83 | |||
| 84 | /* no extra gpio support, we're basically done */ | ||
| 85 | if (!data->use_extra_gpios) { | ||
| 86 | data->gpios[0] = data->vregs[LTC4245_GPIOADC - 0x10]; | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* | ||
| 91 | * If the last reading was too long ago, then we mark all old GPIO | ||
| 92 | * readings as stale by setting them to -EAGAIN | ||
| 93 | */ | ||
| 94 | if (time_after(jiffies, data->last_updated + 5 * HZ)) { | ||
| 95 | dev_dbg(&client->dev, "Marking GPIOs invalid\n"); | ||
| 96 | for (i = 0; i < ARRAY_SIZE(data->gpios); i++) | ||
| 97 | data->gpios[i] = -EAGAIN; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* | ||
| 101 | * Get the current GPIO pin | ||
| 102 | * | ||
| 103 | * The datasheet calls these GPIO[1-3], but we'll calculate the zero | ||
| 104 | * based array index instead, and call them GPIO[0-2]. This is much | ||
| 105 | * easier to think about. | ||
| 106 | */ | ||
| 107 | gpio_curr = (data->cregs[LTC4245_GPIO] & 0xc0) >> 6; | ||
| 108 | if (gpio_curr > 0) | ||
| 109 | gpio_curr -= 1; | ||
| 110 | |||
| 111 | /* Read the GPIO voltage from the GPIOADC register */ | ||
| 112 | data->gpios[gpio_curr] = data->vregs[LTC4245_GPIOADC - 0x10]; | ||
| 113 | |||
| 114 | /* Find the next GPIO pin to read */ | ||
| 115 | gpio_next = (gpio_curr + 1) % ARRAY_SIZE(data->gpios); | ||
| 116 | |||
| 117 | /* | ||
| 118 | * Calculate the correct setting for the GPIO register so it will | ||
| 119 | * sample the next GPIO pin | ||
| 120 | */ | ||
| 121 | gpio_reg = (data->cregs[LTC4245_GPIO] & 0x3f) | ((gpio_next + 1) << 6); | ||
| 122 | |||
| 123 | /* Update the GPIO register */ | ||
| 124 | i2c_smbus_write_byte_data(client, LTC4245_GPIO, gpio_reg); | ||
| 125 | |||
| 126 | /* Update saved data */ | ||
| 127 | data->cregs[LTC4245_GPIO] = gpio_reg; | ||
| 128 | } | ||
| 129 | |||
| 65 | static struct ltc4245_data *ltc4245_update_device(struct device *dev) | 130 | static struct ltc4245_data *ltc4245_update_device(struct device *dev) |
| 66 | { | 131 | { |
| 67 | struct i2c_client *client = to_i2c_client(dev); | 132 | struct i2c_client *client = to_i2c_client(dev); |
| @@ -93,6 +158,9 @@ static struct ltc4245_data *ltc4245_update_device(struct device *dev) | |||
| 93 | data->vregs[i] = val; | 158 | data->vregs[i] = val; |
| 94 | } | 159 | } |
| 95 | 160 | ||
| 161 | /* Update GPIO readings */ | ||
| 162 | ltc4245_update_gpios(dev); | ||
| 163 | |||
| 96 | data->last_updated = jiffies; | 164 | data->last_updated = jiffies; |
| 97 | data->valid = 1; | 165 | data->valid = 1; |
| 98 | } | 166 | } |
| @@ -233,6 +301,22 @@ static ssize_t ltc4245_show_alarm(struct device *dev, | |||
| 233 | return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0); | 301 | return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0); |
| 234 | } | 302 | } |
| 235 | 303 | ||
| 304 | static ssize_t ltc4245_show_gpio(struct device *dev, | ||
| 305 | struct device_attribute *da, | ||
| 306 | char *buf) | ||
| 307 | { | ||
| 308 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
| 309 | struct ltc4245_data *data = ltc4245_update_device(dev); | ||
| 310 | int val = data->gpios[attr->index]; | ||
| 311 | |||
| 312 | /* handle stale GPIO's */ | ||
| 313 | if (val < 0) | ||
| 314 | return val; | ||
| 315 | |||
| 316 | /* Convert to millivolts and print */ | ||
| 317 | return snprintf(buf, PAGE_SIZE, "%u\n", val * 10); | ||
| 318 | } | ||
| 319 | |||
| 236 | /* These macros are used below in constructing device attribute objects | 320 | /* These macros are used below in constructing device attribute objects |
| 237 | * for use with sysfs_create_group() to make a sysfs device file | 321 | * for use with sysfs_create_group() to make a sysfs device file |
| 238 | * for each register. | 322 | * for each register. |
| @@ -254,6 +338,10 @@ static ssize_t ltc4245_show_alarm(struct device *dev, | |||
| 254 | static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \ | 338 | static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \ |
| 255 | ltc4245_show_alarm, NULL, (mask), reg) | 339 | ltc4245_show_alarm, NULL, (mask), reg) |
| 256 | 340 | ||
| 341 | #define LTC4245_GPIO_VOLTAGE(name, gpio_num) \ | ||
| 342 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ | ||
| 343 | ltc4245_show_gpio, NULL, gpio_num) | ||
| 344 | |||
| 257 | /* Construct a sensor_device_attribute structure for each register */ | 345 | /* Construct a sensor_device_attribute structure for each register */ |
| 258 | 346 | ||
| 259 | /* Input voltages */ | 347 | /* Input voltages */ |
| @@ -293,7 +381,9 @@ LTC4245_ALARM(in7_min_alarm, (1 << 2), LTC4245_FAULT2); | |||
| 293 | LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2); | 381 | LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2); |
| 294 | 382 | ||
| 295 | /* GPIO voltages */ | 383 | /* GPIO voltages */ |
| 296 | LTC4245_VOLTAGE(in9_input, LTC4245_GPIOADC); | 384 | LTC4245_GPIO_VOLTAGE(in9_input, 0); |
| 385 | LTC4245_GPIO_VOLTAGE(in10_input, 1); | ||
| 386 | LTC4245_GPIO_VOLTAGE(in11_input, 2); | ||
| 297 | 387 | ||
| 298 | /* Power Consumption (virtual) */ | 388 | /* Power Consumption (virtual) */ |
| 299 | LTC4245_POWER(power1_input, LTC4245_12VSENSE); | 389 | LTC4245_POWER(power1_input, LTC4245_12VSENSE); |
| @@ -304,7 +394,7 @@ LTC4245_POWER(power4_input, LTC4245_VEESENSE); | |||
| 304 | /* Finally, construct an array of pointers to members of the above objects, | 394 | /* Finally, construct an array of pointers to members of the above objects, |
| 305 | * as required for sysfs_create_group() | 395 | * as required for sysfs_create_group() |
| 306 | */ | 396 | */ |
| 307 | static struct attribute *ltc4245_attributes[] = { | 397 | static struct attribute *ltc4245_std_attributes[] = { |
| 308 | &sensor_dev_attr_in1_input.dev_attr.attr, | 398 | &sensor_dev_attr_in1_input.dev_attr.attr, |
| 309 | &sensor_dev_attr_in2_input.dev_attr.attr, | 399 | &sensor_dev_attr_in2_input.dev_attr.attr, |
| 310 | &sensor_dev_attr_in3_input.dev_attr.attr, | 400 | &sensor_dev_attr_in3_input.dev_attr.attr, |
| @@ -345,10 +435,77 @@ static struct attribute *ltc4245_attributes[] = { | |||
| 345 | NULL, | 435 | NULL, |
| 346 | }; | 436 | }; |
| 347 | 437 | ||
| 348 | static const struct attribute_group ltc4245_group = { | 438 | static struct attribute *ltc4245_gpio_attributes[] = { |
| 349 | .attrs = ltc4245_attributes, | 439 | &sensor_dev_attr_in10_input.dev_attr.attr, |
| 440 | &sensor_dev_attr_in11_input.dev_attr.attr, | ||
| 441 | NULL, | ||
| 442 | }; | ||
| 443 | |||
| 444 | static const struct attribute_group ltc4245_std_group = { | ||
| 445 | .attrs = ltc4245_std_attributes, | ||
| 446 | }; | ||
| 447 | |||
| 448 | static const struct attribute_group ltc4245_gpio_group = { | ||
| 449 | .attrs = ltc4245_gpio_attributes, | ||
| 350 | }; | 450 | }; |
| 351 | 451 | ||
| 452 | static int ltc4245_sysfs_create_groups(struct i2c_client *client) | ||
| 453 | { | ||
| 454 | struct ltc4245_data *data = i2c_get_clientdata(client); | ||
| 455 | struct device *dev = &client->dev; | ||
| 456 | int ret; | ||
| 457 | |||
| 458 | /* register the standard sysfs attributes */ | ||
| 459 | ret = sysfs_create_group(&dev->kobj, <c4245_std_group); | ||
| 460 | if (ret) { | ||
| 461 | dev_err(dev, "unable to register standard attributes\n"); | ||
| 462 | return ret; | ||
| 463 | } | ||
| 464 | |||
| 465 | /* if we're using the extra gpio support, register it's attributes */ | ||
| 466 | if (data->use_extra_gpios) { | ||
| 467 | ret = sysfs_create_group(&dev->kobj, <c4245_gpio_group); | ||
| 468 | if (ret) { | ||
| 469 | dev_err(dev, "unable to register gpio attributes\n"); | ||
| 470 | sysfs_remove_group(&dev->kobj, <c4245_std_group); | ||
| 471 | return ret; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | |||
| 475 | return 0; | ||
| 476 | } | ||
| 477 | |||
| 478 | static void ltc4245_sysfs_remove_groups(struct i2c_client *client) | ||
| 479 | { | ||
| 480 | struct ltc4245_data *data = i2c_get_clientdata(client); | ||
| 481 | struct device *dev = &client->dev; | ||
| 482 | |||
| 483 | if (data->use_extra_gpios) | ||
| 484 | sysfs_remove_group(&dev->kobj, <c4245_gpio_group); | ||
| 485 | |||
| 486 | sysfs_remove_group(&dev->kobj, <c4245_std_group); | ||
| 487 | } | ||
| 488 | |||
| 489 | static bool ltc4245_use_extra_gpios(struct i2c_client *client) | ||
| 490 | { | ||
| 491 | struct ltc4245_platform_data *pdata = dev_get_platdata(&client->dev); | ||
| 492 | #ifdef CONFIG_OF | ||
| 493 | struct device_node *np = client->dev.of_node; | ||
| 494 | #endif | ||
| 495 | |||
| 496 | /* prefer platform data */ | ||
| 497 | if (pdata) | ||
| 498 | return pdata->use_extra_gpios; | ||
| 499 | |||
| 500 | #ifdef CONFIG_OF | ||
| 501 | /* fallback on OF */ | ||
| 502 | if (of_find_property(np, "ltc4245,use-extra-gpios", NULL)) | ||
| 503 | return true; | ||
| 504 | #endif | ||
| 505 | |||
| 506 | return false; | ||
| 507 | } | ||
| 508 | |||
| 352 | static int ltc4245_probe(struct i2c_client *client, | 509 | static int ltc4245_probe(struct i2c_client *client, |
| 353 | const struct i2c_device_id *id) | 510 | const struct i2c_device_id *id) |
| 354 | { | 511 | { |
| @@ -367,15 +524,16 @@ static int ltc4245_probe(struct i2c_client *client, | |||
| 367 | 524 | ||
| 368 | i2c_set_clientdata(client, data); | 525 | i2c_set_clientdata(client, data); |
| 369 | mutex_init(&data->update_lock); | 526 | mutex_init(&data->update_lock); |
| 527 | data->use_extra_gpios = ltc4245_use_extra_gpios(client); | ||
| 370 | 528 | ||
| 371 | /* Initialize the LTC4245 chip */ | 529 | /* Initialize the LTC4245 chip */ |
| 372 | i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00); | 530 | i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00); |
| 373 | i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00); | 531 | i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00); |
| 374 | 532 | ||
| 375 | /* Register sysfs hooks */ | 533 | /* Register sysfs hooks */ |
| 376 | ret = sysfs_create_group(&client->dev.kobj, <c4245_group); | 534 | ret = ltc4245_sysfs_create_groups(client); |
| 377 | if (ret) | 535 | if (ret) |
| 378 | goto out_sysfs_create_group; | 536 | goto out_sysfs_create_groups; |
| 379 | 537 | ||
| 380 | data->hwmon_dev = hwmon_device_register(&client->dev); | 538 | data->hwmon_dev = hwmon_device_register(&client->dev); |
| 381 | if (IS_ERR(data->hwmon_dev)) { | 539 | if (IS_ERR(data->hwmon_dev)) { |
| @@ -386,8 +544,8 @@ static int ltc4245_probe(struct i2c_client *client, | |||
| 386 | return 0; | 544 | return 0; |
| 387 | 545 | ||
| 388 | out_hwmon_device_register: | 546 | out_hwmon_device_register: |
| 389 | sysfs_remove_group(&client->dev.kobj, <c4245_group); | 547 | ltc4245_sysfs_remove_groups(client); |
| 390 | out_sysfs_create_group: | 548 | out_sysfs_create_groups: |
| 391 | kfree(data); | 549 | kfree(data); |
| 392 | out_kzalloc: | 550 | out_kzalloc: |
| 393 | return ret; | 551 | return ret; |
| @@ -398,8 +556,7 @@ static int ltc4245_remove(struct i2c_client *client) | |||
| 398 | struct ltc4245_data *data = i2c_get_clientdata(client); | 556 | struct ltc4245_data *data = i2c_get_clientdata(client); |
| 399 | 557 | ||
| 400 | hwmon_device_unregister(data->hwmon_dev); | 558 | hwmon_device_unregister(data->hwmon_dev); |
| 401 | sysfs_remove_group(&client->dev.kobj, <c4245_group); | 559 | ltc4245_sysfs_remove_groups(client); |
| 402 | |||
| 403 | kfree(data); | 560 | kfree(data); |
| 404 | 561 | ||
| 405 | return 0; | 562 | return 0; |
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 4a64b85d4ec9..68e69a49633c 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c | |||
| @@ -1610,11 +1610,8 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) | |||
| 1610 | 1610 | ||
| 1611 | static int __init pc87360_device_add(unsigned short address) | 1611 | static int __init pc87360_device_add(unsigned short address) |
| 1612 | { | 1612 | { |
| 1613 | struct resource res = { | 1613 | struct resource res[3]; |
| 1614 | .name = "pc87360", | 1614 | int err, i, res_count; |
| 1615 | .flags = IORESOURCE_IO, | ||
| 1616 | }; | ||
| 1617 | int err, i; | ||
| 1618 | 1615 | ||
| 1619 | pdev = platform_device_alloc("pc87360", address); | 1616 | pdev = platform_device_alloc("pc87360", address); |
| 1620 | if (!pdev) { | 1617 | if (!pdev) { |
| @@ -1623,22 +1620,28 @@ static int __init pc87360_device_add(unsigned short address) | |||
| 1623 | goto exit; | 1620 | goto exit; |
| 1624 | } | 1621 | } |
| 1625 | 1622 | ||
| 1623 | memset(res, 0, 3 * sizeof(struct resource)); | ||
| 1624 | res_count = 0; | ||
| 1626 | for (i = 0; i < 3; i++) { | 1625 | for (i = 0; i < 3; i++) { |
| 1627 | if (!extra_isa[i]) | 1626 | if (!extra_isa[i]) |
| 1628 | continue; | 1627 | continue; |
| 1629 | res.start = extra_isa[i]; | 1628 | res[res_count].start = extra_isa[i]; |
| 1630 | res.end = extra_isa[i] + PC87360_EXTENT - 1; | 1629 | res[res_count].end = extra_isa[i] + PC87360_EXTENT - 1; |
| 1630 | res[res_count].name = "pc87360", | ||
| 1631 | res[res_count].flags = IORESOURCE_IO, | ||
| 1631 | 1632 | ||
| 1632 | err = acpi_check_resource_conflict(&res); | 1633 | err = acpi_check_resource_conflict(&res[res_count]); |
| 1633 | if (err) | 1634 | if (err) |
| 1634 | goto exit_device_put; | 1635 | goto exit_device_put; |
| 1635 | 1636 | ||
| 1636 | err = platform_device_add_resources(pdev, &res, 1); | 1637 | res_count++; |
| 1637 | if (err) { | 1638 | } |
| 1638 | printk(KERN_ERR "pc87360: Device resource[%d] " | 1639 | |
| 1639 | "addition failed (%d)\n", i, err); | 1640 | err = platform_device_add_resources(pdev, res, res_count); |
| 1640 | goto exit_device_put; | 1641 | if (err) { |
| 1641 | } | 1642 | printk(KERN_ERR "pc87360: Device resources addition failed " |
| 1643 | "(%d)\n", err); | ||
| 1644 | goto exit_device_put; | ||
| 1642 | } | 1645 | } |
| 1643 | 1646 | ||
| 1644 | err = platform_device_add(pdev); | 1647 | err = platform_device_add(pdev); |
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index 3170b26d2443..9ec4daaf6ca6 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * pc87427.c - hardware monitoring driver for the | 2 | * pc87427.c - hardware monitoring driver for the |
| 3 | * National Semiconductor PC87427 Super-I/O chip | 3 | * National Semiconductor PC87427 Super-I/O chip |
| 4 | * Copyright (C) 2006 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2006, 2008, 2010 Jean Delvare <khali@linux-fr.org> |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
| @@ -15,10 +15,11 @@ | |||
| 15 | * Supports the following chips: | 15 | * Supports the following chips: |
| 16 | * | 16 | * |
| 17 | * Chip #vin #fan #pwm #temp devid | 17 | * Chip #vin #fan #pwm #temp devid |
| 18 | * PC87427 - 8 - - 0xF2 | 18 | * PC87427 - 8 4 6 0xF2 |
| 19 | * | 19 | * |
| 20 | * This driver assumes that no more than one chip is present. | 20 | * This driver assumes that no more than one chip is present. |
| 21 | * Only fan inputs are supported so far, although the chip can do much more. | 21 | * Only fans are fully supported so far. Temperatures are in read-only |
| 22 | * mode, and voltages aren't supported at all. | ||
| 22 | */ | 23 | */ |
| 23 | 24 | ||
| 24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
| @@ -57,6 +58,25 @@ struct pc87427_data { | |||
| 57 | u16 fan[8]; /* register values */ | 58 | u16 fan[8]; /* register values */ |
| 58 | u16 fan_min[8]; /* register values */ | 59 | u16 fan_min[8]; /* register values */ |
| 59 | u8 fan_status[8]; /* register values */ | 60 | u8 fan_status[8]; /* register values */ |
| 61 | |||
| 62 | u8 pwm_enabled; /* bit vector */ | ||
| 63 | u8 pwm_auto_ok; /* bit vector */ | ||
| 64 | u8 pwm_enable[4]; /* register values */ | ||
| 65 | u8 pwm[4]; /* register values */ | ||
| 66 | |||
| 67 | u8 temp_enabled; /* bit vector */ | ||
| 68 | s16 temp[6]; /* register values */ | ||
| 69 | s8 temp_min[6]; /* register values */ | ||
| 70 | s8 temp_max[6]; /* register values */ | ||
| 71 | s8 temp_crit[6]; /* register values */ | ||
| 72 | u8 temp_status[6]; /* register values */ | ||
| 73 | u8 temp_type[6]; /* register values */ | ||
| 74 | }; | ||
| 75 | |||
| 76 | struct pc87427_sio_data { | ||
| 77 | unsigned short address[2]; | ||
| 78 | u8 has_fanin; | ||
| 79 | u8 has_fanout; | ||
| 60 | }; | 80 | }; |
| 61 | 81 | ||
| 62 | /* | 82 | /* |
| @@ -65,6 +85,13 @@ struct pc87427_data { | |||
| 65 | 85 | ||
| 66 | #define SIOREG_LDSEL 0x07 /* Logical device select */ | 86 | #define SIOREG_LDSEL 0x07 /* Logical device select */ |
| 67 | #define SIOREG_DEVID 0x20 /* Device ID */ | 87 | #define SIOREG_DEVID 0x20 /* Device ID */ |
| 88 | #define SIOREG_CF2 0x22 /* Configuration 2 */ | ||
| 89 | #define SIOREG_CF3 0x23 /* Configuration 3 */ | ||
| 90 | #define SIOREG_CF4 0x24 /* Configuration 4 */ | ||
| 91 | #define SIOREG_CF5 0x25 /* Configuration 5 */ | ||
| 92 | #define SIOREG_CFB 0x2B /* Configuration B */ | ||
| 93 | #define SIOREG_CFC 0x2C /* Configuration C */ | ||
| 94 | #define SIOREG_CFD 0x2D /* Configuration D */ | ||
| 68 | #define SIOREG_ACT 0x30 /* Device activation */ | 95 | #define SIOREG_ACT 0x30 /* Device activation */ |
| 69 | #define SIOREG_MAP 0x50 /* I/O or memory mapping */ | 96 | #define SIOREG_MAP 0x50 /* I/O or memory mapping */ |
| 70 | #define SIOREG_IOBASE 0x60 /* I/O base address */ | 97 | #define SIOREG_IOBASE 0x60 /* I/O base address */ |
| @@ -102,6 +129,8 @@ static inline void superio_exit(int sioaddr) | |||
| 102 | #define BANK_FM(nr) (nr) | 129 | #define BANK_FM(nr) (nr) |
| 103 | #define BANK_FT(nr) (0x08 + (nr)) | 130 | #define BANK_FT(nr) (0x08 + (nr)) |
| 104 | #define BANK_FC(nr) (0x10 + (nr) * 2) | 131 | #define BANK_FC(nr) (0x10 + (nr) * 2) |
| 132 | #define BANK_TM(nr) (nr) | ||
| 133 | #define BANK_VM(nr) (0x08 + (nr)) | ||
| 105 | 134 | ||
| 106 | /* | 135 | /* |
| 107 | * I/O access functions | 136 | * I/O access functions |
| @@ -179,6 +208,127 @@ static inline u16 fan_to_reg(unsigned long val) | |||
| 179 | } | 208 | } |
| 180 | 209 | ||
| 181 | /* | 210 | /* |
| 211 | * PWM registers and conversions | ||
| 212 | */ | ||
| 213 | |||
| 214 | #define PC87427_REG_PWM_ENABLE 0x10 | ||
| 215 | #define PC87427_REG_PWM_DUTY 0x12 | ||
| 216 | |||
| 217 | #define PWM_ENABLE_MODE_MASK (7 << 4) | ||
| 218 | #define PWM_ENABLE_CTLEN (1 << 0) | ||
| 219 | |||
| 220 | #define PWM_MODE_MANUAL (0 << 4) | ||
| 221 | #define PWM_MODE_AUTO (1 << 4) | ||
| 222 | #define PWM_MODE_OFF (2 << 4) | ||
| 223 | #define PWM_MODE_ON (7 << 4) | ||
| 224 | |||
| 225 | /* Dedicated function to read all registers related to a given PWM output. | ||
| 226 | This saves us quite a few locks and bank selections. | ||
| 227 | Must be called with data->lock held. | ||
| 228 | nr is from 0 to 3 */ | ||
| 229 | static void pc87427_readall_pwm(struct pc87427_data *data, u8 nr) | ||
| 230 | { | ||
| 231 | int iobase = data->address[LD_FAN]; | ||
| 232 | |||
| 233 | outb(BANK_FC(nr), iobase + PC87427_REG_BANK); | ||
| 234 | data->pwm_enable[nr] = inb(iobase + PC87427_REG_PWM_ENABLE); | ||
| 235 | data->pwm[nr] = inb(iobase + PC87427_REG_PWM_DUTY); | ||
| 236 | } | ||
| 237 | |||
| 238 | static inline int pwm_enable_from_reg(u8 reg) | ||
| 239 | { | ||
| 240 | switch (reg & PWM_ENABLE_MODE_MASK) { | ||
| 241 | case PWM_MODE_ON: | ||
| 242 | return 0; | ||
| 243 | case PWM_MODE_MANUAL: | ||
| 244 | case PWM_MODE_OFF: | ||
| 245 | return 1; | ||
| 246 | case PWM_MODE_AUTO: | ||
| 247 | return 2; | ||
| 248 | default: | ||
| 249 | return -EPROTO; | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | static inline u8 pwm_enable_to_reg(unsigned long val, u8 pwmval) | ||
| 254 | { | ||
| 255 | switch (val) { | ||
| 256 | default: | ||
| 257 | return PWM_MODE_ON; | ||
| 258 | case 1: | ||
| 259 | return pwmval ? PWM_MODE_MANUAL : PWM_MODE_OFF; | ||
| 260 | case 2: | ||
| 261 | return PWM_MODE_AUTO; | ||
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | /* | ||
| 266 | * Temperature registers and conversions | ||
| 267 | */ | ||
| 268 | |||
| 269 | #define PC87427_REG_TEMP_STATUS 0x10 | ||
| 270 | #define PC87427_REG_TEMP 0x14 | ||
| 271 | #define PC87427_REG_TEMP_MAX 0x18 | ||
| 272 | #define PC87427_REG_TEMP_MIN 0x19 | ||
| 273 | #define PC87427_REG_TEMP_CRIT 0x1a | ||
| 274 | #define PC87427_REG_TEMP_TYPE 0x1d | ||
| 275 | |||
| 276 | #define TEMP_STATUS_CHANEN (1 << 0) | ||
| 277 | #define TEMP_STATUS_LOWFLG (1 << 1) | ||
| 278 | #define TEMP_STATUS_HIGHFLG (1 << 2) | ||
| 279 | #define TEMP_STATUS_CRITFLG (1 << 3) | ||
| 280 | #define TEMP_STATUS_SENSERR (1 << 5) | ||
| 281 | #define TEMP_TYPE_MASK (3 << 5) | ||
| 282 | |||
| 283 | #define TEMP_TYPE_THERMISTOR (1 << 5) | ||
| 284 | #define TEMP_TYPE_REMOTE_DIODE (2 << 5) | ||
| 285 | #define TEMP_TYPE_LOCAL_DIODE (3 << 5) | ||
| 286 | |||
| 287 | /* Dedicated function to read all registers related to a given temperature | ||
| 288 | input. This saves us quite a few locks and bank selections. | ||
| 289 | Must be called with data->lock held. | ||
| 290 | nr is from 0 to 5 */ | ||
| 291 | static void pc87427_readall_temp(struct pc87427_data *data, u8 nr) | ||
| 292 | { | ||
| 293 | int iobase = data->address[LD_TEMP]; | ||
| 294 | |||
| 295 | outb(BANK_TM(nr), iobase + PC87427_REG_BANK); | ||
| 296 | data->temp[nr] = le16_to_cpu(inw(iobase + PC87427_REG_TEMP)); | ||
| 297 | data->temp_max[nr] = inb(iobase + PC87427_REG_TEMP_MAX); | ||
| 298 | data->temp_min[nr] = inb(iobase + PC87427_REG_TEMP_MIN); | ||
| 299 | data->temp_crit[nr] = inb(iobase + PC87427_REG_TEMP_CRIT); | ||
| 300 | data->temp_type[nr] = inb(iobase + PC87427_REG_TEMP_TYPE); | ||
| 301 | data->temp_status[nr] = inb(iobase + PC87427_REG_TEMP_STATUS); | ||
| 302 | /* Clear fan alarm bits */ | ||
| 303 | outb(data->temp_status[nr], iobase + PC87427_REG_TEMP_STATUS); | ||
| 304 | } | ||
| 305 | |||
| 306 | static inline unsigned int temp_type_from_reg(u8 reg) | ||
| 307 | { | ||
| 308 | switch (reg & TEMP_TYPE_MASK) { | ||
| 309 | case TEMP_TYPE_THERMISTOR: | ||
| 310 | return 4; | ||
| 311 | case TEMP_TYPE_REMOTE_DIODE: | ||
| 312 | case TEMP_TYPE_LOCAL_DIODE: | ||
| 313 | return 3; | ||
| 314 | default: | ||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | |||
| 319 | /* We assume 8-bit thermal sensors; 9-bit thermal sensors are possible | ||
| 320 | too, but I have no idea how to figure out when they are used. */ | ||
| 321 | static inline long temp_from_reg(s16 reg) | ||
| 322 | { | ||
| 323 | return reg * 1000 / 256; | ||
| 324 | } | ||
| 325 | |||
| 326 | static inline long temp_from_reg8(s8 reg) | ||
| 327 | { | ||
| 328 | return reg * 1000; | ||
| 329 | } | ||
| 330 | |||
| 331 | /* | ||
| 182 | * Data interface | 332 | * Data interface |
| 183 | */ | 333 | */ |
| 184 | 334 | ||
| @@ -198,6 +348,21 @@ static struct pc87427_data *pc87427_update_device(struct device *dev) | |||
| 198 | continue; | 348 | continue; |
| 199 | pc87427_readall_fan(data, i); | 349 | pc87427_readall_fan(data, i); |
| 200 | } | 350 | } |
| 351 | |||
| 352 | /* PWM outputs */ | ||
| 353 | for (i = 0; i < 4; i++) { | ||
| 354 | if (!(data->pwm_enabled & (1 << i))) | ||
| 355 | continue; | ||
| 356 | pc87427_readall_pwm(data, i); | ||
| 357 | } | ||
| 358 | |||
| 359 | /* Temperature channels */ | ||
| 360 | for (i = 0; i < 6; i++) { | ||
| 361 | if (!(data->temp_enabled & (1 << i))) | ||
| 362 | continue; | ||
| 363 | pc87427_readall_temp(data, i); | ||
| 364 | } | ||
| 365 | |||
| 201 | data->last_updated = jiffies; | 366 | data->last_updated = jiffies; |
| 202 | 367 | ||
| 203 | done: | 368 | done: |
| @@ -208,9 +373,8 @@ done: | |||
| 208 | static ssize_t show_fan_input(struct device *dev, struct device_attribute | 373 | static ssize_t show_fan_input(struct device *dev, struct device_attribute |
| 209 | *devattr, char *buf) | 374 | *devattr, char *buf) |
| 210 | { | 375 | { |
| 211 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 212 | struct pc87427_data *data = pc87427_update_device(dev); | 376 | struct pc87427_data *data = pc87427_update_device(dev); |
| 213 | int nr = attr->index; | 377 | int nr = to_sensor_dev_attr(devattr)->index; |
| 214 | 378 | ||
| 215 | return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr])); | 379 | return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr])); |
| 216 | } | 380 | } |
| @@ -218,9 +382,8 @@ static ssize_t show_fan_input(struct device *dev, struct device_attribute | |||
| 218 | static ssize_t show_fan_min(struct device *dev, struct device_attribute | 382 | static ssize_t show_fan_min(struct device *dev, struct device_attribute |
| 219 | *devattr, char *buf) | 383 | *devattr, char *buf) |
| 220 | { | 384 | { |
| 221 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 222 | struct pc87427_data *data = pc87427_update_device(dev); | 385 | struct pc87427_data *data = pc87427_update_device(dev); |
| 223 | int nr = attr->index; | 386 | int nr = to_sensor_dev_attr(devattr)->index; |
| 224 | 387 | ||
| 225 | return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr])); | 388 | return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr])); |
| 226 | } | 389 | } |
| @@ -228,9 +391,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute | |||
| 228 | static ssize_t show_fan_alarm(struct device *dev, struct device_attribute | 391 | static ssize_t show_fan_alarm(struct device *dev, struct device_attribute |
| 229 | *devattr, char *buf) | 392 | *devattr, char *buf) |
| 230 | { | 393 | { |
| 231 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 232 | struct pc87427_data *data = pc87427_update_device(dev); | 394 | struct pc87427_data *data = pc87427_update_device(dev); |
| 233 | int nr = attr->index; | 395 | int nr = to_sensor_dev_attr(devattr)->index; |
| 234 | 396 | ||
| 235 | return sprintf(buf, "%d\n", !!(data->fan_status[nr] | 397 | return sprintf(buf, "%d\n", !!(data->fan_status[nr] |
| 236 | & FAN_STATUS_LOSPD)); | 398 | & FAN_STATUS_LOSPD)); |
| @@ -239,9 +401,8 @@ static ssize_t show_fan_alarm(struct device *dev, struct device_attribute | |||
| 239 | static ssize_t show_fan_fault(struct device *dev, struct device_attribute | 401 | static ssize_t show_fan_fault(struct device *dev, struct device_attribute |
| 240 | *devattr, char *buf) | 402 | *devattr, char *buf) |
| 241 | { | 403 | { |
| 242 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 243 | struct pc87427_data *data = pc87427_update_device(dev); | 404 | struct pc87427_data *data = pc87427_update_device(dev); |
| 244 | int nr = attr->index; | 405 | int nr = to_sensor_dev_attr(devattr)->index; |
| 245 | 406 | ||
| 246 | return sprintf(buf, "%d\n", !!(data->fan_status[nr] | 407 | return sprintf(buf, "%d\n", !!(data->fan_status[nr] |
| 247 | & FAN_STATUS_STALL)); | 408 | & FAN_STATUS_STALL)); |
| @@ -251,11 +412,13 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute | |||
| 251 | *devattr, const char *buf, size_t count) | 412 | *devattr, const char *buf, size_t count) |
| 252 | { | 413 | { |
| 253 | struct pc87427_data *data = dev_get_drvdata(dev); | 414 | struct pc87427_data *data = dev_get_drvdata(dev); |
| 254 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 415 | int nr = to_sensor_dev_attr(devattr)->index; |
| 255 | int nr = attr->index; | 416 | unsigned long val; |
| 256 | unsigned long val = simple_strtoul(buf, NULL, 10); | ||
| 257 | int iobase = data->address[LD_FAN]; | 417 | int iobase = data->address[LD_FAN]; |
| 258 | 418 | ||
| 419 | if (strict_strtoul(buf, 10, &val) < 0) | ||
| 420 | return -EINVAL; | ||
| 421 | |||
| 259 | mutex_lock(&data->lock); | 422 | mutex_lock(&data->lock); |
| 260 | outb(BANK_FM(nr), iobase + PC87427_REG_BANK); | 423 | outb(BANK_FM(nr), iobase + PC87427_REG_BANK); |
| 261 | /* The low speed limit registers are read-only while monitoring | 424 | /* The low speed limit registers are read-only while monitoring |
| @@ -377,6 +540,390 @@ static const struct attribute_group pc87427_group_fan[8] = { | |||
| 377 | { .attrs = pc87427_attributes_fan[7] }, | 540 | { .attrs = pc87427_attributes_fan[7] }, |
| 378 | }; | 541 | }; |
| 379 | 542 | ||
| 543 | /* Must be called with data->lock held and pc87427_readall_pwm() freshly | ||
| 544 | called */ | ||
| 545 | static void update_pwm_enable(struct pc87427_data *data, int nr, u8 mode) | ||
| 546 | { | ||
| 547 | int iobase = data->address[LD_FAN]; | ||
| 548 | data->pwm_enable[nr] &= ~PWM_ENABLE_MODE_MASK; | ||
| 549 | data->pwm_enable[nr] |= mode; | ||
| 550 | outb(data->pwm_enable[nr], iobase + PC87427_REG_PWM_ENABLE); | ||
| 551 | } | ||
| 552 | |||
| 553 | static ssize_t show_pwm_enable(struct device *dev, struct device_attribute | ||
| 554 | *devattr, char *buf) | ||
| 555 | { | ||
| 556 | struct pc87427_data *data = pc87427_update_device(dev); | ||
| 557 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 558 | int pwm_enable; | ||
| 559 | |||
| 560 | pwm_enable = pwm_enable_from_reg(data->pwm_enable[nr]); | ||
| 561 | if (pwm_enable < 0) | ||
| 562 | return pwm_enable; | ||
| 563 | return sprintf(buf, "%d\n", pwm_enable); | ||
| 564 | } | ||
| 565 | |||
| 566 | static ssize_t set_pwm_enable(struct device *dev, struct device_attribute | ||
| 567 | *devattr, const char *buf, size_t count) | ||
| 568 | { | ||
| 569 | struct pc87427_data *data = dev_get_drvdata(dev); | ||
| 570 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 571 | unsigned long val; | ||
| 572 | |||
| 573 | if (strict_strtoul(buf, 10, &val) < 0 || val > 2) | ||
| 574 | return -EINVAL; | ||
| 575 | /* Can't go to automatic mode if it isn't configured */ | ||
| 576 | if (val == 2 && !(data->pwm_auto_ok & (1 << nr))) | ||
| 577 | return -EINVAL; | ||
| 578 | |||
| 579 | mutex_lock(&data->lock); | ||
| 580 | pc87427_readall_pwm(data, nr); | ||
| 581 | update_pwm_enable(data, nr, pwm_enable_to_reg(val, data->pwm[nr])); | ||
| 582 | mutex_unlock(&data->lock); | ||
| 583 | |||
| 584 | return count; | ||
| 585 | } | ||
| 586 | |||
| 587 | static ssize_t show_pwm(struct device *dev, struct device_attribute | ||
| 588 | *devattr, char *buf) | ||
| 589 | { | ||
| 590 | struct pc87427_data *data = pc87427_update_device(dev); | ||
| 591 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 592 | |||
| 593 | return sprintf(buf, "%d\n", (int)data->pwm[nr]); | ||
| 594 | } | ||
| 595 | |||
| 596 | static ssize_t set_pwm(struct device *dev, struct device_attribute | ||
| 597 | *devattr, const char *buf, size_t count) | ||
| 598 | { | ||
| 599 | struct pc87427_data *data = dev_get_drvdata(dev); | ||
| 600 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 601 | unsigned long val; | ||
| 602 | int iobase = data->address[LD_FAN]; | ||
| 603 | u8 mode; | ||
| 604 | |||
| 605 | if (strict_strtoul(buf, 10, &val) < 0 || val > 0xff) | ||
| 606 | return -EINVAL; | ||
| 607 | |||
| 608 | mutex_lock(&data->lock); | ||
| 609 | pc87427_readall_pwm(data, nr); | ||
| 610 | mode = data->pwm_enable[nr] & PWM_ENABLE_MODE_MASK; | ||
| 611 | if (mode != PWM_MODE_MANUAL && mode != PWM_MODE_OFF) { | ||
| 612 | dev_notice(dev, "Can't set PWM%d duty cycle while not in " | ||
| 613 | "manual mode\n", nr + 1); | ||
| 614 | mutex_unlock(&data->lock); | ||
| 615 | return -EPERM; | ||
| 616 | } | ||
| 617 | |||
| 618 | /* We may have to change the mode */ | ||
| 619 | if (mode == PWM_MODE_MANUAL && val == 0) { | ||
| 620 | /* Transition from Manual to Off */ | ||
| 621 | update_pwm_enable(data, nr, PWM_MODE_OFF); | ||
| 622 | mode = PWM_MODE_OFF; | ||
| 623 | dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1, | ||
| 624 | "manual", "off"); | ||
| 625 | } else if (mode == PWM_MODE_OFF && val != 0) { | ||
| 626 | /* Transition from Off to Manual */ | ||
| 627 | update_pwm_enable(data, nr, PWM_MODE_MANUAL); | ||
| 628 | mode = PWM_MODE_MANUAL; | ||
| 629 | dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1, | ||
| 630 | "off", "manual"); | ||
| 631 | } | ||
| 632 | |||
| 633 | data->pwm[nr] = val; | ||
| 634 | if (mode == PWM_MODE_MANUAL) | ||
| 635 | outb(val, iobase + PC87427_REG_PWM_DUTY); | ||
| 636 | mutex_unlock(&data->lock); | ||
| 637 | |||
| 638 | return count; | ||
| 639 | } | ||
| 640 | |||
| 641 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, | ||
| 642 | show_pwm_enable, set_pwm_enable, 0); | ||
| 643 | static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, | ||
| 644 | show_pwm_enable, set_pwm_enable, 1); | ||
| 645 | static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, | ||
| 646 | show_pwm_enable, set_pwm_enable, 2); | ||
| 647 | static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, | ||
| 648 | show_pwm_enable, set_pwm_enable, 3); | ||
| 649 | |||
| 650 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); | ||
| 651 | static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); | ||
| 652 | static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); | ||
| 653 | static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); | ||
| 654 | |||
| 655 | static struct attribute *pc87427_attributes_pwm[4][3] = { | ||
| 656 | { | ||
| 657 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
| 658 | &sensor_dev_attr_pwm1.dev_attr.attr, | ||
| 659 | NULL | ||
| 660 | }, { | ||
| 661 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
| 662 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
| 663 | NULL | ||
| 664 | }, { | ||
| 665 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
| 666 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
| 667 | NULL | ||
| 668 | }, { | ||
| 669 | &sensor_dev_attr_pwm4_enable.dev_attr.attr, | ||
| 670 | &sensor_dev_attr_pwm4.dev_attr.attr, | ||
| 671 | NULL | ||
| 672 | } | ||
| 673 | }; | ||
| 674 | |||
| 675 | static const struct attribute_group pc87427_group_pwm[4] = { | ||
| 676 | { .attrs = pc87427_attributes_pwm[0] }, | ||
| 677 | { .attrs = pc87427_attributes_pwm[1] }, | ||
| 678 | { .attrs = pc87427_attributes_pwm[2] }, | ||
| 679 | { .attrs = pc87427_attributes_pwm[3] }, | ||
| 680 | }; | ||
| 681 | |||
| 682 | static ssize_t show_temp_input(struct device *dev, struct device_attribute | ||
| 683 | *devattr, char *buf) | ||
| 684 | { | ||
| 685 | struct pc87427_data *data = pc87427_update_device(dev); | ||
| 686 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 687 | |||
| 688 | return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr])); | ||
| 689 | } | ||
| 690 | |||
| 691 | static ssize_t show_temp_min(struct device *dev, struct device_attribute | ||
| 692 | *devattr, char *buf) | ||
| 693 | { | ||
| 694 | struct pc87427_data *data = pc87427_update_device(dev); | ||
| 695 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 696 | |||
| 697 | return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_min[nr])); | ||
| 698 | } | ||
| 699 | |||
| 700 | static ssize_t show_temp_max(struct device *dev, struct device_attribute | ||
| 701 | *devattr, char *buf) | ||
| 702 | { | ||
| 703 | struct pc87427_data *data = pc87427_update_device(dev); | ||
| 704 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 705 | |||
| 706 | return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_max[nr])); | ||
| 707 | } | ||
| 708 | |||
| 709 | static ssize_t show_temp_crit(struct device *dev, struct device_attribute | ||
| 710 | *devattr, char *buf) | ||
| 711 | { | ||
| 712 | struct pc87427_data *data = pc87427_update_device(dev); | ||
| 713 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 714 | |||
| 715 | return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_crit[nr])); | ||
| 716 | } | ||
| 717 | |||
| 718 | static ssize_t show_temp_type(struct device *dev, struct device_attribute | ||
| 719 | *devattr, char *buf) | ||
| 720 | { | ||
| 721 | struct pc87427_data *data = pc87427_update_device(dev); | ||
| 722 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 723 | |||
| 724 | return sprintf(buf, "%u\n", temp_type_from_reg(data->temp_type[nr])); | ||
| 725 | } | ||
| 726 | |||
| 727 | static ssize_t show_temp_min_alarm(struct device *dev, struct device_attribute | ||
| 728 | *devattr, char *buf) | ||
| 729 | { | ||
| 730 | struct pc87427_data *data = pc87427_update_device(dev); | ||
| 731 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 732 | |||
| 733 | return sprintf(buf, "%d\n", !!(data->temp_status[nr] | ||
| 734 | & TEMP_STATUS_LOWFLG)); | ||
| 735 | } | ||
| 736 | |||
| 737 | static ssize_t show_temp_max_alarm(struct device *dev, struct device_attribute | ||
| 738 | *devattr, char *buf) | ||
| 739 | { | ||
| 740 | struct pc87427_data *data = pc87427_update_device(dev); | ||
| 741 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 742 | |||
| 743 | return sprintf(buf, "%d\n", !!(data->temp_status[nr] | ||
| 744 | & TEMP_STATUS_HIGHFLG)); | ||
| 745 | } | ||
| 746 | |||
| 747 | static ssize_t show_temp_crit_alarm(struct device *dev, struct device_attribute | ||
| 748 | *devattr, char *buf) | ||
| 749 | { | ||
| 750 | struct pc87427_data *data = pc87427_update_device(dev); | ||
| 751 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 752 | |||
| 753 | return sprintf(buf, "%d\n", !!(data->temp_status[nr] | ||
| 754 | & TEMP_STATUS_CRITFLG)); | ||
| 755 | } | ||
| 756 | |||
| 757 | static ssize_t show_temp_fault(struct device *dev, struct device_attribute | ||
| 758 | *devattr, char *buf) | ||
| 759 | { | ||
| 760 | struct pc87427_data *data = pc87427_update_device(dev); | ||
| 761 | int nr = to_sensor_dev_attr(devattr)->index; | ||
| 762 | |||
| 763 | return sprintf(buf, "%d\n", !!(data->temp_status[nr] | ||
| 764 | & TEMP_STATUS_SENSERR)); | ||
| 765 | } | ||
| 766 | |||
| 767 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); | ||
| 768 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1); | ||
| 769 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2); | ||
| 770 | static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3); | ||
| 771 | static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4); | ||
| 772 | static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5); | ||
| 773 | |||
| 774 | static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min, NULL, 0); | ||
| 775 | static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min, NULL, 1); | ||
| 776 | static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min, NULL, 2); | ||
| 777 | static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min, NULL, 3); | ||
| 778 | static SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min, NULL, 4); | ||
| 779 | static SENSOR_DEVICE_ATTR(temp6_min, S_IRUGO, show_temp_min, NULL, 5); | ||
| 780 | |||
| 781 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0); | ||
| 782 | static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1); | ||
| 783 | static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2); | ||
| 784 | static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3); | ||
| 785 | static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4); | ||
| 786 | static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5); | ||
| 787 | |||
| 788 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); | ||
| 789 | static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1); | ||
| 790 | static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2); | ||
| 791 | static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3); | ||
| 792 | static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4); | ||
| 793 | static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5); | ||
| 794 | |||
| 795 | static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0); | ||
| 796 | static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1); | ||
| 797 | static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2); | ||
| 798 | static SENSOR_DEVICE_ATTR(temp4_type, S_IRUGO, show_temp_type, NULL, 3); | ||
| 799 | static SENSOR_DEVICE_ATTR(temp5_type, S_IRUGO, show_temp_type, NULL, 4); | ||
| 800 | static SENSOR_DEVICE_ATTR(temp6_type, S_IRUGO, show_temp_type, NULL, 5); | ||
| 801 | |||
| 802 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, | ||
| 803 | show_temp_min_alarm, NULL, 0); | ||
| 804 | static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, | ||
| 805 | show_temp_min_alarm, NULL, 1); | ||
| 806 | static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, | ||
| 807 | show_temp_min_alarm, NULL, 2); | ||
| 808 | static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, | ||
| 809 | show_temp_min_alarm, NULL, 3); | ||
| 810 | static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, | ||
| 811 | show_temp_min_alarm, NULL, 4); | ||
| 812 | static SENSOR_DEVICE_ATTR(temp6_min_alarm, S_IRUGO, | ||
| 813 | show_temp_min_alarm, NULL, 5); | ||
| 814 | |||
| 815 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, | ||
| 816 | show_temp_max_alarm, NULL, 0); | ||
| 817 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, | ||
| 818 | show_temp_max_alarm, NULL, 1); | ||
| 819 | static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, | ||
| 820 | show_temp_max_alarm, NULL, 2); | ||
| 821 | static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, | ||
| 822 | show_temp_max_alarm, NULL, 3); | ||
| 823 | static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, | ||
| 824 | show_temp_max_alarm, NULL, 4); | ||
| 825 | static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO, | ||
| 826 | show_temp_max_alarm, NULL, 5); | ||
| 827 | |||
| 828 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, | ||
| 829 | show_temp_crit_alarm, NULL, 0); | ||
| 830 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, | ||
| 831 | show_temp_crit_alarm, NULL, 1); | ||
| 832 | static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, | ||
| 833 | show_temp_crit_alarm, NULL, 2); | ||
| 834 | static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, | ||
| 835 | show_temp_crit_alarm, NULL, 3); | ||
| 836 | static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, | ||
| 837 | show_temp_crit_alarm, NULL, 4); | ||
| 838 | static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO, | ||
| 839 | show_temp_crit_alarm, NULL, 5); | ||
| 840 | |||
| 841 | static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); | ||
| 842 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); | ||
| 843 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2); | ||
| 844 | static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3); | ||
| 845 | static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4); | ||
| 846 | static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5); | ||
| 847 | |||
| 848 | static struct attribute *pc87427_attributes_temp[6][10] = { | ||
| 849 | { | ||
| 850 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
| 851 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
| 852 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
| 853 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
| 854 | &sensor_dev_attr_temp1_type.dev_attr.attr, | ||
| 855 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | ||
| 856 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
| 857 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | ||
| 858 | &sensor_dev_attr_temp1_fault.dev_attr.attr, | ||
| 859 | NULL | ||
| 860 | }, { | ||
| 861 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
| 862 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
| 863 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
| 864 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | ||
| 865 | &sensor_dev_attr_temp2_type.dev_attr.attr, | ||
| 866 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | ||
| 867 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | ||
| 868 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | ||
| 869 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | ||
| 870 | NULL | ||
| 871 | }, { | ||
| 872 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
| 873 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
| 874 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
| 875 | &sensor_dev_attr_temp3_crit.dev_attr.attr, | ||
| 876 | &sensor_dev_attr_temp3_type.dev_attr.attr, | ||
| 877 | &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, | ||
| 878 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, | ||
| 879 | &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, | ||
| 880 | &sensor_dev_attr_temp3_fault.dev_attr.attr, | ||
| 881 | NULL | ||
| 882 | }, { | ||
| 883 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
| 884 | &sensor_dev_attr_temp4_min.dev_attr.attr, | ||
| 885 | &sensor_dev_attr_temp4_max.dev_attr.attr, | ||
| 886 | &sensor_dev_attr_temp4_crit.dev_attr.attr, | ||
| 887 | &sensor_dev_attr_temp4_type.dev_attr.attr, | ||
| 888 | &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, | ||
| 889 | &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, | ||
| 890 | &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, | ||
| 891 | &sensor_dev_attr_temp4_fault.dev_attr.attr, | ||
| 892 | NULL | ||
| 893 | }, { | ||
| 894 | &sensor_dev_attr_temp5_input.dev_attr.attr, | ||
| 895 | &sensor_dev_attr_temp5_min.dev_attr.attr, | ||
| 896 | &sensor_dev_attr_temp5_max.dev_attr.attr, | ||
| 897 | &sensor_dev_attr_temp5_crit.dev_attr.attr, | ||
| 898 | &sensor_dev_attr_temp5_type.dev_attr.attr, | ||
| 899 | &sensor_dev_attr_temp5_min_alarm.dev_attr.attr, | ||
| 900 | &sensor_dev_attr_temp5_max_alarm.dev_attr.attr, | ||
| 901 | &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, | ||
| 902 | &sensor_dev_attr_temp5_fault.dev_attr.attr, | ||
| 903 | NULL | ||
| 904 | }, { | ||
| 905 | &sensor_dev_attr_temp6_input.dev_attr.attr, | ||
| 906 | &sensor_dev_attr_temp6_min.dev_attr.attr, | ||
| 907 | &sensor_dev_attr_temp6_max.dev_attr.attr, | ||
| 908 | &sensor_dev_attr_temp6_crit.dev_attr.attr, | ||
| 909 | &sensor_dev_attr_temp6_type.dev_attr.attr, | ||
| 910 | &sensor_dev_attr_temp6_min_alarm.dev_attr.attr, | ||
| 911 | &sensor_dev_attr_temp6_max_alarm.dev_attr.attr, | ||
| 912 | &sensor_dev_attr_temp6_crit_alarm.dev_attr.attr, | ||
| 913 | &sensor_dev_attr_temp6_fault.dev_attr.attr, | ||
| 914 | NULL | ||
| 915 | } | ||
| 916 | }; | ||
| 917 | |||
| 918 | static const struct attribute_group pc87427_group_temp[6] = { | ||
| 919 | { .attrs = pc87427_attributes_temp[0] }, | ||
| 920 | { .attrs = pc87427_attributes_temp[1] }, | ||
| 921 | { .attrs = pc87427_attributes_temp[2] }, | ||
| 922 | { .attrs = pc87427_attributes_temp[3] }, | ||
| 923 | { .attrs = pc87427_attributes_temp[4] }, | ||
| 924 | { .attrs = pc87427_attributes_temp[5] }, | ||
| 925 | }; | ||
| 926 | |||
| 380 | static ssize_t show_name(struct device *dev, struct device_attribute | 927 | static ssize_t show_name(struct device *dev, struct device_attribute |
| 381 | *devattr, char *buf) | 928 | *devattr, char *buf) |
| 382 | { | 929 | { |
| @@ -391,8 +938,49 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | |||
| 391 | * Device detection, attach and detach | 938 | * Device detection, attach and detach |
| 392 | */ | 939 | */ |
| 393 | 940 | ||
| 941 | static void pc87427_release_regions(struct platform_device *pdev, int count) | ||
| 942 | { | ||
| 943 | struct resource *res; | ||
| 944 | int i; | ||
| 945 | |||
| 946 | for (i = 0; i < count; i++) { | ||
| 947 | res = platform_get_resource(pdev, IORESOURCE_IO, i); | ||
| 948 | release_region(res->start, resource_size(res)); | ||
| 949 | } | ||
| 950 | } | ||
| 951 | |||
| 952 | static int __devinit pc87427_request_regions(struct platform_device *pdev, | ||
| 953 | int count) | ||
| 954 | { | ||
| 955 | struct resource *res; | ||
| 956 | int i, err = 0; | ||
| 957 | |||
| 958 | for (i = 0; i < count; i++) { | ||
| 959 | res = platform_get_resource(pdev, IORESOURCE_IO, i); | ||
| 960 | if (!res) { | ||
| 961 | err = -ENOENT; | ||
| 962 | dev_err(&pdev->dev, "Missing resource #%d\n", i); | ||
| 963 | break; | ||
| 964 | } | ||
| 965 | if (!request_region(res->start, resource_size(res), DRVNAME)) { | ||
| 966 | err = -EBUSY; | ||
| 967 | dev_err(&pdev->dev, | ||
| 968 | "Failed to request region 0x%lx-0x%lx\n", | ||
| 969 | (unsigned long)res->start, | ||
| 970 | (unsigned long)res->end); | ||
| 971 | break; | ||
| 972 | } | ||
| 973 | } | ||
| 974 | |||
| 975 | if (err && i) | ||
| 976 | pc87427_release_regions(pdev, i); | ||
| 977 | |||
| 978 | return err; | ||
| 979 | } | ||
| 980 | |||
| 394 | static void __devinit pc87427_init_device(struct device *dev) | 981 | static void __devinit pc87427_init_device(struct device *dev) |
| 395 | { | 982 | { |
| 983 | struct pc87427_sio_data *sio_data = dev->platform_data; | ||
| 396 | struct pc87427_data *data = dev_get_drvdata(dev); | 984 | struct pc87427_data *data = dev_get_drvdata(dev); |
| 397 | int i; | 985 | int i; |
| 398 | u8 reg; | 986 | u8 reg; |
| @@ -400,10 +988,12 @@ static void __devinit pc87427_init_device(struct device *dev) | |||
| 400 | /* The FMC module should be ready */ | 988 | /* The FMC module should be ready */ |
| 401 | reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK); | 989 | reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK); |
| 402 | if (!(reg & 0x80)) | 990 | if (!(reg & 0x80)) |
| 403 | dev_warn(dev, "FMC module not ready!\n"); | 991 | dev_warn(dev, "%s module not ready!\n", "FMC"); |
| 404 | 992 | ||
| 405 | /* Check which fans are enabled */ | 993 | /* Check which fans are enabled */ |
| 406 | for (i = 0; i < 8; i++) { | 994 | for (i = 0; i < 8; i++) { |
| 995 | if (!(sio_data->has_fanin & (1 << i))) /* Not wired */ | ||
| 996 | continue; | ||
| 407 | reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i), | 997 | reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i), |
| 408 | PC87427_REG_FAN_STATUS); | 998 | PC87427_REG_FAN_STATUS); |
| 409 | if (reg & FAN_STATUS_MONEN) | 999 | if (reg & FAN_STATUS_MONEN) |
| @@ -411,37 +1001,93 @@ static void __devinit pc87427_init_device(struct device *dev) | |||
| 411 | } | 1001 | } |
| 412 | 1002 | ||
| 413 | if (!data->fan_enabled) { | 1003 | if (!data->fan_enabled) { |
| 414 | dev_dbg(dev, "Enabling all fan inputs\n"); | 1004 | dev_dbg(dev, "Enabling monitoring of all fans\n"); |
| 415 | for (i = 0; i < 8; i++) | 1005 | for (i = 0; i < 8; i++) { |
| 1006 | if (!(sio_data->has_fanin & (1 << i))) /* Not wired */ | ||
| 1007 | continue; | ||
| 416 | pc87427_write8_bank(data, LD_FAN, BANK_FM(i), | 1008 | pc87427_write8_bank(data, LD_FAN, BANK_FM(i), |
| 417 | PC87427_REG_FAN_STATUS, | 1009 | PC87427_REG_FAN_STATUS, |
| 418 | FAN_STATUS_MONEN); | 1010 | FAN_STATUS_MONEN); |
| 419 | data->fan_enabled = 0xff; | 1011 | } |
| 1012 | data->fan_enabled = sio_data->has_fanin; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | /* Check which PWM outputs are enabled */ | ||
| 1016 | for (i = 0; i < 4; i++) { | ||
| 1017 | if (!(sio_data->has_fanout & (1 << i))) /* Not wired */ | ||
| 1018 | continue; | ||
| 1019 | reg = pc87427_read8_bank(data, LD_FAN, BANK_FC(i), | ||
| 1020 | PC87427_REG_PWM_ENABLE); | ||
| 1021 | if (reg & PWM_ENABLE_CTLEN) | ||
| 1022 | data->pwm_enabled |= (1 << i); | ||
| 1023 | |||
| 1024 | /* We don't expose an interface to reconfigure the automatic | ||
| 1025 | fan control mode, so only allow to return to this mode if | ||
| 1026 | it was originally set. */ | ||
| 1027 | if ((reg & PWM_ENABLE_MODE_MASK) == PWM_MODE_AUTO) { | ||
| 1028 | dev_dbg(dev, "PWM%d is in automatic control mode\n", | ||
| 1029 | i + 1); | ||
| 1030 | data->pwm_auto_ok |= (1 << i); | ||
| 1031 | } | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | /* The HMC module should be ready */ | ||
| 1035 | reg = pc87427_read8(data, LD_TEMP, PC87427_REG_BANK); | ||
| 1036 | if (!(reg & 0x80)) | ||
| 1037 | dev_warn(dev, "%s module not ready!\n", "HMC"); | ||
| 1038 | |||
| 1039 | /* Check which temperature channels are enabled */ | ||
| 1040 | for (i = 0; i < 6; i++) { | ||
| 1041 | reg = pc87427_read8_bank(data, LD_TEMP, BANK_TM(i), | ||
| 1042 | PC87427_REG_TEMP_STATUS); | ||
| 1043 | if (reg & TEMP_STATUS_CHANEN) | ||
| 1044 | data->temp_enabled |= (1 << i); | ||
| 1045 | } | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | static void pc87427_remove_files(struct device *dev) | ||
| 1049 | { | ||
| 1050 | struct pc87427_data *data = dev_get_drvdata(dev); | ||
| 1051 | int i; | ||
| 1052 | |||
| 1053 | device_remove_file(dev, &dev_attr_name); | ||
| 1054 | for (i = 0; i < 8; i++) { | ||
| 1055 | if (!(data->fan_enabled & (1 << i))) | ||
| 1056 | continue; | ||
| 1057 | sysfs_remove_group(&dev->kobj, &pc87427_group_fan[i]); | ||
| 1058 | } | ||
| 1059 | for (i = 0; i < 4; i++) { | ||
| 1060 | if (!(data->pwm_enabled & (1 << i))) | ||
| 1061 | continue; | ||
| 1062 | sysfs_remove_group(&dev->kobj, &pc87427_group_pwm[i]); | ||
| 1063 | } | ||
| 1064 | for (i = 0; i < 6; i++) { | ||
| 1065 | if (!(data->temp_enabled & (1 << i))) | ||
| 1066 | continue; | ||
| 1067 | sysfs_remove_group(&dev->kobj, &pc87427_group_temp[i]); | ||
| 420 | } | 1068 | } |
| 421 | } | 1069 | } |
| 422 | 1070 | ||
| 423 | static int __devinit pc87427_probe(struct platform_device *pdev) | 1071 | static int __devinit pc87427_probe(struct platform_device *pdev) |
| 424 | { | 1072 | { |
| 1073 | struct pc87427_sio_data *sio_data = pdev->dev.platform_data; | ||
| 425 | struct pc87427_data *data; | 1074 | struct pc87427_data *data; |
| 426 | struct resource *res; | 1075 | int i, err, res_count; |
| 427 | int i, err; | ||
| 428 | 1076 | ||
| 429 | if (!(data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL))) { | 1077 | data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL); |
| 1078 | if (!data) { | ||
| 430 | err = -ENOMEM; | 1079 | err = -ENOMEM; |
| 431 | printk(KERN_ERR DRVNAME ": Out of memory\n"); | 1080 | printk(KERN_ERR DRVNAME ": Out of memory\n"); |
| 432 | goto exit; | 1081 | goto exit; |
| 433 | } | 1082 | } |
| 434 | 1083 | ||
| 435 | /* This will need to be revisited when we add support for | 1084 | data->address[0] = sio_data->address[0]; |
| 436 | temperature and voltage monitoring. */ | 1085 | data->address[1] = sio_data->address[1]; |
| 437 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1086 | res_count = (data->address[0] != 0) + (data->address[1] != 0); |
| 438 | if (!request_region(res->start, resource_size(res), DRVNAME)) { | 1087 | |
| 439 | err = -EBUSY; | 1088 | err = pc87427_request_regions(pdev, res_count); |
| 440 | dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n", | 1089 | if (err) |
| 441 | (unsigned long)res->start, (unsigned long)res->end); | ||
| 442 | goto exit_kfree; | 1090 | goto exit_kfree; |
| 443 | } | ||
| 444 | data->address[0] = res->start; | ||
| 445 | 1091 | ||
| 446 | mutex_init(&data->lock); | 1092 | mutex_init(&data->lock); |
| 447 | data->name = "pc87427"; | 1093 | data->name = "pc87427"; |
| @@ -449,13 +1095,31 @@ static int __devinit pc87427_probe(struct platform_device *pdev) | |||
| 449 | pc87427_init_device(&pdev->dev); | 1095 | pc87427_init_device(&pdev->dev); |
| 450 | 1096 | ||
| 451 | /* Register sysfs hooks */ | 1097 | /* Register sysfs hooks */ |
| 452 | if ((err = device_create_file(&pdev->dev, &dev_attr_name))) | 1098 | err = device_create_file(&pdev->dev, &dev_attr_name); |
| 1099 | if (err) | ||
| 453 | goto exit_release_region; | 1100 | goto exit_release_region; |
| 454 | for (i = 0; i < 8; i++) { | 1101 | for (i = 0; i < 8; i++) { |
| 455 | if (!(data->fan_enabled & (1 << i))) | 1102 | if (!(data->fan_enabled & (1 << i))) |
| 456 | continue; | 1103 | continue; |
| 457 | if ((err = sysfs_create_group(&pdev->dev.kobj, | 1104 | err = sysfs_create_group(&pdev->dev.kobj, |
| 458 | &pc87427_group_fan[i]))) | 1105 | &pc87427_group_fan[i]); |
| 1106 | if (err) | ||
| 1107 | goto exit_remove_files; | ||
| 1108 | } | ||
| 1109 | for (i = 0; i < 4; i++) { | ||
| 1110 | if (!(data->pwm_enabled & (1 << i))) | ||
| 1111 | continue; | ||
| 1112 | err = sysfs_create_group(&pdev->dev.kobj, | ||
| 1113 | &pc87427_group_pwm[i]); | ||
| 1114 | if (err) | ||
| 1115 | goto exit_remove_files; | ||
| 1116 | } | ||
| 1117 | for (i = 0; i < 6; i++) { | ||
| 1118 | if (!(data->temp_enabled & (1 << i))) | ||
| 1119 | continue; | ||
| 1120 | err = sysfs_create_group(&pdev->dev.kobj, | ||
| 1121 | &pc87427_group_temp[i]); | ||
| 1122 | if (err) | ||
| 459 | goto exit_remove_files; | 1123 | goto exit_remove_files; |
| 460 | } | 1124 | } |
| 461 | 1125 | ||
| @@ -469,13 +1133,9 @@ static int __devinit pc87427_probe(struct platform_device *pdev) | |||
| 469 | return 0; | 1133 | return 0; |
| 470 | 1134 | ||
| 471 | exit_remove_files: | 1135 | exit_remove_files: |
| 472 | for (i = 0; i < 8; i++) { | 1136 | pc87427_remove_files(&pdev->dev); |
| 473 | if (!(data->fan_enabled & (1 << i))) | ||
| 474 | continue; | ||
| 475 | sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]); | ||
| 476 | } | ||
| 477 | exit_release_region: | 1137 | exit_release_region: |
| 478 | release_region(res->start, resource_size(res)); | 1138 | pc87427_release_regions(pdev, res_count); |
| 479 | exit_kfree: | 1139 | exit_kfree: |
| 480 | platform_set_drvdata(pdev, NULL); | 1140 | platform_set_drvdata(pdev, NULL); |
| 481 | kfree(data); | 1141 | kfree(data); |
| @@ -486,21 +1146,16 @@ exit: | |||
| 486 | static int __devexit pc87427_remove(struct platform_device *pdev) | 1146 | static int __devexit pc87427_remove(struct platform_device *pdev) |
| 487 | { | 1147 | { |
| 488 | struct pc87427_data *data = platform_get_drvdata(pdev); | 1148 | struct pc87427_data *data = platform_get_drvdata(pdev); |
| 489 | struct resource *res; | 1149 | int res_count; |
| 490 | int i; | 1150 | |
| 1151 | res_count = (data->address[0] != 0) + (data->address[1] != 0); | ||
| 491 | 1152 | ||
| 492 | hwmon_device_unregister(data->hwmon_dev); | 1153 | hwmon_device_unregister(data->hwmon_dev); |
| 493 | device_remove_file(&pdev->dev, &dev_attr_name); | 1154 | pc87427_remove_files(&pdev->dev); |
| 494 | for (i = 0; i < 8; i++) { | ||
| 495 | if (!(data->fan_enabled & (1 << i))) | ||
| 496 | continue; | ||
| 497 | sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]); | ||
| 498 | } | ||
| 499 | platform_set_drvdata(pdev, NULL); | 1155 | platform_set_drvdata(pdev, NULL); |
| 500 | kfree(data); | 1156 | kfree(data); |
| 501 | 1157 | ||
| 502 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1158 | pc87427_release_regions(pdev, res_count); |
| 503 | release_region(res->start, resource_size(res)); | ||
| 504 | 1159 | ||
| 505 | return 0; | 1160 | return 0; |
| 506 | } | 1161 | } |
| @@ -515,34 +1170,50 @@ static struct platform_driver pc87427_driver = { | |||
| 515 | .remove = __devexit_p(pc87427_remove), | 1170 | .remove = __devexit_p(pc87427_remove), |
| 516 | }; | 1171 | }; |
| 517 | 1172 | ||
| 518 | static int __init pc87427_device_add(unsigned short address) | 1173 | static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data) |
| 519 | { | 1174 | { |
| 520 | struct resource res = { | 1175 | struct resource res[2] = { |
| 521 | .start = address, | 1176 | { .flags = IORESOURCE_IO }, |
| 522 | .end = address + REGION_LENGTH - 1, | 1177 | { .flags = IORESOURCE_IO }, |
| 523 | .name = logdev_str[0], | ||
| 524 | .flags = IORESOURCE_IO, | ||
| 525 | }; | 1178 | }; |
| 526 | int err; | 1179 | int err, i, res_count; |
| 527 | 1180 | ||
| 528 | err = acpi_check_resource_conflict(&res); | 1181 | res_count = 0; |
| 529 | if (err) | 1182 | for (i = 0; i < 2; i++) { |
| 530 | goto exit; | 1183 | if (!sio_data->address[i]) |
| 1184 | continue; | ||
| 1185 | res[res_count].start = sio_data->address[i]; | ||
| 1186 | res[res_count].end = sio_data->address[i] + REGION_LENGTH - 1; | ||
| 1187 | res[res_count].name = logdev_str[i]; | ||
| 531 | 1188 | ||
| 532 | pdev = platform_device_alloc(DRVNAME, address); | 1189 | err = acpi_check_resource_conflict(&res[res_count]); |
| 1190 | if (err) | ||
| 1191 | goto exit; | ||
| 1192 | |||
| 1193 | res_count++; | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | pdev = platform_device_alloc(DRVNAME, res[0].start); | ||
| 533 | if (!pdev) { | 1197 | if (!pdev) { |
| 534 | err = -ENOMEM; | 1198 | err = -ENOMEM; |
| 535 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | 1199 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); |
| 536 | goto exit; | 1200 | goto exit; |
| 537 | } | 1201 | } |
| 538 | 1202 | ||
| 539 | err = platform_device_add_resources(pdev, &res, 1); | 1203 | err = platform_device_add_resources(pdev, res, res_count); |
| 540 | if (err) { | 1204 | if (err) { |
| 541 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | 1205 | printk(KERN_ERR DRVNAME ": Device resource addition failed " |
| 542 | "(%d)\n", err); | 1206 | "(%d)\n", err); |
| 543 | goto exit_device_put; | 1207 | goto exit_device_put; |
| 544 | } | 1208 | } |
| 545 | 1209 | ||
| 1210 | err = platform_device_add_data(pdev, sio_data, | ||
| 1211 | sizeof(struct pc87427_sio_data)); | ||
| 1212 | if (err) { | ||
| 1213 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); | ||
| 1214 | goto exit_device_put; | ||
| 1215 | } | ||
| 1216 | |||
| 546 | err = platform_device_add(pdev); | 1217 | err = platform_device_add(pdev); |
| 547 | if (err) { | 1218 | if (err) { |
| 548 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | 1219 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", |
| @@ -558,9 +1229,10 @@ exit: | |||
| 558 | return err; | 1229 | return err; |
| 559 | } | 1230 | } |
| 560 | 1231 | ||
| 561 | static int __init pc87427_find(int sioaddr, unsigned short *address) | 1232 | static int __init pc87427_find(int sioaddr, struct pc87427_sio_data *sio_data) |
| 562 | { | 1233 | { |
| 563 | u16 val; | 1234 | u16 val; |
| 1235 | u8 cfg, cfg_b; | ||
| 564 | int i, err = 0; | 1236 | int i, err = 0; |
| 565 | 1237 | ||
| 566 | /* Identify device */ | 1238 | /* Identify device */ |
| @@ -571,7 +1243,7 @@ static int __init pc87427_find(int sioaddr, unsigned short *address) | |||
| 571 | } | 1243 | } |
| 572 | 1244 | ||
| 573 | for (i = 0; i < 2; i++) { | 1245 | for (i = 0; i < 2; i++) { |
| 574 | address[i] = 0; | 1246 | sio_data->address[i] = 0; |
| 575 | /* Select logical device */ | 1247 | /* Select logical device */ |
| 576 | superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]); | 1248 | superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]); |
| 577 | 1249 | ||
| @@ -596,9 +1268,58 @@ static int __init pc87427_find(int sioaddr, unsigned short *address) | |||
| 596 | "for logical device 0x%02x\n", logdev[i]); | 1268 | "for logical device 0x%02x\n", logdev[i]); |
| 597 | continue; | 1269 | continue; |
| 598 | } | 1270 | } |
| 599 | address[i] = val; | 1271 | sio_data->address[i] = val; |
| 600 | } | 1272 | } |
| 601 | 1273 | ||
| 1274 | /* No point in loading the driver if everything is disabled */ | ||
| 1275 | if (!sio_data->address[0] && !sio_data->address[1]) { | ||
| 1276 | err = -ENODEV; | ||
| 1277 | goto exit; | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | /* Check which fan inputs are wired */ | ||
| 1281 | sio_data->has_fanin = (1 << 2) | (1 << 3); /* FANIN2, FANIN3 */ | ||
| 1282 | |||
| 1283 | cfg = superio_inb(sioaddr, SIOREG_CF2); | ||
| 1284 | if (!(cfg & (1 << 3))) | ||
| 1285 | sio_data->has_fanin |= (1 << 0); /* FANIN0 */ | ||
| 1286 | if (!(cfg & (1 << 2))) | ||
| 1287 | sio_data->has_fanin |= (1 << 4); /* FANIN4 */ | ||
| 1288 | |||
| 1289 | cfg = superio_inb(sioaddr, SIOREG_CFD); | ||
| 1290 | if (!(cfg & (1 << 0))) | ||
| 1291 | sio_data->has_fanin |= (1 << 1); /* FANIN1 */ | ||
| 1292 | |||
| 1293 | cfg = superio_inb(sioaddr, SIOREG_CF4); | ||
| 1294 | if (!(cfg & (1 << 0))) | ||
| 1295 | sio_data->has_fanin |= (1 << 7); /* FANIN7 */ | ||
| 1296 | cfg_b = superio_inb(sioaddr, SIOREG_CFB); | ||
| 1297 | if (!(cfg & (1 << 1)) && (cfg_b & (1 << 3))) | ||
| 1298 | sio_data->has_fanin |= (1 << 5); /* FANIN5 */ | ||
| 1299 | cfg = superio_inb(sioaddr, SIOREG_CF3); | ||
| 1300 | if ((cfg & (1 << 3)) && !(cfg_b & (1 << 5))) | ||
| 1301 | sio_data->has_fanin |= (1 << 6); /* FANIN6 */ | ||
| 1302 | |||
| 1303 | /* Check which fan outputs are wired */ | ||
| 1304 | sio_data->has_fanout = (1 << 0); /* FANOUT0 */ | ||
| 1305 | if (cfg_b & (1 << 0)) | ||
| 1306 | sio_data->has_fanout |= (1 << 3); /* FANOUT3 */ | ||
| 1307 | |||
| 1308 | cfg = superio_inb(sioaddr, SIOREG_CFC); | ||
| 1309 | if (!(cfg & (1 << 4))) { | ||
| 1310 | if (cfg_b & (1 << 1)) | ||
| 1311 | sio_data->has_fanout |= (1 << 1); /* FANOUT1 */ | ||
| 1312 | if (cfg_b & (1 << 2)) | ||
| 1313 | sio_data->has_fanout |= (1 << 2); /* FANOUT2 */ | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | /* FANOUT1 and FANOUT2 can each be routed to 2 different pins */ | ||
| 1317 | cfg = superio_inb(sioaddr, SIOREG_CF5); | ||
| 1318 | if (cfg & (1 << 6)) | ||
| 1319 | sio_data->has_fanout |= (1 << 1); /* FANOUT1 */ | ||
| 1320 | if (cfg & (1 << 5)) | ||
| 1321 | sio_data->has_fanout |= (1 << 2); /* FANOUT2 */ | ||
| 1322 | |||
| 602 | exit: | 1323 | exit: |
| 603 | superio_exit(sioaddr); | 1324 | superio_exit(sioaddr); |
| 604 | return err; | 1325 | return err; |
| @@ -607,15 +1328,10 @@ exit: | |||
| 607 | static int __init pc87427_init(void) | 1328 | static int __init pc87427_init(void) |
| 608 | { | 1329 | { |
| 609 | int err; | 1330 | int err; |
| 610 | unsigned short address[2]; | 1331 | struct pc87427_sio_data sio_data; |
| 611 | |||
| 612 | if (pc87427_find(0x2e, address) | ||
| 613 | && pc87427_find(0x4e, address)) | ||
| 614 | return -ENODEV; | ||
| 615 | 1332 | ||
| 616 | /* For now the driver only handles fans so we only care about the | 1333 | if (pc87427_find(0x2e, &sio_data) |
| 617 | first address. */ | 1334 | && pc87427_find(0x4e, &sio_data)) |
| 618 | if (!address[0]) | ||
| 619 | return -ENODEV; | 1335 | return -ENODEV; |
| 620 | 1336 | ||
| 621 | err = platform_driver_register(&pc87427_driver); | 1337 | err = platform_driver_register(&pc87427_driver); |
| @@ -623,7 +1339,7 @@ static int __init pc87427_init(void) | |||
| 623 | goto exit; | 1339 | goto exit; |
| 624 | 1340 | ||
| 625 | /* Sets global pdev as a side effect */ | 1341 | /* Sets global pdev as a side effect */ |
| 626 | err = pc87427_device_add(address[0]); | 1342 | err = pc87427_device_add(&sio_data); |
| 627 | if (err) | 1343 | if (err) |
| 628 | goto exit_driver; | 1344 | goto exit_driver; |
| 629 | 1345 | ||
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 7442cf754856..ffb793af680b 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | 39 | ||
| 40 | #define DRVNAME "via_cputemp" | 40 | #define DRVNAME "via_cputemp" |
| 41 | 41 | ||
| 42 | enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME } SHOW; | 42 | enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME }; |
| 43 | 43 | ||
| 44 | /* | 44 | /* |
| 45 | * Functions declaration | 45 | * Functions declaration |
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 0dcaba9b7189..e96e69dd36fb 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3 | 39 | w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3 |
| 40 | w83627dhg-p 9 5 4 3 0xb070 0xc1 0x5ca3 | 40 | w83627dhg-p 9 5 4 3 0xb070 0xc1 0x5ca3 |
| 41 | w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3 | 41 | w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3 |
| 42 | w83667hg-b 9 5 3 3 0xb350 0xc1 0x5ca3 | ||
| 42 | */ | 43 | */ |
| 43 | 44 | ||
| 44 | #include <linux/module.h> | 45 | #include <linux/module.h> |
| @@ -55,7 +56,7 @@ | |||
| 55 | #include <linux/io.h> | 56 | #include <linux/io.h> |
| 56 | #include "lm75.h" | 57 | #include "lm75.h" |
| 57 | 58 | ||
| 58 | enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg }; | 59 | enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg, w83667hg_b }; |
| 59 | 60 | ||
| 60 | /* used to set data->name = w83627ehf_device_names[data->sio_kind] */ | 61 | /* used to set data->name = w83627ehf_device_names[data->sio_kind] */ |
| 61 | static const char * w83627ehf_device_names[] = { | 62 | static const char * w83627ehf_device_names[] = { |
| @@ -63,6 +64,7 @@ static const char * w83627ehf_device_names[] = { | |||
| 63 | "w83627dhg", | 64 | "w83627dhg", |
| 64 | "w83627dhg", | 65 | "w83627dhg", |
| 65 | "w83667hg", | 66 | "w83667hg", |
| 67 | "w83667hg", | ||
| 66 | }; | 68 | }; |
| 67 | 69 | ||
| 68 | static unsigned short force_id; | 70 | static unsigned short force_id; |
| @@ -91,6 +93,7 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID"); | |||
| 91 | #define SIO_W83627DHG_ID 0xa020 | 93 | #define SIO_W83627DHG_ID 0xa020 |
| 92 | #define SIO_W83627DHG_P_ID 0xb070 | 94 | #define SIO_W83627DHG_P_ID 0xb070 |
| 93 | #define SIO_W83667HG_ID 0xa510 | 95 | #define SIO_W83667HG_ID 0xa510 |
| 96 | #define SIO_W83667HG_B_ID 0xb350 | ||
| 94 | #define SIO_ID_MASK 0xFFF0 | 97 | #define SIO_ID_MASK 0xFFF0 |
| 95 | 98 | ||
| 96 | static inline void | 99 | static inline void |
| @@ -201,8 +204,14 @@ static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 }; | |||
| 201 | static const u8 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 }; | 204 | static const u8 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 }; |
| 202 | static const u8 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 }; | 205 | static const u8 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 }; |
| 203 | static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 }; | 206 | static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 }; |
| 204 | static const u8 W83627EHF_REG_FAN_MAX_OUTPUT[] = { 0xff, 0x67, 0xff, 0x69 }; | 207 | |
| 205 | static const u8 W83627EHF_REG_FAN_STEP_OUTPUT[] = { 0xff, 0x68, 0xff, 0x6a }; | 208 | static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_COMMON[] |
| 209 | = { 0xff, 0x67, 0xff, 0x69 }; | ||
| 210 | static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON[] | ||
| 211 | = { 0xff, 0x68, 0xff, 0x6a }; | ||
| 212 | |||
| 213 | static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b }; | ||
| 214 | static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[] = { 0x68, 0x6a, 0x6c }; | ||
| 206 | 215 | ||
| 207 | /* | 216 | /* |
| 208 | * Conversions | 217 | * Conversions |
| @@ -277,6 +286,11 @@ struct w83627ehf_data { | |||
| 277 | struct device *hwmon_dev; | 286 | struct device *hwmon_dev; |
| 278 | struct mutex lock; | 287 | struct mutex lock; |
| 279 | 288 | ||
| 289 | const u8 *REG_FAN_START_OUTPUT; | ||
| 290 | const u8 *REG_FAN_STOP_OUTPUT; | ||
| 291 | const u8 *REG_FAN_MAX_OUTPUT; | ||
| 292 | const u8 *REG_FAN_STEP_OUTPUT; | ||
| 293 | |||
| 280 | struct mutex update_lock; | 294 | struct mutex update_lock; |
| 281 | char valid; /* !=0 if following fields are valid */ | 295 | char valid; /* !=0 if following fields are valid */ |
| 282 | unsigned long last_updated; /* In jiffies */ | 296 | unsigned long last_updated; /* In jiffies */ |
| @@ -524,7 +538,10 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | |||
| 524 | } | 538 | } |
| 525 | } | 539 | } |
| 526 | 540 | ||
| 527 | for (i = 0; i < 4; i++) { | 541 | for (i = 0; i < data->pwm_num; i++) { |
| 542 | if (!(data->has_fan & (1 << i))) | ||
| 543 | continue; | ||
| 544 | |||
| 528 | /* pwmcfg, tolerance mapped for i=0, i=1 to same reg */ | 545 | /* pwmcfg, tolerance mapped for i=0, i=1 to same reg */ |
| 529 | if (i != 1) { | 546 | if (i != 1) { |
| 530 | pwmcfg = w83627ehf_read_value(data, | 547 | pwmcfg = w83627ehf_read_value(data, |
| @@ -546,6 +563,17 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | |||
| 546 | W83627EHF_REG_FAN_STOP_OUTPUT[i]); | 563 | W83627EHF_REG_FAN_STOP_OUTPUT[i]); |
| 547 | data->fan_stop_time[i] = w83627ehf_read_value(data, | 564 | data->fan_stop_time[i] = w83627ehf_read_value(data, |
| 548 | W83627EHF_REG_FAN_STOP_TIME[i]); | 565 | W83627EHF_REG_FAN_STOP_TIME[i]); |
| 566 | |||
| 567 | if (data->REG_FAN_MAX_OUTPUT[i] != 0xff) | ||
| 568 | data->fan_max_output[i] = | ||
| 569 | w83627ehf_read_value(data, | ||
| 570 | data->REG_FAN_MAX_OUTPUT[i]); | ||
| 571 | |||
| 572 | if (data->REG_FAN_STEP_OUTPUT[i] != 0xff) | ||
| 573 | data->fan_step_output[i] = | ||
| 574 | w83627ehf_read_value(data, | ||
| 575 | data->REG_FAN_STEP_OUTPUT[i]); | ||
| 576 | |||
| 549 | data->target_temp[i] = | 577 | data->target_temp[i] = |
| 550 | w83627ehf_read_value(data, | 578 | w83627ehf_read_value(data, |
| 551 | W83627EHF_REG_TARGET[i]) & | 579 | W83627EHF_REG_TARGET[i]) & |
| @@ -1126,7 +1154,7 @@ store_##reg(struct device *dev, struct device_attribute *attr, \ | |||
| 1126 | u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \ | 1154 | u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \ |
| 1127 | mutex_lock(&data->update_lock); \ | 1155 | mutex_lock(&data->update_lock); \ |
| 1128 | data->reg[nr] = val; \ | 1156 | data->reg[nr] = val; \ |
| 1129 | w83627ehf_write_value(data, W83627EHF_REG_##REG[nr], val); \ | 1157 | w83627ehf_write_value(data, data->REG_##REG[nr], val); \ |
| 1130 | mutex_unlock(&data->update_lock); \ | 1158 | mutex_unlock(&data->update_lock); \ |
| 1131 | return count; \ | 1159 | return count; \ |
| 1132 | } | 1160 | } |
| @@ -1206,12 +1234,26 @@ static struct sensor_device_attribute sda_sf3_arrays[] = { | |||
| 1206 | store_fan_stop_output, 1), | 1234 | store_fan_stop_output, 1), |
| 1207 | SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, | 1235 | SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, |
| 1208 | store_fan_stop_output, 2), | 1236 | store_fan_stop_output, 2), |
| 1237 | }; | ||
| 1209 | 1238 | ||
| 1210 | /* pwm1 and pwm3 don't support max and step settings */ | 1239 | |
| 1240 | /* | ||
| 1241 | * pwm1 and pwm3 don't support max and step settings on all chips. | ||
| 1242 | * Need to check support while generating/removing attribute files. | ||
| 1243 | */ | ||
| 1244 | static struct sensor_device_attribute sda_sf3_max_step_arrays[] = { | ||
| 1245 | SENSOR_ATTR(pwm1_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, | ||
| 1246 | store_fan_max_output, 0), | ||
| 1247 | SENSOR_ATTR(pwm1_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, | ||
| 1248 | store_fan_step_output, 0), | ||
| 1211 | SENSOR_ATTR(pwm2_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, | 1249 | SENSOR_ATTR(pwm2_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, |
| 1212 | store_fan_max_output, 1), | 1250 | store_fan_max_output, 1), |
| 1213 | SENSOR_ATTR(pwm2_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, | 1251 | SENSOR_ATTR(pwm2_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, |
| 1214 | store_fan_step_output, 1), | 1252 | store_fan_step_output, 1), |
| 1253 | SENSOR_ATTR(pwm3_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, | ||
| 1254 | store_fan_max_output, 2), | ||
| 1255 | SENSOR_ATTR(pwm3_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, | ||
| 1256 | store_fan_step_output, 2), | ||
| 1215 | }; | 1257 | }; |
| 1216 | 1258 | ||
| 1217 | static ssize_t | 1259 | static ssize_t |
| @@ -1235,6 +1277,12 @@ static void w83627ehf_device_remove_files(struct device *dev) | |||
| 1235 | 1277 | ||
| 1236 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) | 1278 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) |
| 1237 | device_remove_file(dev, &sda_sf3_arrays[i].dev_attr); | 1279 | device_remove_file(dev, &sda_sf3_arrays[i].dev_attr); |
| 1280 | for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) { | ||
| 1281 | struct sensor_device_attribute *attr = | ||
| 1282 | &sda_sf3_max_step_arrays[i]; | ||
| 1283 | if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) | ||
| 1284 | device_remove_file(dev, &attr->dev_attr); | ||
| 1285 | } | ||
| 1238 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) | 1286 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) |
| 1239 | device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); | 1287 | device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); |
| 1240 | for (i = 0; i < data->in_num; i++) { | 1288 | for (i = 0; i < data->in_num; i++) { |
| @@ -1343,22 +1391,37 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
| 1343 | /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ | 1391 | /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ |
| 1344 | data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9; | 1392 | data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9; |
| 1345 | /* 667HG has 3 pwms */ | 1393 | /* 667HG has 3 pwms */ |
| 1346 | data->pwm_num = (sio_data->kind == w83667hg) ? 3 : 4; | 1394 | data->pwm_num = (sio_data->kind == w83667hg |
| 1395 | || sio_data->kind == w83667hg_b) ? 3 : 4; | ||
| 1347 | 1396 | ||
| 1348 | /* Check temp3 configuration bit for 667HG */ | 1397 | /* Check temp3 configuration bit for 667HG */ |
| 1349 | if (sio_data->kind == w83667hg) { | 1398 | if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) { |
| 1350 | data->temp3_disable = w83627ehf_read_value(data, | 1399 | data->temp3_disable = w83627ehf_read_value(data, |
| 1351 | W83627EHF_REG_TEMP_CONFIG[1]) & 0x01; | 1400 | W83627EHF_REG_TEMP_CONFIG[1]) & 0x01; |
| 1352 | data->in6_skip = !data->temp3_disable; | 1401 | data->in6_skip = !data->temp3_disable; |
| 1353 | } | 1402 | } |
| 1354 | 1403 | ||
| 1404 | data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT; | ||
| 1405 | data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT; | ||
| 1406 | if (sio_data->kind == w83667hg_b) { | ||
| 1407 | data->REG_FAN_MAX_OUTPUT = | ||
| 1408 | W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B; | ||
| 1409 | data->REG_FAN_STEP_OUTPUT = | ||
| 1410 | W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B; | ||
| 1411 | } else { | ||
| 1412 | data->REG_FAN_MAX_OUTPUT = | ||
| 1413 | W83627EHF_REG_FAN_MAX_OUTPUT_COMMON; | ||
| 1414 | data->REG_FAN_STEP_OUTPUT = | ||
| 1415 | W83627EHF_REG_FAN_STEP_OUTPUT_COMMON; | ||
| 1416 | } | ||
| 1417 | |||
| 1355 | /* Initialize the chip */ | 1418 | /* Initialize the chip */ |
| 1356 | w83627ehf_init_device(data); | 1419 | w83627ehf_init_device(data); |
| 1357 | 1420 | ||
| 1358 | data->vrm = vid_which_vrm(); | 1421 | data->vrm = vid_which_vrm(); |
| 1359 | superio_enter(sio_data->sioreg); | 1422 | superio_enter(sio_data->sioreg); |
| 1360 | /* Read VID value */ | 1423 | /* Read VID value */ |
| 1361 | if (sio_data->kind == w83667hg) { | 1424 | if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) { |
| 1362 | /* W83667HG has different pins for VID input and output, so | 1425 | /* W83667HG has different pins for VID input and output, so |
| 1363 | we can get the VID input values directly at logical device D | 1426 | we can get the VID input values directly at logical device D |
| 1364 | 0xe3. */ | 1427 | 0xe3. */ |
| @@ -1409,7 +1472,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
| 1409 | } | 1472 | } |
| 1410 | 1473 | ||
| 1411 | /* fan4 and fan5 share some pins with the GPIO and serial flash */ | 1474 | /* fan4 and fan5 share some pins with the GPIO and serial flash */ |
| 1412 | if (sio_data->kind == w83667hg) { | 1475 | if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) { |
| 1413 | fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20; | 1476 | fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20; |
| 1414 | fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40; | 1477 | fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40; |
| 1415 | } else { | 1478 | } else { |
| @@ -1440,6 +1503,15 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
| 1440 | &sda_sf3_arrays[i].dev_attr))) | 1503 | &sda_sf3_arrays[i].dev_attr))) |
| 1441 | goto exit_remove; | 1504 | goto exit_remove; |
| 1442 | 1505 | ||
| 1506 | for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) { | ||
| 1507 | struct sensor_device_attribute *attr = | ||
| 1508 | &sda_sf3_max_step_arrays[i]; | ||
| 1509 | if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) { | ||
| 1510 | err = device_create_file(dev, &attr->dev_attr); | ||
| 1511 | if (err) | ||
| 1512 | goto exit_remove; | ||
| 1513 | } | ||
| 1514 | } | ||
| 1443 | /* if fan4 is enabled create the sf3 files for it */ | 1515 | /* if fan4 is enabled create the sf3 files for it */ |
| 1444 | if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4) | 1516 | if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4) |
| 1445 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) { | 1517 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) { |
| @@ -1556,6 +1628,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr, | |||
| 1556 | static const char __initdata sio_name_W83627DHG[] = "W83627DHG"; | 1628 | static const char __initdata sio_name_W83627DHG[] = "W83627DHG"; |
| 1557 | static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P"; | 1629 | static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P"; |
| 1558 | static const char __initdata sio_name_W83667HG[] = "W83667HG"; | 1630 | static const char __initdata sio_name_W83667HG[] = "W83667HG"; |
| 1631 | static const char __initdata sio_name_W83667HG_B[] = "W83667HG-B"; | ||
| 1559 | 1632 | ||
| 1560 | u16 val; | 1633 | u16 val; |
| 1561 | const char *sio_name; | 1634 | const char *sio_name; |
| @@ -1588,6 +1661,10 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr, | |||
| 1588 | sio_data->kind = w83667hg; | 1661 | sio_data->kind = w83667hg; |
| 1589 | sio_name = sio_name_W83667HG; | 1662 | sio_name = sio_name_W83667HG; |
| 1590 | break; | 1663 | break; |
| 1664 | case SIO_W83667HG_B_ID: | ||
| 1665 | sio_data->kind = w83667hg_b; | ||
| 1666 | sio_name = sio_name_W83667HG_B; | ||
| 1667 | break; | ||
| 1591 | default: | 1668 | default: |
| 1592 | if (val != 0xffff) | 1669 | if (val != 0xffff) |
| 1593 | pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n", | 1670 | pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n", |
diff --git a/include/linux/i2c/ltc4245.h b/include/linux/i2c/ltc4245.h new file mode 100644 index 000000000000..56bda4be0016 --- /dev/null +++ b/include/linux/i2c/ltc4245.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | /* | ||
| 2 | * Platform Data for LTC4245 hardware monitor chip | ||
| 3 | * | ||
| 4 | * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef LINUX_LTC4245_H | ||
| 13 | #define LINUX_LTC4245_H | ||
| 14 | |||
| 15 | #include <linux/types.h> | ||
| 16 | |||
| 17 | struct ltc4245_platform_data { | ||
| 18 | bool use_extra_gpios; | ||
| 19 | }; | ||
| 20 | |||
| 21 | #endif /* LINUX_LTC4245_H */ | ||
