diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-14 17:57:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-14 17:57:58 -0400 |
commit | d310ad0c9d6354affc8abdcfb189ae1a434f18ae (patch) | |
tree | b4daa9dc377e30087b6433a6ab95cc9ef0768528 | |
parent | c29c08b59875fe053471cf9eb66f8cfef39bc509 (diff) | |
parent | f279941863f0d39fa8285b84449b52b8286a254b (diff) |
Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging: (22 commits)
hwmon: (via-cputemp) Remove bogus "SHOW" global variable
hwmon: jc42 depends on I2C
hwmon: (pc87427) Add a maintainer
hwmon: (pc87427) Move sysfs file removal to a separate function
hwmon: (pc87427) Add temperature monitoring support
hwmon: (pc87427) Add support for the second logical device
hwmon: (pc87427) Add support for manual fan speed control
hwmon: (pc87427) Minor style cleanups
hwmon: (pc87427) Handle disabled fan inputs properly
hwmon: (w83627ehf) Add support for W83667HG-B
hwmon: (w83627ehf) Driver cleanup
hwmon: Add driver for SMSC EMC2103 temperature monitor and fan controller
hwmon: Remove in[0-*]_fault from sysfs-interface
hwmon: Add 4 current alarm/beep attributes to sysfs-interface
hwmon: Add 3 critical limit attributes to sysfs-interface
hwmon: (asc7621) Clean up and improve detect function
hwmon: (it87) Export labels for internal sensors
hwmon: (lm75) Add suspend/resume feature
hwmon: (emc1403) Add power support
hwmon: (ltc4245) Expose all GPIO pins as analog voltages
...
-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 */ | ||