diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-28 19:23:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-28 19:23:27 -0400 |
commit | 2ff712585a5026a021859233fce145068292584d (patch) | |
tree | 1dda6f9fa831be1267cafe260932f0abfccc4583 | |
parent | 6174d0fd35f486f59b743630bdf088a9f9792d4d (diff) | |
parent | 3379ceeefde923a05c2c77ed2d84ba26c2fe9e81 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/hwmon-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/hwmon-2.6: (39 commits)
hwmon: Remove Yuan Mu's address
hwmon: Fix unchecked return status, SMSC chips
hwmon: Fix unchecked return status, batch 6
w83792d: Fix unchecked return status
w83l785ts: Fix unchecked return status
w83781d: Fix unchecked return status
vt8231: Fix unchecked return status
Fix unchecked return status, batch 5
hwmon: Fix unchecked return status, batch 4
hwmon: Fix unchecked return status, batch 3
hwmon: Fix unchecked return status, batch 2
w83627ehf: Fix unchecked return status
pc87360: Check for error on sysfs files creation
pc87360: Delete sysfs files on device deletion
pc87360: Move some code around
hwmon: Fix unchecked return status, batch 1
vt1211: Document module parameters
vt1211: Add documentation
hwmon: New driver for the VIA VT1211
w83791d: Documentation update
...
51 files changed, 5727 insertions, 1915 deletions
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87 index 9555be1ed999..e783fd62e308 100644 --- a/Documentation/hwmon/it87 +++ b/Documentation/hwmon/it87 | |||
@@ -13,12 +13,25 @@ Supported chips: | |||
13 | from Super I/O config space (8 I/O ports) | 13 | from Super I/O config space (8 I/O ports) |
14 | Datasheet: Publicly available at the ITE website | 14 | Datasheet: Publicly available at the ITE website |
15 | http://www.ite.com.tw/ | 15 | http://www.ite.com.tw/ |
16 | * IT8716F | ||
17 | Prefix: 'it8716' | ||
18 | Addresses scanned: from Super I/O config space (8 I/O ports) | ||
19 | Datasheet: Publicly available at the ITE website | ||
20 | http://www.ite.com.tw/product_info/file/pc/IT8716F_V0.3.ZIP | ||
21 | * IT8718F | ||
22 | Prefix: 'it8718' | ||
23 | Addresses scanned: from Super I/O config space (8 I/O ports) | ||
24 | Datasheet: Publicly available at the ITE website | ||
25 | http://www.ite.com.tw/product_info/file/pc/IT8718F_V0.2.zip | ||
26 | http://www.ite.com.tw/product_info/file/pc/IT8718F_V0%203_(for%20C%20version).zip | ||
16 | * SiS950 [clone of IT8705F] | 27 | * SiS950 [clone of IT8705F] |
17 | Prefix: 'it87' | 28 | Prefix: 'it87' |
18 | Addresses scanned: from Super I/O config space (8 I/O ports) | 29 | Addresses scanned: from Super I/O config space (8 I/O ports) |
19 | Datasheet: No longer be available | 30 | Datasheet: No longer be available |
20 | 31 | ||
21 | Author: Christophe Gauthron <chrisg@0-in.com> | 32 | Authors: |
33 | Christophe Gauthron <chrisg@0-in.com> | ||
34 | Jean Delvare <khali@linux-fr.org> | ||
22 | 35 | ||
23 | 36 | ||
24 | Module Parameters | 37 | Module Parameters |
@@ -43,26 +56,46 @@ Module Parameters | |||
43 | Description | 56 | Description |
44 | ----------- | 57 | ----------- |
45 | 58 | ||
46 | This driver implements support for the IT8705F, IT8712F and SiS950 chips. | 59 | This driver implements support for the IT8705F, IT8712F, IT8716F, |
47 | 60 | IT8718F and SiS950 chips. | |
48 | This driver also supports IT8712F, which adds SMBus access, and a VID | ||
49 | input, used to report the Vcore voltage of the Pentium processor. | ||
50 | The IT8712F additionally features VID inputs. | ||
51 | 61 | ||
52 | These chips are 'Super I/O chips', supporting floppy disks, infrared ports, | 62 | These chips are 'Super I/O chips', supporting floppy disks, infrared ports, |
53 | joysticks and other miscellaneous stuff. For hardware monitoring, they | 63 | joysticks and other miscellaneous stuff. For hardware monitoring, they |
54 | include an 'environment controller' with 3 temperature sensors, 3 fan | 64 | include an 'environment controller' with 3 temperature sensors, 3 fan |
55 | rotation speed sensors, 8 voltage sensors, and associated alarms. | 65 | rotation speed sensors, 8 voltage sensors, and associated alarms. |
56 | 66 | ||
67 | The IT8712F and IT8716F additionally feature VID inputs, used to report | ||
68 | the Vcore voltage of the processor. The early IT8712F have 5 VID pins, | ||
69 | the IT8716F and late IT8712F have 6. They are shared with other functions | ||
70 | though, so the functionality may not be available on a given system. | ||
71 | The driver dumbly assume it is there. | ||
72 | |||
73 | The IT8718F also features VID inputs (up to 8 pins) but the value is | ||
74 | stored in the Super-I/O configuration space. Due to technical limitations, | ||
75 | this value can currently only be read once at initialization time, so | ||
76 | the driver won't notice and report changes in the VID value. The two | ||
77 | upper VID bits share their pins with voltage inputs (in5 and in6) so you | ||
78 | can't have both on a given board. | ||
79 | |||
80 | The IT8716F, IT8718F and later IT8712F revisions have support for | ||
81 | 2 additional fans. They are not yet supported by the driver. | ||
82 | |||
83 | The IT8716F and IT8718F, and late IT8712F and IT8705F also have optional | ||
84 | 16-bit tachometer counters for fans 1 to 3. This is better (no more fan | ||
85 | clock divider mess) but not compatible with the older chips and | ||
86 | revisions. For now, the driver only uses the 16-bit mode on the | ||
87 | IT8716F and IT8718F. | ||
88 | |||
57 | Temperatures are measured in degrees Celsius. An alarm is triggered once | 89 | Temperatures are measured in degrees Celsius. An alarm is triggered once |
58 | when the Overtemperature Shutdown limit is crossed. | 90 | when the Overtemperature Shutdown limit is crossed. |
59 | 91 | ||
60 | Fan rotation speeds are reported in RPM (rotations per minute). An alarm is | 92 | Fan rotation speeds are reported in RPM (rotations per minute). An alarm is |
61 | triggered if the rotation speed has dropped below a programmable limit. Fan | 93 | triggered if the rotation speed has dropped below a programmable limit. When |
62 | readings can be divided by a programmable divider (1, 2, 4 or 8) to give the | 94 | 16-bit tachometer counters aren't used, fan readings can be divided by |
63 | readings more range or accuracy. Not all RPM values can accurately be | 95 | a programmable divider (1, 2, 4 or 8) to give the readings more range or |
64 | represented, so some rounding is done. With a divider of 2, the lowest | 96 | accuracy. With a divider of 2, the lowest representable value is around |
65 | representable value is around 2600 RPM. | 97 | 2600 RPM. Not all RPM values can accurately be represented, so some rounding |
98 | is done. | ||
66 | 99 | ||
67 | Voltage sensors (also known as IN sensors) report their values in volts. An | 100 | Voltage sensors (also known as IN sensors) report their values in volts. An |
68 | alarm is triggered if the voltage has crossed a programmable minimum or | 101 | alarm is triggered if the voltage has crossed a programmable minimum or |
@@ -71,9 +104,9 @@ zero'; this is important for negative voltage measurements. All voltage | |||
71 | inputs can measure voltages between 0 and 4.08 volts, with a resolution of | 104 | inputs can measure voltages between 0 and 4.08 volts, with a resolution of |
72 | 0.016 volt. The battery voltage in8 does not have limit registers. | 105 | 0.016 volt. The battery voltage in8 does not have limit registers. |
73 | 106 | ||
74 | The VID lines (IT8712F only) encode the core voltage value: the voltage | 107 | The VID lines (IT8712F/IT8716F/IT8718F) encode the core voltage value: |
75 | level your processor should work with. This is hardcoded by the mainboard | 108 | the voltage level your processor should work with. This is hardcoded by |
76 | and/or processor itself. It is a value in volts. | 109 | the mainboard and/or processor itself. It is a value in volts. |
77 | 110 | ||
78 | If an alarm triggers, it will remain triggered until the hardware register | 111 | If an alarm triggers, it will remain triggered until the hardware register |
79 | is read at least once. This means that the cause for the alarm may already | 112 | is read at least once. This means that the cause for the alarm may already |
diff --git a/Documentation/hwmon/k8temp b/Documentation/hwmon/k8temp new file mode 100644 index 000000000000..bab445ab0f52 --- /dev/null +++ b/Documentation/hwmon/k8temp | |||
@@ -0,0 +1,52 @@ | |||
1 | Kernel driver k8temp | ||
2 | ==================== | ||
3 | |||
4 | Supported chips: | ||
5 | * AMD K8 CPU | ||
6 | Prefix: 'k8temp' | ||
7 | Addresses scanned: PCI space | ||
8 | Datasheet: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf | ||
9 | |||
10 | Author: Rudolf Marek | ||
11 | Contact: Rudolf Marek <r.marek@sh.cvut.cz> | ||
12 | |||
13 | Description | ||
14 | ----------- | ||
15 | |||
16 | This driver permits reading temperature sensor(s) embedded inside AMD K8 CPUs. | ||
17 | Official documentation says that it works from revision F of K8 core, but | ||
18 | in fact it seems to be implemented for all revisions of K8 except the first | ||
19 | two revisions (SH-B0 and SH-B3). | ||
20 | |||
21 | There can be up to four temperature sensors inside single CPU. The driver | ||
22 | will auto-detect the sensors and will display only temperatures from | ||
23 | implemented sensors. | ||
24 | |||
25 | Mapping of /sys files is as follows: | ||
26 | |||
27 | temp1_input - temperature of Core 0 and "place" 0 | ||
28 | temp2_input - temperature of Core 0 and "place" 1 | ||
29 | temp3_input - temperature of Core 1 and "place" 0 | ||
30 | temp4_input - temperature of Core 1 and "place" 1 | ||
31 | |||
32 | Temperatures are measured in degrees Celsius and measurement resolution is | ||
33 | 1 degree C. It is expected that future CPU will have better resolution. The | ||
34 | temperature is updated once a second. Valid temperatures are from -49 to | ||
35 | 206 degrees C. | ||
36 | |||
37 | Temperature known as TCaseMax was specified for processors up to revision E. | ||
38 | This temperature is defined as temperature between heat-spreader and CPU | ||
39 | case, so the internal CPU temperature supplied by this driver can be higher. | ||
40 | There is no easy way how to measure the temperature which will correlate | ||
41 | with TCaseMax temperature. | ||
42 | |||
43 | For newer revisions of CPU (rev F, socket AM2) there is a mathematically | ||
44 | computed temperature called TControl, which must be lower than TControlMax. | ||
45 | |||
46 | The relationship is following: | ||
47 | |||
48 | temp1_input - TjOffset*2 < TControlMax, | ||
49 | |||
50 | TjOffset is not yet exported by the driver, TControlMax is usually | ||
51 | 70 degrees C. The rule of the thumb -> CPU temperature should not cross | ||
52 | 60 degrees C too much. | ||
diff --git a/Documentation/hwmon/vt1211 b/Documentation/hwmon/vt1211 new file mode 100644 index 000000000000..77fa633b97a8 --- /dev/null +++ b/Documentation/hwmon/vt1211 | |||
@@ -0,0 +1,206 @@ | |||
1 | Kernel driver vt1211 | ||
2 | ==================== | ||
3 | |||
4 | Supported chips: | ||
5 | * VIA VT1211 | ||
6 | Prefix: 'vt1211' | ||
7 | Addresses scanned: none, address read from Super-I/O config space | ||
8 | Datasheet: Provided by VIA upon request and under NDA | ||
9 | |||
10 | Authors: Juerg Haefliger <juergh@gmail.com> | ||
11 | |||
12 | This driver is based on the driver for kernel 2.4 by Mark D. Studebaker and | ||
13 | its port to kernel 2.6 by Lars Ekman. | ||
14 | |||
15 | Thanks to Joseph Chan and Fiona Gatt from VIA for providing documentation and | ||
16 | technical support. | ||
17 | |||
18 | |||
19 | Module Parameters | ||
20 | ----------------- | ||
21 | |||
22 | * uch_config: int Override the BIOS default universal channel (UCH) | ||
23 | configuration for channels 1-5. | ||
24 | Legal values are in the range of 0-31. Bit 0 maps to | ||
25 | UCH1, bit 1 maps to UCH2 and so on. Setting a bit to 1 | ||
26 | enables the thermal input of that particular UCH and | ||
27 | setting a bit to 0 enables the voltage input. | ||
28 | |||
29 | * int_mode: int Override the BIOS default temperature interrupt mode. | ||
30 | The only possible value is 0 which forces interrupt | ||
31 | mode 0. In this mode, any pending interrupt is cleared | ||
32 | when the status register is read but is regenerated as | ||
33 | long as the temperature stays above the hysteresis | ||
34 | limit. | ||
35 | |||
36 | Be aware that overriding BIOS defaults might cause some unwanted side effects! | ||
37 | |||
38 | |||
39 | Description | ||
40 | ----------- | ||
41 | |||
42 | The VIA VT1211 Super-I/O chip includes complete hardware monitoring | ||
43 | capabilities. It monitors 2 dedicated temperature sensor inputs (temp1 and | ||
44 | temp2), 1 dedicated voltage (in5) and 2 fans. Additionally, the chip | ||
45 | implements 5 universal input channels (UCH1-5) that can be individually | ||
46 | programmed to either monitor a voltage or a temperature. | ||
47 | |||
48 | This chip also provides manual and automatic control of fan speeds (according | ||
49 | to the datasheet). The driver only supports automatic control since the manual | ||
50 | mode doesn't seem to work as advertised in the datasheet. In fact I couldn't | ||
51 | get manual mode to work at all! Be aware that automatic mode hasn't been | ||
52 | tested very well (due to the fact that my EPIA M10000 doesn't have the fans | ||
53 | connected to the PWM outputs of the VT1211 :-(). | ||
54 | |||
55 | The following table shows the relationship between the vt1211 inputs and the | ||
56 | sysfs nodes. | ||
57 | |||
58 | Sensor Voltage Mode Temp Mode Default Use (from the datasheet) | ||
59 | ------ ------------ --------- -------------------------------- | ||
60 | Reading 1 temp1 Intel thermal diode | ||
61 | Reading 3 temp2 Internal thermal diode | ||
62 | UCH1/Reading2 in0 temp3 NTC type thermistor | ||
63 | UCH2 in1 temp4 +2.5V | ||
64 | UCH3 in2 temp5 VccP (processor core) | ||
65 | UCH4 in3 temp6 +5V | ||
66 | UCH5 in4 temp7 +12V | ||
67 | +3.3V in5 Internal VCC (+3.3V) | ||
68 | |||
69 | |||
70 | Voltage Monitoring | ||
71 | ------------------ | ||
72 | |||
73 | Voltages are sampled by an 8-bit ADC with a LSB of ~10mV. The supported input | ||
74 | range is thus from 0 to 2.60V. Voltage values outside of this range need | ||
75 | external scaling resistors. This external scaling needs to be compensated for | ||
76 | via compute lines in sensors.conf, like: | ||
77 | |||
78 | compute inx @*(1+R1/R2), @/(1+R1/R2) | ||
79 | |||
80 | The board level scaling resistors according to VIA's recommendation are as | ||
81 | follows. And this is of course totally dependent on the actual board | ||
82 | implementation :-) You will have to find documentation for your own | ||
83 | motherboard and edit sensors.conf accordingly. | ||
84 | |||
85 | Expected | ||
86 | Voltage R1 R2 Divider Raw Value | ||
87 | ----------------------------------------------- | ||
88 | +2.5V 2K 10K 1.2 2083 mV | ||
89 | VccP --- --- 1.0 1400 mV (1) | ||
90 | +5V 14K 10K 2.4 2083 mV | ||
91 | +12V 47K 10K 5.7 2105 mV | ||
92 | +3.3V (int) 2K 3.4K 1.588 3300 mV (2) | ||
93 | +3.3V (ext) 6.8K 10K 1.68 1964 mV | ||
94 | |||
95 | (1) Depending on the CPU (1.4V is for a VIA C3 Nehemiah). | ||
96 | (2) R1 and R2 for 3.3V (int) are internal to the VT1211 chip and the driver | ||
97 | performs the scaling and returns the properly scaled voltage value. | ||
98 | |||
99 | Each measured voltage has an associated low and high limit which triggers an | ||
100 | alarm when crossed. | ||
101 | |||
102 | |||
103 | Temperature Monitoring | ||
104 | ---------------------- | ||
105 | |||
106 | Temperatures are reported in millidegree Celsius. Each measured temperature | ||
107 | has a high limit which triggers an alarm if crossed. There is an associated | ||
108 | hysteresis value with each temperature below which the temperature has to drop | ||
109 | before the alarm is cleared (this is only true for interrupt mode 0). The | ||
110 | interrupt mode can be forced to 0 in case the BIOS doesn't do it | ||
111 | automatically. See the 'Module Parameters' section for details. | ||
112 | |||
113 | All temperature channels except temp2 are external. Temp2 is the VT1211 | ||
114 | internal thermal diode and the driver does all the scaling for temp2 and | ||
115 | returns the temperature in millidegree Celsius. For the external channels | ||
116 | temp1 and temp3-temp7, scaling depends on the board implementation and needs | ||
117 | to be performed in userspace via sensors.conf. | ||
118 | |||
119 | Temp1 is an Intel-type thermal diode which requires the following formula to | ||
120 | convert between sysfs readings and real temperatures: | ||
121 | |||
122 | compute temp1 (@-Offset)/Gain, (@*Gain)+Offset | ||
123 | |||
124 | According to the VIA VT1211 BIOS porting guide, the following gain and offset | ||
125 | values should be used: | ||
126 | |||
127 | Diode Type Offset Gain | ||
128 | ---------- ------ ---- | ||
129 | Intel CPU 88.638 0.9528 | ||
130 | 65.000 0.9686 *) | ||
131 | VIA C3 Ezra 83.869 0.9528 | ||
132 | VIA C3 Ezra-T 73.869 0.9528 | ||
133 | |||
134 | *) This is the formula from the lm_sensors 2.10.0 sensors.conf file. I don't | ||
135 | know where it comes from or how it was derived, it's just listed here for | ||
136 | completeness. | ||
137 | |||
138 | Temp3-temp7 support NTC thermistors. For these channels, the driver returns | ||
139 | the voltages as seen at the individual pins of UCH1-UCH5. The voltage at the | ||
140 | pin (Vpin) is formed by a voltage divider made of the thermistor (Rth) and a | ||
141 | scaling resistor (Rs): | ||
142 | |||
143 | Vpin = 2200 * Rth / (Rs + Rth) (2200 is the ADC max limit of 2200 mV) | ||
144 | |||
145 | The equation for the thermistor is as follows (google it if you want to know | ||
146 | more about it): | ||
147 | |||
148 | Rth = Ro * exp(B * (1 / T - 1 / To)) (To is 298.15K (25C) and Ro is the | ||
149 | nominal resistance at 25C) | ||
150 | |||
151 | Mingling the above two equations and assuming Rs = Ro and B = 3435 yields the | ||
152 | following formula for sensors.conf: | ||
153 | |||
154 | compute tempx 1 / (1 / 298.15 - (` (2200 / @ - 1)) / 3435) - 273.15, | ||
155 | 2200 / (1 + (^ (3435 / 298.15 - 3435 / (273.15 + @)))) | ||
156 | |||
157 | |||
158 | Fan Speed Control | ||
159 | ----------------- | ||
160 | |||
161 | The VT1211 provides 2 programmable PWM outputs to control the speeds of 2 | ||
162 | fans. Writing a 2 to any of the two pwm[1-2]_enable sysfs nodes will put the | ||
163 | PWM controller in automatic mode. There is only a single controller that | ||
164 | controls both PWM outputs but each PWM output can be individually enabled and | ||
165 | disabled. | ||
166 | |||
167 | Each PWM has 4 associated distinct output duty-cycles: full, high, low and | ||
168 | off. Full and off are internally hard-wired to 255 (100%) and 0 (0%), | ||
169 | respectively. High and low can be programmed via | ||
170 | pwm[1-2]_auto_point[2-3]_pwm. Each PWM output can be associated with a | ||
171 | different thermal input but - and here's the weird part - only one set of | ||
172 | thermal thresholds exist that controls both PWMs output duty-cycles. The | ||
173 | thermal thresholds are accessible via pwm[1-2]_auto_point[1-4]_temp. Note | ||
174 | that even though there are 2 sets of 4 auto points each, they map to the same | ||
175 | registers in the VT1211 and programming one set is sufficient (actually only | ||
176 | the first set pwm1_auto_point[1-4]_temp is writable, the second set is | ||
177 | read-only). | ||
178 | |||
179 | PWM Auto Point PWM Output Duty-Cycle | ||
180 | ------------------------------------------------ | ||
181 | pwm[1-2]_auto_point4_pwm full speed duty-cycle (hard-wired to 255) | ||
182 | pwm[1-2]_auto_point3_pwm high speed duty-cycle | ||
183 | pwm[1-2]_auto_point2_pwm low speed duty-cycle | ||
184 | pwm[1-2]_auto_point1_pwm off duty-cycle (hard-wired to 0) | ||
185 | |||
186 | Temp Auto Point Thermal Threshold | ||
187 | --------------------------------------------- | ||
188 | pwm[1-2]_auto_point4_temp full speed temp | ||
189 | pwm[1-2]_auto_point3_temp high speed temp | ||
190 | pwm[1-2]_auto_point2_temp low speed temp | ||
191 | pwm[1-2]_auto_point1_temp off temp | ||
192 | |||
193 | Long story short, the controller implements the following algorithm to set the | ||
194 | PWM output duty-cycle based on the input temperature: | ||
195 | |||
196 | Thermal Threshold Output Duty-Cycle | ||
197 | (Rising Temp) (Falling Temp) | ||
198 | ---------------------------------------------------------- | ||
199 | full speed duty-cycle full speed duty-cycle | ||
200 | full speed temp | ||
201 | high speed duty-cycle full speed duty-cycle | ||
202 | high speed temp | ||
203 | low speed duty-cycle high speed duty-cycle | ||
204 | low speed temp | ||
205 | off duty-cycle low speed duty-cycle | ||
206 | off temp | ||
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf new file mode 100644 index 000000000000..fae3b781d82d --- /dev/null +++ b/Documentation/hwmon/w83627ehf | |||
@@ -0,0 +1,85 @@ | |||
1 | Kernel driver w83627ehf | ||
2 | ======================= | ||
3 | |||
4 | Supported chips: | ||
5 | * Winbond W83627EHF/EHG (ISA access ONLY) | ||
6 | Prefix: 'w83627ehf' | ||
7 | Addresses scanned: ISA address retrieved from Super I/O registers | ||
8 | Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83627EHF_%20W83627EHGb.pdf | ||
9 | |||
10 | Authors: | ||
11 | Jean Delvare <khali@linux-fr.org> | ||
12 | Yuan Mu (Winbond) | ||
13 | Rudolf Marek <r.marek@sh.cvut.cz> | ||
14 | |||
15 | Description | ||
16 | ----------- | ||
17 | |||
18 | This driver implements support for the Winbond W83627EHF and W83627EHG | ||
19 | super I/O chips. We will refer to them collectively as Winbond chips. | ||
20 | |||
21 | The chips implement three temperature sensors, five fan rotation | ||
22 | speed sensors, ten analog voltage sensors, alarms with beep warnings (control | ||
23 | unimplemented), and some automatic fan regulation strategies (plus manual | ||
24 | fan control mode). | ||
25 | |||
26 | Temperatures are measured in degrees Celsius and measurement resolution is 1 | ||
27 | degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when | ||
28 | the temperature gets higher than high limit; it stays on until the temperature | ||
29 | falls below the Hysteresis value. | ||
30 | |||
31 | Fan rotation speeds are reported in RPM (rotations per minute). An alarm is | ||
32 | triggered if the rotation speed has dropped below a programmable limit. Fan | ||
33 | readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 or | ||
34 | 128) to give the readings more range or accuracy. The driver sets the most | ||
35 | suitable fan divisor itself. Some fans might not be present because they | ||
36 | share pins with other functions. | ||
37 | |||
38 | Voltage sensors (also known as IN sensors) report their values in millivolts. | ||
39 | An alarm is triggered if the voltage has crossed a programmable minimum | ||
40 | or maximum limit. | ||
41 | |||
42 | The driver supports automatic fan control mode known as Thermal Cruise. | ||
43 | In this mode, the chip attempts to keep the measured temperature in a | ||
44 | predefined temperature range. If the temperature goes out of range, fan | ||
45 | is driven slower/faster to reach the predefined range again. | ||
46 | |||
47 | The mode works for fan1-fan4. Mapping of temperatures to pwm outputs is as | ||
48 | follows: | ||
49 | |||
50 | temp1 -> pwm1 | ||
51 | temp2 -> pwm2 | ||
52 | temp3 -> pwm3 | ||
53 | prog -> pwm4 (the programmable setting is not supported by the driver) | ||
54 | |||
55 | /sys files | ||
56 | ---------- | ||
57 | |||
58 | pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range: | ||
59 | 0 (stop) to 255 (full) | ||
60 | |||
61 | pwm[1-4]_enable - this file controls mode of fan/temperature control: | ||
62 | * 1 Manual Mode, write to pwm file any value 0-255 (full speed) | ||
63 | * 2 Thermal Cruise | ||
64 | |||
65 | Thermal Cruise mode | ||
66 | ------------------- | ||
67 | |||
68 | If the temperature is in the range defined by: | ||
69 | |||
70 | pwm[1-4]_target - set target temperature, unit millidegree Celcius | ||
71 | (range 0 - 127000) | ||
72 | pwm[1-4]_tolerance - tolerance, unit millidegree Celcius (range 0 - 15000) | ||
73 | |||
74 | there are no changes to fan speed. Once the temperature leaves the interval, | ||
75 | fan speed increases (temp is higher) or decreases if lower than desired. | ||
76 | There are defined steps and times, but not exported by the driver yet. | ||
77 | |||
78 | pwm[1-4]_min_output - minimum fan speed (range 1 - 255), when the temperature | ||
79 | is below defined range. | ||
80 | pwm[1-4]_stop_time - how many milliseconds [ms] must elapse to switch | ||
81 | corresponding fan off. (when the temperature was below | ||
82 | defined range). | ||
83 | |||
84 | Note: last two functions are influenced by other control bits, not yet exported | ||
85 | by the driver, so a change might not have any effect. | ||
diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d index 83a3836289c2..19b2ed739fa1 100644 --- a/Documentation/hwmon/w83791d +++ b/Documentation/hwmon/w83791d | |||
@@ -5,7 +5,7 @@ Supported chips: | |||
5 | * Winbond W83791D | 5 | * Winbond W83791D |
6 | Prefix: 'w83791d' | 6 | Prefix: 'w83791d' |
7 | Addresses scanned: I2C 0x2c - 0x2f | 7 | Addresses scanned: I2C 0x2c - 0x2f |
8 | Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791Da.pdf | 8 | Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791D_W83791Gb.pdf |
9 | 9 | ||
10 | Author: Charles Spirakis <bezaur@gmail.com> | 10 | Author: Charles Spirakis <bezaur@gmail.com> |
11 | 11 | ||
@@ -20,6 +20,9 @@ Credits: | |||
20 | Chunhao Huang <DZShen@Winbond.com.tw>, | 20 | Chunhao Huang <DZShen@Winbond.com.tw>, |
21 | Rudolf Marek <r.marek@sh.cvut.cz> | 21 | Rudolf Marek <r.marek@sh.cvut.cz> |
22 | 22 | ||
23 | Additional contributors: | ||
24 | Sven Anders <anders@anduras.de> | ||
25 | |||
23 | Module Parameters | 26 | Module Parameters |
24 | ----------------- | 27 | ----------------- |
25 | 28 | ||
@@ -46,7 +49,8 @@ Module Parameters | |||
46 | Description | 49 | Description |
47 | ----------- | 50 | ----------- |
48 | 51 | ||
49 | This driver implements support for the Winbond W83791D chip. | 52 | This driver implements support for the Winbond W83791D chip. The W83791G |
53 | chip appears to be the same as the W83791D but is lead free. | ||
50 | 54 | ||
51 | Detection of the chip can sometimes be foiled because it can be in an | 55 | Detection of the chip can sometimes be foiled because it can be in an |
52 | internal state that allows no clean access (Bank with ID register is not | 56 | internal state that allows no clean access (Bank with ID register is not |
@@ -71,34 +75,36 @@ Voltage sensors (also known as IN sensors) report their values in millivolts. | |||
71 | An alarm is triggered if the voltage has crossed a programmable minimum | 75 | An alarm is triggered if the voltage has crossed a programmable minimum |
72 | or maximum limit. | 76 | or maximum limit. |
73 | 77 | ||
74 | Alarms are provided as output from a "realtime status register". The | 78 | The bit ordering for the alarm "realtime status register" and the |
75 | following bits are defined: | 79 | "beep enable registers" are different. |
76 | 80 | ||
77 | bit - alarm on: | 81 | in0 (VCORE) : alarms: 0x000001 beep_enable: 0x000001 |
78 | 0 - Vcore | 82 | in1 (VINR0) : alarms: 0x000002 beep_enable: 0x002000 <== mismatch |
79 | 1 - VINR0 | 83 | in2 (+3.3VIN): alarms: 0x000004 beep_enable: 0x000004 |
80 | 2 - +3.3VIN | 84 | in3 (5VDD) : alarms: 0x000008 beep_enable: 0x000008 |
81 | 3 - 5VDD | 85 | in4 (+12VIN) : alarms: 0x000100 beep_enable: 0x000100 |
82 | 4 - temp1 | 86 | in5 (-12VIN) : alarms: 0x000200 beep_enable: 0x000200 |
83 | 5 - temp2 | 87 | in6 (-5VIN) : alarms: 0x000400 beep_enable: 0x000400 |
84 | 6 - fan1 | 88 | in7 (VSB) : alarms: 0x080000 beep_enable: 0x010000 <== mismatch |
85 | 7 - fan2 | 89 | in8 (VBAT) : alarms: 0x100000 beep_enable: 0x020000 <== mismatch |
86 | 8 - +12VIN | 90 | in9 (VINR1) : alarms: 0x004000 beep_enable: 0x004000 |
87 | 9 - -12VIN | 91 | temp1 : alarms: 0x000010 beep_enable: 0x000010 |
88 | 10 - -5VIN | 92 | temp2 : alarms: 0x000020 beep_enable: 0x000020 |
89 | 11 - fan3 | 93 | temp3 : alarms: 0x002000 beep_enable: 0x000002 <== mismatch |
90 | 12 - chassis | 94 | fan1 : alarms: 0x000040 beep_enable: 0x000040 |
91 | 13 - temp3 | 95 | fan2 : alarms: 0x000080 beep_enable: 0x000080 |
92 | 14 - VINR1 | 96 | fan3 : alarms: 0x000800 beep_enable: 0x000800 |
93 | 15 - reserved | 97 | fan4 : alarms: 0x200000 beep_enable: 0x200000 |
94 | 16 - tart1 | 98 | fan5 : alarms: 0x400000 beep_enable: 0x400000 |
95 | 17 - tart2 | 99 | tart1 : alarms: 0x010000 beep_enable: 0x040000 <== mismatch |
96 | 18 - tart3 | 100 | tart2 : alarms: 0x020000 beep_enable: 0x080000 <== mismatch |
97 | 19 - VSB | 101 | tart3 : alarms: 0x040000 beep_enable: 0x100000 <== mismatch |
98 | 20 - VBAT | 102 | case_open : alarms: 0x001000 beep_enable: 0x001000 |
99 | 21 - fan4 | 103 | user_enable : alarms: -------- beep_enable: 0x800000 |
100 | 22 - fan5 | 104 | |
101 | 23 - reserved | 105 | *** NOTE: It is the responsibility of user-space code to handle the fact |
106 | that the beep enable and alarm bits are in different positions when using that | ||
107 | feature of the chip. | ||
102 | 108 | ||
103 | When an alarm goes off, you can be warned by a beeping signal through your | 109 | When an alarm goes off, you can be warned by a beeping signal through your |
104 | computer speaker. It is possible to enable all beeping globally, or only | 110 | computer speaker. It is possible to enable all beeping globally, or only |
@@ -109,5 +115,6 @@ often will do no harm, but will return 'old' values. | |||
109 | 115 | ||
110 | W83791D TODO: | 116 | W83791D TODO: |
111 | --------------- | 117 | --------------- |
112 | Provide a patch for per-file alarms as discussed on the mailing list | 118 | Provide a patch for per-file alarms and beep enables as defined in the hwmon |
119 | documentation (Documentation/hwmon/sysfs-interface) | ||
113 | Provide a patch for smart-fan control (still need appropriate motherboard/fans) | 120 | Provide a patch for smart-fan control (still need appropriate motherboard/fans) |
diff --git a/MAINTAINERS b/MAINTAINERS index 63673e6513b7..332b220f8a23 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3309,6 +3309,12 @@ W: http://linuxtv.org | |||
3309 | T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git | 3309 | T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git |
3310 | S: Maintained | 3310 | S: Maintained |
3311 | 3311 | ||
3312 | VT1211 HARDWARE MONITOR DRIVER | ||
3313 | P: Juerg Haefliger | ||
3314 | M: juergh@gmail.com | ||
3315 | L: lm-sensors@lm-sensors.org | ||
3316 | S: Maintained | ||
3317 | |||
3312 | VT8231 HARDWARE MONITOR DRIVER | 3318 | VT8231 HARDWARE MONITOR DRIVER |
3313 | P: Roger Lucas | 3319 | P: Roger Lucas |
3314 | M: roger@planbit.co.uk | 3320 | M: roger@planbit.co.uk |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 0e31a0c496e8..9b88b25b6edb 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -53,7 +53,7 @@ config SENSORS_ADM1021 | |||
53 | 53 | ||
54 | config SENSORS_ADM1025 | 54 | config SENSORS_ADM1025 |
55 | tristate "Analog Devices ADM1025 and compatibles" | 55 | tristate "Analog Devices ADM1025 and compatibles" |
56 | depends on HWMON && I2C && EXPERIMENTAL | 56 | depends on HWMON && I2C |
57 | select HWMON_VID | 57 | select HWMON_VID |
58 | help | 58 | help |
59 | If you say yes here you get support for Analog Devices ADM1025 | 59 | If you say yes here you get support for Analog Devices ADM1025 |
@@ -94,6 +94,16 @@ config SENSORS_ADM9240 | |||
94 | This driver can also be built as a module. If so, the module | 94 | This driver can also be built as a module. If so, the module |
95 | will be called adm9240. | 95 | will be called adm9240. |
96 | 96 | ||
97 | config SENSORS_K8TEMP | ||
98 | tristate "AMD K8 processor sensor" | ||
99 | depends on HWMON && X86 && PCI && EXPERIMENTAL | ||
100 | help | ||
101 | If you say yes here you get support for the temperature | ||
102 | sensor(s) inside your AMD K8 CPU. | ||
103 | |||
104 | This driver can also be built as a module. If so, the module | ||
105 | will be called k8temp. | ||
106 | |||
97 | config SENSORS_ASB100 | 107 | config SENSORS_ASB100 |
98 | tristate "Asus ASB100 Bach" | 108 | tristate "Asus ASB100 Bach" |
99 | depends on HWMON && I2C && EXPERIMENTAL | 109 | depends on HWMON && I2C && EXPERIMENTAL |
@@ -121,7 +131,7 @@ config SENSORS_ATXP1 | |||
121 | 131 | ||
122 | config SENSORS_DS1621 | 132 | config SENSORS_DS1621 |
123 | tristate "Dallas Semiconductor DS1621 and DS1625" | 133 | tristate "Dallas Semiconductor DS1621 and DS1625" |
124 | depends on HWMON && I2C && EXPERIMENTAL | 134 | depends on HWMON && I2C |
125 | help | 135 | help |
126 | If you say yes here you get support for Dallas Semiconductor | 136 | If you say yes here you get support for Dallas Semiconductor |
127 | DS1621 and DS1625 sensor chips. | 137 | DS1621 and DS1625 sensor chips. |
@@ -141,7 +151,7 @@ config SENSORS_F71805F | |||
141 | 151 | ||
142 | config SENSORS_FSCHER | 152 | config SENSORS_FSCHER |
143 | tristate "FSC Hermes" | 153 | tristate "FSC Hermes" |
144 | depends on HWMON && I2C && EXPERIMENTAL | 154 | depends on HWMON && I2C |
145 | help | 155 | help |
146 | If you say yes here you get support for Fujitsu Siemens | 156 | If you say yes here you get support for Fujitsu Siemens |
147 | Computers Hermes sensor chips. | 157 | Computers Hermes sensor chips. |
@@ -151,7 +161,7 @@ config SENSORS_FSCHER | |||
151 | 161 | ||
152 | config SENSORS_FSCPOS | 162 | config SENSORS_FSCPOS |
153 | tristate "FSC Poseidon" | 163 | tristate "FSC Poseidon" |
154 | depends on HWMON && I2C && EXPERIMENTAL | 164 | depends on HWMON && I2C |
155 | help | 165 | help |
156 | If you say yes here you get support for Fujitsu Siemens | 166 | If you say yes here you get support for Fujitsu Siemens |
157 | Computers Poseidon sensor chips. | 167 | Computers Poseidon sensor chips. |
@@ -171,7 +181,7 @@ config SENSORS_GL518SM | |||
171 | 181 | ||
172 | config SENSORS_GL520SM | 182 | config SENSORS_GL520SM |
173 | tristate "Genesys Logic GL520SM" | 183 | tristate "Genesys Logic GL520SM" |
174 | depends on HWMON && I2C && EXPERIMENTAL | 184 | depends on HWMON && I2C |
175 | select HWMON_VID | 185 | select HWMON_VID |
176 | help | 186 | help |
177 | If you say yes here you get support for Genesys Logic GL520SM | 187 | If you say yes here you get support for Genesys Logic GL520SM |
@@ -186,15 +196,15 @@ config SENSORS_IT87 | |||
186 | select I2C_ISA | 196 | select I2C_ISA |
187 | select HWMON_VID | 197 | select HWMON_VID |
188 | help | 198 | help |
189 | If you say yes here you get support for ITE IT87xx sensor chips | 199 | If you say yes here you get support for ITE IT8705F, IT8712F, |
190 | and clones: SiS960. | 200 | IT8716F and IT8718F sensor chips, and the SiS960 clone. |
191 | 201 | ||
192 | This driver can also be built as a module. If so, the module | 202 | This driver can also be built as a module. If so, the module |
193 | will be called it87. | 203 | will be called it87. |
194 | 204 | ||
195 | config SENSORS_LM63 | 205 | config SENSORS_LM63 |
196 | tristate "National Semiconductor LM63" | 206 | tristate "National Semiconductor LM63" |
197 | depends on HWMON && I2C && EXPERIMENTAL | 207 | depends on HWMON && I2C |
198 | help | 208 | help |
199 | If you say yes here you get support for the National Semiconductor | 209 | If you say yes here you get support for the National Semiconductor |
200 | LM63 remote diode digital temperature sensor with integrated fan | 210 | LM63 remote diode digital temperature sensor with integrated fan |
@@ -231,7 +241,7 @@ config SENSORS_LM75 | |||
231 | 241 | ||
232 | config SENSORS_LM77 | 242 | config SENSORS_LM77 |
233 | tristate "National Semiconductor LM77" | 243 | tristate "National Semiconductor LM77" |
234 | depends on HWMON && I2C && EXPERIMENTAL | 244 | depends on HWMON && I2C |
235 | help | 245 | help |
236 | If you say yes here you get support for National Semiconductor LM77 | 246 | If you say yes here you get support for National Semiconductor LM77 |
237 | sensor chips. | 247 | sensor chips. |
@@ -241,7 +251,7 @@ config SENSORS_LM77 | |||
241 | 251 | ||
242 | config SENSORS_LM78 | 252 | config SENSORS_LM78 |
243 | tristate "National Semiconductor LM78 and compatibles" | 253 | tristate "National Semiconductor LM78 and compatibles" |
244 | depends on HWMON && I2C && EXPERIMENTAL | 254 | depends on HWMON && I2C |
245 | select I2C_ISA | 255 | select I2C_ISA |
246 | select HWMON_VID | 256 | select HWMON_VID |
247 | help | 257 | help |
@@ -284,7 +294,7 @@ config SENSORS_LM85 | |||
284 | 294 | ||
285 | config SENSORS_LM87 | 295 | config SENSORS_LM87 |
286 | tristate "National Semiconductor LM87" | 296 | tristate "National Semiconductor LM87" |
287 | depends on HWMON && I2C && EXPERIMENTAL | 297 | depends on HWMON && I2C |
288 | select HWMON_VID | 298 | select HWMON_VID |
289 | help | 299 | help |
290 | If you say yes here you get support for National Semiconductor LM87 | 300 | If you say yes here you get support for National Semiconductor LM87 |
@@ -309,7 +319,7 @@ config SENSORS_LM90 | |||
309 | 319 | ||
310 | config SENSORS_LM92 | 320 | config SENSORS_LM92 |
311 | tristate "National Semiconductor LM92 and compatibles" | 321 | tristate "National Semiconductor LM92 and compatibles" |
312 | depends on HWMON && I2C && EXPERIMENTAL | 322 | depends on HWMON && I2C |
313 | help | 323 | help |
314 | If you say yes here you get support for National Semiconductor LM92 | 324 | If you say yes here you get support for National Semiconductor LM92 |
315 | and Maxim MAX6635 sensor chips. | 325 | and Maxim MAX6635 sensor chips. |
@@ -319,7 +329,7 @@ config SENSORS_LM92 | |||
319 | 329 | ||
320 | config SENSORS_MAX1619 | 330 | config SENSORS_MAX1619 |
321 | tristate "Maxim MAX1619 sensor chip" | 331 | tristate "Maxim MAX1619 sensor chip" |
322 | depends on HWMON && I2C && EXPERIMENTAL | 332 | depends on HWMON && I2C |
323 | help | 333 | help |
324 | If you say yes here you get support for MAX1619 sensor chip. | 334 | If you say yes here you get support for MAX1619 sensor chip. |
325 | 335 | ||
@@ -354,7 +364,7 @@ config SENSORS_SIS5595 | |||
354 | 364 | ||
355 | config SENSORS_SMSC47M1 | 365 | config SENSORS_SMSC47M1 |
356 | tristate "SMSC LPC47M10x and compatibles" | 366 | tristate "SMSC LPC47M10x and compatibles" |
357 | depends on HWMON && I2C && EXPERIMENTAL | 367 | depends on HWMON && I2C |
358 | select I2C_ISA | 368 | select I2C_ISA |
359 | help | 369 | help |
360 | If you say yes here you get support for the integrated fan | 370 | If you say yes here you get support for the integrated fan |
@@ -407,8 +417,19 @@ config SENSORS_VIA686A | |||
407 | This driver can also be built as a module. If so, the module | 417 | This driver can also be built as a module. If so, the module |
408 | will be called via686a. | 418 | will be called via686a. |
409 | 419 | ||
420 | config SENSORS_VT1211 | ||
421 | tristate "VIA VT1211" | ||
422 | depends on HWMON && EXPERIMENTAL | ||
423 | select HWMON_VID | ||
424 | help | ||
425 | If you say yes here then you get support for hardware monitoring | ||
426 | features of the VIA VT1211 Super-I/O chip. | ||
427 | |||
428 | This driver can also be built as a module. If so, the module | ||
429 | will be called vt1211. | ||
430 | |||
410 | config SENSORS_VT8231 | 431 | config SENSORS_VT8231 |
411 | tristate "VT8231" | 432 | tristate "VIA VT8231" |
412 | depends on HWMON && I2C && PCI && EXPERIMENTAL | 433 | depends on HWMON && I2C && PCI && EXPERIMENTAL |
413 | select HWMON_VID | 434 | select HWMON_VID |
414 | select I2C_ISA | 435 | select I2C_ISA |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 31415843a91a..af01cc64f7d2 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -27,6 +27,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o | |||
27 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o | 27 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o |
28 | obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o | 28 | obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o |
29 | obj-$(CONFIG_SENSORS_IT87) += it87.o | 29 | obj-$(CONFIG_SENSORS_IT87) += it87.o |
30 | obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o | ||
30 | obj-$(CONFIG_SENSORS_LM63) += lm63.o | 31 | obj-$(CONFIG_SENSORS_LM63) += lm63.o |
31 | obj-$(CONFIG_SENSORS_LM70) += lm70.o | 32 | obj-$(CONFIG_SENSORS_LM70) += lm70.o |
32 | obj-$(CONFIG_SENSORS_LM75) += lm75.o | 33 | obj-$(CONFIG_SENSORS_LM75) += lm75.o |
@@ -45,6 +46,7 @@ obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o | |||
45 | obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o | 46 | obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o |
46 | obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o | 47 | obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o |
47 | obj-$(CONFIG_SENSORS_VIA686A) += via686a.o | 48 | obj-$(CONFIG_SENSORS_VIA686A) += via686a.o |
49 | obj-$(CONFIG_SENSORS_VT1211) += vt1211.o | ||
48 | obj-$(CONFIG_SENSORS_VT8231) += vt8231.o | 50 | obj-$(CONFIG_SENSORS_VT8231) += vt8231.o |
49 | obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o | 51 | obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o |
50 | obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o | 52 | obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o |
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index 35ad1b032726..e5cb0fdab9b1 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c | |||
@@ -1354,13 +1354,39 @@ LEAVE_UPDATE: | |||
1354 | return NULL; | 1354 | return NULL; |
1355 | } | 1355 | } |
1356 | 1356 | ||
1357 | #ifdef CONFIG_PM | ||
1358 | static int abituguru_suspend(struct platform_device *pdev, pm_message_t state) | ||
1359 | { | ||
1360 | struct abituguru_data *data = platform_get_drvdata(pdev); | ||
1361 | /* make sure all communications with the uguru are done and no new | ||
1362 | ones are started */ | ||
1363 | mutex_lock(&data->update_lock); | ||
1364 | return 0; | ||
1365 | } | ||
1366 | |||
1367 | static int abituguru_resume(struct platform_device *pdev) | ||
1368 | { | ||
1369 | struct abituguru_data *data = platform_get_drvdata(pdev); | ||
1370 | /* See if the uGuru is still ready */ | ||
1371 | if (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT) | ||
1372 | data->uguru_ready = 0; | ||
1373 | mutex_unlock(&data->update_lock); | ||
1374 | return 0; | ||
1375 | } | ||
1376 | #else | ||
1377 | #define abituguru_suspend NULL | ||
1378 | #define abituguru_resume NULL | ||
1379 | #endif /* CONFIG_PM */ | ||
1380 | |||
1357 | static struct platform_driver abituguru_driver = { | 1381 | static struct platform_driver abituguru_driver = { |
1358 | .driver = { | 1382 | .driver = { |
1359 | .owner = THIS_MODULE, | 1383 | .owner = THIS_MODULE, |
1360 | .name = ABIT_UGURU_NAME, | 1384 | .name = ABIT_UGURU_NAME, |
1361 | }, | 1385 | }, |
1362 | .probe = abituguru_probe, | 1386 | .probe = abituguru_probe, |
1363 | .remove = __devexit_p(abituguru_remove), | 1387 | .remove = __devexit_p(abituguru_remove), |
1388 | .suspend = abituguru_suspend, | ||
1389 | .resume = abituguru_resume, | ||
1364 | }; | 1390 | }; |
1365 | 1391 | ||
1366 | static int __init abituguru_detect(void) | 1392 | static int __init abituguru_detect(void) |
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index 2b6e74dd4a82..c466329b2ef4 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c | |||
@@ -190,6 +190,21 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter) | |||
190 | return i2c_probe(adapter, &addr_data, adm1021_detect); | 190 | return i2c_probe(adapter, &addr_data, adm1021_detect); |
191 | } | 191 | } |
192 | 192 | ||
193 | static struct attribute *adm1021_attributes[] = { | ||
194 | &dev_attr_temp1_max.attr, | ||
195 | &dev_attr_temp1_min.attr, | ||
196 | &dev_attr_temp1_input.attr, | ||
197 | &dev_attr_temp2_max.attr, | ||
198 | &dev_attr_temp2_min.attr, | ||
199 | &dev_attr_temp2_input.attr, | ||
200 | &dev_attr_alarms.attr, | ||
201 | NULL | ||
202 | }; | ||
203 | |||
204 | static const struct attribute_group adm1021_group = { | ||
205 | .attrs = adm1021_attributes, | ||
206 | }; | ||
207 | |||
193 | static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) | 208 | static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) |
194 | { | 209 | { |
195 | int i; | 210 | int i; |
@@ -287,22 +302,19 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) | |||
287 | adm1021_init_client(new_client); | 302 | adm1021_init_client(new_client); |
288 | 303 | ||
289 | /* Register sysfs hooks */ | 304 | /* Register sysfs hooks */ |
305 | if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1021_group))) | ||
306 | goto error2; | ||
307 | |||
290 | data->class_dev = hwmon_device_register(&new_client->dev); | 308 | data->class_dev = hwmon_device_register(&new_client->dev); |
291 | if (IS_ERR(data->class_dev)) { | 309 | if (IS_ERR(data->class_dev)) { |
292 | err = PTR_ERR(data->class_dev); | 310 | err = PTR_ERR(data->class_dev); |
293 | goto error2; | 311 | goto error3; |
294 | } | 312 | } |
295 | 313 | ||
296 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
297 | device_create_file(&new_client->dev, &dev_attr_temp1_min); | ||
298 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
299 | device_create_file(&new_client->dev, &dev_attr_temp2_max); | ||
300 | device_create_file(&new_client->dev, &dev_attr_temp2_min); | ||
301 | device_create_file(&new_client->dev, &dev_attr_temp2_input); | ||
302 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
303 | |||
304 | return 0; | 314 | return 0; |
305 | 315 | ||
316 | error3: | ||
317 | sysfs_remove_group(&new_client->dev.kobj, &adm1021_group); | ||
306 | error2: | 318 | error2: |
307 | i2c_detach_client(new_client); | 319 | i2c_detach_client(new_client); |
308 | error1: | 320 | error1: |
@@ -326,6 +338,7 @@ static int adm1021_detach_client(struct i2c_client *client) | |||
326 | int err; | 338 | int err; |
327 | 339 | ||
328 | hwmon_device_unregister(data->class_dev); | 340 | hwmon_device_unregister(data->class_dev); |
341 | sysfs_remove_group(&client->dev.kobj, &adm1021_group); | ||
329 | 342 | ||
330 | if ((err = i2c_detach_client(client))) | 343 | if ((err = i2c_detach_client(client))) |
331 | return err; | 344 | return err; |
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index a4c859c9fbf8..8c562885b54b 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c | |||
@@ -315,6 +315,49 @@ static int adm1025_attach_adapter(struct i2c_adapter *adapter) | |||
315 | return i2c_probe(adapter, &addr_data, adm1025_detect); | 315 | return i2c_probe(adapter, &addr_data, adm1025_detect); |
316 | } | 316 | } |
317 | 317 | ||
318 | static struct attribute *adm1025_attributes[] = { | ||
319 | &dev_attr_in0_input.attr, | ||
320 | &dev_attr_in1_input.attr, | ||
321 | &dev_attr_in2_input.attr, | ||
322 | &dev_attr_in3_input.attr, | ||
323 | &dev_attr_in5_input.attr, | ||
324 | &dev_attr_in0_min.attr, | ||
325 | &dev_attr_in1_min.attr, | ||
326 | &dev_attr_in2_min.attr, | ||
327 | &dev_attr_in3_min.attr, | ||
328 | &dev_attr_in5_min.attr, | ||
329 | &dev_attr_in0_max.attr, | ||
330 | &dev_attr_in1_max.attr, | ||
331 | &dev_attr_in2_max.attr, | ||
332 | &dev_attr_in3_max.attr, | ||
333 | &dev_attr_in5_max.attr, | ||
334 | &dev_attr_temp1_input.attr, | ||
335 | &dev_attr_temp2_input.attr, | ||
336 | &dev_attr_temp1_min.attr, | ||
337 | &dev_attr_temp2_min.attr, | ||
338 | &dev_attr_temp1_max.attr, | ||
339 | &dev_attr_temp2_max.attr, | ||
340 | &dev_attr_alarms.attr, | ||
341 | &dev_attr_cpu0_vid.attr, | ||
342 | &dev_attr_vrm.attr, | ||
343 | NULL | ||
344 | }; | ||
345 | |||
346 | static const struct attribute_group adm1025_group = { | ||
347 | .attrs = adm1025_attributes, | ||
348 | }; | ||
349 | |||
350 | static struct attribute *adm1025_attributes_opt[] = { | ||
351 | &dev_attr_in4_input.attr, | ||
352 | &dev_attr_in4_min.attr, | ||
353 | &dev_attr_in4_max.attr, | ||
354 | NULL | ||
355 | }; | ||
356 | |||
357 | static const struct attribute_group adm1025_group_opt = { | ||
358 | .attrs = adm1025_attributes_opt, | ||
359 | }; | ||
360 | |||
318 | /* | 361 | /* |
319 | * The following function does more than just detection. If detection | 362 | * The following function does more than just detection. If detection |
320 | * succeeds, it also registers the new chip. | 363 | * succeeds, it also registers the new chip. |
@@ -415,46 +458,31 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) | |||
415 | adm1025_init_client(new_client); | 458 | adm1025_init_client(new_client); |
416 | 459 | ||
417 | /* Register sysfs hooks */ | 460 | /* Register sysfs hooks */ |
418 | data->class_dev = hwmon_device_register(&new_client->dev); | 461 | if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1025_group))) |
419 | if (IS_ERR(data->class_dev)) { | ||
420 | err = PTR_ERR(data->class_dev); | ||
421 | goto exit_detach; | 462 | goto exit_detach; |
422 | } | ||
423 | |||
424 | device_create_file(&new_client->dev, &dev_attr_in0_input); | ||
425 | device_create_file(&new_client->dev, &dev_attr_in1_input); | ||
426 | device_create_file(&new_client->dev, &dev_attr_in2_input); | ||
427 | device_create_file(&new_client->dev, &dev_attr_in3_input); | ||
428 | device_create_file(&new_client->dev, &dev_attr_in5_input); | ||
429 | device_create_file(&new_client->dev, &dev_attr_in0_min); | ||
430 | device_create_file(&new_client->dev, &dev_attr_in1_min); | ||
431 | device_create_file(&new_client->dev, &dev_attr_in2_min); | ||
432 | device_create_file(&new_client->dev, &dev_attr_in3_min); | ||
433 | device_create_file(&new_client->dev, &dev_attr_in5_min); | ||
434 | device_create_file(&new_client->dev, &dev_attr_in0_max); | ||
435 | device_create_file(&new_client->dev, &dev_attr_in1_max); | ||
436 | device_create_file(&new_client->dev, &dev_attr_in2_max); | ||
437 | device_create_file(&new_client->dev, &dev_attr_in3_max); | ||
438 | device_create_file(&new_client->dev, &dev_attr_in5_max); | ||
439 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
440 | device_create_file(&new_client->dev, &dev_attr_temp2_input); | ||
441 | device_create_file(&new_client->dev, &dev_attr_temp1_min); | ||
442 | device_create_file(&new_client->dev, &dev_attr_temp2_min); | ||
443 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
444 | device_create_file(&new_client->dev, &dev_attr_temp2_max); | ||
445 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
446 | device_create_file(&new_client->dev, &dev_attr_cpu0_vid); | ||
447 | device_create_file(&new_client->dev, &dev_attr_vrm); | ||
448 | 463 | ||
449 | /* Pin 11 is either in4 (+12V) or VID4 */ | 464 | /* Pin 11 is either in4 (+12V) or VID4 */ |
450 | if (!(config & 0x20)) { | 465 | if (!(config & 0x20)) { |
451 | device_create_file(&new_client->dev, &dev_attr_in4_input); | 466 | if ((err = device_create_file(&new_client->dev, |
452 | device_create_file(&new_client->dev, &dev_attr_in4_min); | 467 | &dev_attr_in4_input)) |
453 | device_create_file(&new_client->dev, &dev_attr_in4_max); | 468 | || (err = device_create_file(&new_client->dev, |
469 | &dev_attr_in4_min)) | ||
470 | || (err = device_create_file(&new_client->dev, | ||
471 | &dev_attr_in4_max))) | ||
472 | goto exit_remove; | ||
473 | } | ||
474 | |||
475 | data->class_dev = hwmon_device_register(&new_client->dev); | ||
476 | if (IS_ERR(data->class_dev)) { | ||
477 | err = PTR_ERR(data->class_dev); | ||
478 | goto exit_remove; | ||
454 | } | 479 | } |
455 | 480 | ||
456 | return 0; | 481 | return 0; |
457 | 482 | ||
483 | exit_remove: | ||
484 | sysfs_remove_group(&new_client->dev.kobj, &adm1025_group); | ||
485 | sysfs_remove_group(&new_client->dev.kobj, &adm1025_group_opt); | ||
458 | exit_detach: | 486 | exit_detach: |
459 | i2c_detach_client(new_client); | 487 | i2c_detach_client(new_client); |
460 | exit_free: | 488 | exit_free: |
@@ -511,6 +539,8 @@ static int adm1025_detach_client(struct i2c_client *client) | |||
511 | int err; | 539 | int err; |
512 | 540 | ||
513 | hwmon_device_unregister(data->class_dev); | 541 | hwmon_device_unregister(data->class_dev); |
542 | sysfs_remove_group(&client->dev.kobj, &adm1025_group); | ||
543 | sysfs_remove_group(&client->dev.kobj, &adm1025_group_opt); | ||
514 | 544 | ||
515 | if ((err = i2c_detach_client(client))) | 545 | if ((err = i2c_detach_client(client))) |
516 | return err; | 546 | return err; |
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index 6d4f8b8d358e..b4618b2705f7 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c | |||
@@ -323,15 +323,6 @@ static int adm1026_attach_adapter(struct i2c_adapter *adapter) | |||
323 | return i2c_probe(adapter, &addr_data, adm1026_detect); | 323 | return i2c_probe(adapter, &addr_data, adm1026_detect); |
324 | } | 324 | } |
325 | 325 | ||
326 | static int adm1026_detach_client(struct i2c_client *client) | ||
327 | { | ||
328 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
329 | hwmon_device_unregister(data->class_dev); | ||
330 | i2c_detach_client(client); | ||
331 | kfree(data); | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static int adm1026_read_value(struct i2c_client *client, u8 reg) | 326 | static int adm1026_read_value(struct i2c_client *client, u8 reg) |
336 | { | 327 | { |
337 | int res; | 328 | int res; |
@@ -1450,6 +1441,135 @@ static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); | |||
1450 | static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); | 1441 | static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); |
1451 | static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); | 1442 | static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); |
1452 | 1443 | ||
1444 | static struct attribute *adm1026_attributes[] = { | ||
1445 | &sensor_dev_attr_in0_input.dev_attr.attr, | ||
1446 | &sensor_dev_attr_in0_max.dev_attr.attr, | ||
1447 | &sensor_dev_attr_in0_min.dev_attr.attr, | ||
1448 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
1449 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
1450 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
1451 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
1452 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
1453 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
1454 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
1455 | &sensor_dev_attr_in3_max.dev_attr.attr, | ||
1456 | &sensor_dev_attr_in3_min.dev_attr.attr, | ||
1457 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
1458 | &sensor_dev_attr_in4_max.dev_attr.attr, | ||
1459 | &sensor_dev_attr_in4_min.dev_attr.attr, | ||
1460 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
1461 | &sensor_dev_attr_in5_max.dev_attr.attr, | ||
1462 | &sensor_dev_attr_in5_min.dev_attr.attr, | ||
1463 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
1464 | &sensor_dev_attr_in6_max.dev_attr.attr, | ||
1465 | &sensor_dev_attr_in6_min.dev_attr.attr, | ||
1466 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
1467 | &sensor_dev_attr_in7_max.dev_attr.attr, | ||
1468 | &sensor_dev_attr_in7_min.dev_attr.attr, | ||
1469 | &sensor_dev_attr_in8_input.dev_attr.attr, | ||
1470 | &sensor_dev_attr_in8_max.dev_attr.attr, | ||
1471 | &sensor_dev_attr_in8_min.dev_attr.attr, | ||
1472 | &sensor_dev_attr_in9_input.dev_attr.attr, | ||
1473 | &sensor_dev_attr_in9_max.dev_attr.attr, | ||
1474 | &sensor_dev_attr_in9_min.dev_attr.attr, | ||
1475 | &sensor_dev_attr_in10_input.dev_attr.attr, | ||
1476 | &sensor_dev_attr_in10_max.dev_attr.attr, | ||
1477 | &sensor_dev_attr_in10_min.dev_attr.attr, | ||
1478 | &sensor_dev_attr_in11_input.dev_attr.attr, | ||
1479 | &sensor_dev_attr_in11_max.dev_attr.attr, | ||
1480 | &sensor_dev_attr_in11_min.dev_attr.attr, | ||
1481 | &sensor_dev_attr_in12_input.dev_attr.attr, | ||
1482 | &sensor_dev_attr_in12_max.dev_attr.attr, | ||
1483 | &sensor_dev_attr_in12_min.dev_attr.attr, | ||
1484 | &sensor_dev_attr_in13_input.dev_attr.attr, | ||
1485 | &sensor_dev_attr_in13_max.dev_attr.attr, | ||
1486 | &sensor_dev_attr_in13_min.dev_attr.attr, | ||
1487 | &sensor_dev_attr_in14_input.dev_attr.attr, | ||
1488 | &sensor_dev_attr_in14_max.dev_attr.attr, | ||
1489 | &sensor_dev_attr_in14_min.dev_attr.attr, | ||
1490 | &sensor_dev_attr_in15_input.dev_attr.attr, | ||
1491 | &sensor_dev_attr_in15_max.dev_attr.attr, | ||
1492 | &sensor_dev_attr_in15_min.dev_attr.attr, | ||
1493 | &sensor_dev_attr_in16_input.dev_attr.attr, | ||
1494 | &sensor_dev_attr_in16_max.dev_attr.attr, | ||
1495 | &sensor_dev_attr_in16_min.dev_attr.attr, | ||
1496 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
1497 | &sensor_dev_attr_fan1_div.dev_attr.attr, | ||
1498 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
1499 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
1500 | &sensor_dev_attr_fan2_div.dev_attr.attr, | ||
1501 | &sensor_dev_attr_fan2_min.dev_attr.attr, | ||
1502 | &sensor_dev_attr_fan3_input.dev_attr.attr, | ||
1503 | &sensor_dev_attr_fan3_div.dev_attr.attr, | ||
1504 | &sensor_dev_attr_fan3_min.dev_attr.attr, | ||
1505 | &sensor_dev_attr_fan4_input.dev_attr.attr, | ||
1506 | &sensor_dev_attr_fan4_div.dev_attr.attr, | ||
1507 | &sensor_dev_attr_fan4_min.dev_attr.attr, | ||
1508 | &sensor_dev_attr_fan5_input.dev_attr.attr, | ||
1509 | &sensor_dev_attr_fan5_div.dev_attr.attr, | ||
1510 | &sensor_dev_attr_fan5_min.dev_attr.attr, | ||
1511 | &sensor_dev_attr_fan6_input.dev_attr.attr, | ||
1512 | &sensor_dev_attr_fan6_div.dev_attr.attr, | ||
1513 | &sensor_dev_attr_fan6_min.dev_attr.attr, | ||
1514 | &sensor_dev_attr_fan7_input.dev_attr.attr, | ||
1515 | &sensor_dev_attr_fan7_div.dev_attr.attr, | ||
1516 | &sensor_dev_attr_fan7_min.dev_attr.attr, | ||
1517 | &sensor_dev_attr_fan8_input.dev_attr.attr, | ||
1518 | &sensor_dev_attr_fan8_div.dev_attr.attr, | ||
1519 | &sensor_dev_attr_fan8_min.dev_attr.attr, | ||
1520 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
1521 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
1522 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
1523 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
1524 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
1525 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
1526 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
1527 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
1528 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
1529 | &sensor_dev_attr_temp1_offset.dev_attr.attr, | ||
1530 | &sensor_dev_attr_temp2_offset.dev_attr.attr, | ||
1531 | &sensor_dev_attr_temp3_offset.dev_attr.attr, | ||
1532 | &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, | ||
1533 | &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, | ||
1534 | &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, | ||
1535 | &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr, | ||
1536 | &sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr, | ||
1537 | &sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr, | ||
1538 | &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, | ||
1539 | &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, | ||
1540 | &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, | ||
1541 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
1542 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | ||
1543 | &sensor_dev_attr_temp3_crit.dev_attr.attr, | ||
1544 | &dev_attr_temp1_crit_enable.attr, | ||
1545 | &dev_attr_temp2_crit_enable.attr, | ||
1546 | &dev_attr_temp3_crit_enable.attr, | ||
1547 | &dev_attr_cpu0_vid.attr, | ||
1548 | &dev_attr_vrm.attr, | ||
1549 | &dev_attr_alarms.attr, | ||
1550 | &dev_attr_alarm_mask.attr, | ||
1551 | &dev_attr_gpio.attr, | ||
1552 | &dev_attr_gpio_mask.attr, | ||
1553 | &dev_attr_pwm1.attr, | ||
1554 | &dev_attr_pwm2.attr, | ||
1555 | &dev_attr_pwm3.attr, | ||
1556 | &dev_attr_pwm1_enable.attr, | ||
1557 | &dev_attr_pwm2_enable.attr, | ||
1558 | &dev_attr_pwm3_enable.attr, | ||
1559 | &dev_attr_temp1_auto_point1_pwm.attr, | ||
1560 | &dev_attr_temp2_auto_point1_pwm.attr, | ||
1561 | &dev_attr_temp3_auto_point1_pwm.attr, | ||
1562 | &dev_attr_temp1_auto_point2_pwm.attr, | ||
1563 | &dev_attr_temp2_auto_point2_pwm.attr, | ||
1564 | &dev_attr_temp3_auto_point2_pwm.attr, | ||
1565 | &dev_attr_analog_out.attr, | ||
1566 | NULL | ||
1567 | }; | ||
1568 | |||
1569 | static const struct attribute_group adm1026_group = { | ||
1570 | .attrs = adm1026_attributes, | ||
1571 | }; | ||
1572 | |||
1453 | static int adm1026_detect(struct i2c_adapter *adapter, int address, | 1573 | static int adm1026_detect(struct i2c_adapter *adapter, int address, |
1454 | int kind) | 1574 | int kind) |
1455 | { | 1575 | { |
@@ -1554,145 +1674,20 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, | |||
1554 | adm1026_init_client(new_client); | 1674 | adm1026_init_client(new_client); |
1555 | 1675 | ||
1556 | /* Register sysfs hooks */ | 1676 | /* Register sysfs hooks */ |
1677 | if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1026_group))) | ||
1678 | goto exitdetach; | ||
1679 | |||
1557 | data->class_dev = hwmon_device_register(&new_client->dev); | 1680 | data->class_dev = hwmon_device_register(&new_client->dev); |
1558 | if (IS_ERR(data->class_dev)) { | 1681 | if (IS_ERR(data->class_dev)) { |
1559 | err = PTR_ERR(data->class_dev); | 1682 | err = PTR_ERR(data->class_dev); |
1560 | goto exitdetach; | 1683 | goto exitremove; |
1561 | } | 1684 | } |
1562 | 1685 | ||
1563 | device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr); | ||
1564 | device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr); | ||
1565 | device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr); | ||
1566 | device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr); | ||
1567 | device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr); | ||
1568 | device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr); | ||
1569 | device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr); | ||
1570 | device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr); | ||
1571 | device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr); | ||
1572 | device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr); | ||
1573 | device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr); | ||
1574 | device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr); | ||
1575 | device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr); | ||
1576 | device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr); | ||
1577 | device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr); | ||
1578 | device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr); | ||
1579 | device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr); | ||
1580 | device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr); | ||
1581 | device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr); | ||
1582 | device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr); | ||
1583 | device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr); | ||
1584 | device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr); | ||
1585 | device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr); | ||
1586 | device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr); | ||
1587 | device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr); | ||
1588 | device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr); | ||
1589 | device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr); | ||
1590 | device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr); | ||
1591 | device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr); | ||
1592 | device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr); | ||
1593 | device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr); | ||
1594 | device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr); | ||
1595 | device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr); | ||
1596 | device_create_file(&new_client->dev, &sensor_dev_attr_in11_input.dev_attr); | ||
1597 | device_create_file(&new_client->dev, &sensor_dev_attr_in11_max.dev_attr); | ||
1598 | device_create_file(&new_client->dev, &sensor_dev_attr_in11_min.dev_attr); | ||
1599 | device_create_file(&new_client->dev, &sensor_dev_attr_in12_input.dev_attr); | ||
1600 | device_create_file(&new_client->dev, &sensor_dev_attr_in12_max.dev_attr); | ||
1601 | device_create_file(&new_client->dev, &sensor_dev_attr_in12_min.dev_attr); | ||
1602 | device_create_file(&new_client->dev, &sensor_dev_attr_in13_input.dev_attr); | ||
1603 | device_create_file(&new_client->dev, &sensor_dev_attr_in13_max.dev_attr); | ||
1604 | device_create_file(&new_client->dev, &sensor_dev_attr_in13_min.dev_attr); | ||
1605 | device_create_file(&new_client->dev, &sensor_dev_attr_in14_input.dev_attr); | ||
1606 | device_create_file(&new_client->dev, &sensor_dev_attr_in14_max.dev_attr); | ||
1607 | device_create_file(&new_client->dev, &sensor_dev_attr_in14_min.dev_attr); | ||
1608 | device_create_file(&new_client->dev, &sensor_dev_attr_in15_input.dev_attr); | ||
1609 | device_create_file(&new_client->dev, &sensor_dev_attr_in15_max.dev_attr); | ||
1610 | device_create_file(&new_client->dev, &sensor_dev_attr_in15_min.dev_attr); | ||
1611 | device_create_file(&new_client->dev, &sensor_dev_attr_in16_input.dev_attr); | ||
1612 | device_create_file(&new_client->dev, &sensor_dev_attr_in16_max.dev_attr); | ||
1613 | device_create_file(&new_client->dev, &sensor_dev_attr_in16_min.dev_attr); | ||
1614 | device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr); | ||
1615 | device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr); | ||
1616 | device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr); | ||
1617 | device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr); | ||
1618 | device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr); | ||
1619 | device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr); | ||
1620 | device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr); | ||
1621 | device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr); | ||
1622 | device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr); | ||
1623 | device_create_file(&new_client->dev, &sensor_dev_attr_fan4_input.dev_attr); | ||
1624 | device_create_file(&new_client->dev, &sensor_dev_attr_fan4_div.dev_attr); | ||
1625 | device_create_file(&new_client->dev, &sensor_dev_attr_fan4_min.dev_attr); | ||
1626 | device_create_file(&new_client->dev, &sensor_dev_attr_fan5_input.dev_attr); | ||
1627 | device_create_file(&new_client->dev, &sensor_dev_attr_fan5_div.dev_attr); | ||
1628 | device_create_file(&new_client->dev, &sensor_dev_attr_fan5_min.dev_attr); | ||
1629 | device_create_file(&new_client->dev, &sensor_dev_attr_fan6_input.dev_attr); | ||
1630 | device_create_file(&new_client->dev, &sensor_dev_attr_fan6_div.dev_attr); | ||
1631 | device_create_file(&new_client->dev, &sensor_dev_attr_fan6_min.dev_attr); | ||
1632 | device_create_file(&new_client->dev, &sensor_dev_attr_fan7_input.dev_attr); | ||
1633 | device_create_file(&new_client->dev, &sensor_dev_attr_fan7_div.dev_attr); | ||
1634 | device_create_file(&new_client->dev, &sensor_dev_attr_fan7_min.dev_attr); | ||
1635 | device_create_file(&new_client->dev, &sensor_dev_attr_fan8_input.dev_attr); | ||
1636 | device_create_file(&new_client->dev, &sensor_dev_attr_fan8_div.dev_attr); | ||
1637 | device_create_file(&new_client->dev, &sensor_dev_attr_fan8_min.dev_attr); | ||
1638 | device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr); | ||
1639 | device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr); | ||
1640 | device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr); | ||
1641 | device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr); | ||
1642 | device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr); | ||
1643 | device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr); | ||
1644 | device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr); | ||
1645 | device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr); | ||
1646 | device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr); | ||
1647 | device_create_file(&new_client->dev, &sensor_dev_attr_temp1_offset.dev_attr); | ||
1648 | device_create_file(&new_client->dev, &sensor_dev_attr_temp2_offset.dev_attr); | ||
1649 | device_create_file(&new_client->dev, &sensor_dev_attr_temp3_offset.dev_attr); | ||
1650 | device_create_file(&new_client->dev, | ||
1651 | &sensor_dev_attr_temp1_auto_point1_temp.dev_attr); | ||
1652 | device_create_file(&new_client->dev, | ||
1653 | &sensor_dev_attr_temp2_auto_point1_temp.dev_attr); | ||
1654 | device_create_file(&new_client->dev, | ||
1655 | &sensor_dev_attr_temp3_auto_point1_temp.dev_attr); | ||
1656 | device_create_file(&new_client->dev, | ||
1657 | &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr); | ||
1658 | device_create_file(&new_client->dev, | ||
1659 | &sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr); | ||
1660 | device_create_file(&new_client->dev, | ||
1661 | &sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr); | ||
1662 | device_create_file(&new_client->dev, | ||
1663 | &sensor_dev_attr_temp1_auto_point2_temp.dev_attr); | ||
1664 | device_create_file(&new_client->dev, | ||
1665 | &sensor_dev_attr_temp2_auto_point2_temp.dev_attr); | ||
1666 | device_create_file(&new_client->dev, | ||
1667 | &sensor_dev_attr_temp3_auto_point2_temp.dev_attr); | ||
1668 | device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr); | ||
1669 | device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr); | ||
1670 | device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr); | ||
1671 | device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable); | ||
1672 | device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable); | ||
1673 | device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable); | ||
1674 | device_create_file(&new_client->dev, &dev_attr_cpu0_vid); | ||
1675 | device_create_file(&new_client->dev, &dev_attr_vrm); | ||
1676 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
1677 | device_create_file(&new_client->dev, &dev_attr_alarm_mask); | ||
1678 | device_create_file(&new_client->dev, &dev_attr_gpio); | ||
1679 | device_create_file(&new_client->dev, &dev_attr_gpio_mask); | ||
1680 | device_create_file(&new_client->dev, &dev_attr_pwm1); | ||
1681 | device_create_file(&new_client->dev, &dev_attr_pwm2); | ||
1682 | device_create_file(&new_client->dev, &dev_attr_pwm3); | ||
1683 | device_create_file(&new_client->dev, &dev_attr_pwm1_enable); | ||
1684 | device_create_file(&new_client->dev, &dev_attr_pwm2_enable); | ||
1685 | device_create_file(&new_client->dev, &dev_attr_pwm3_enable); | ||
1686 | device_create_file(&new_client->dev, &dev_attr_temp1_auto_point1_pwm); | ||
1687 | device_create_file(&new_client->dev, &dev_attr_temp2_auto_point1_pwm); | ||
1688 | device_create_file(&new_client->dev, &dev_attr_temp3_auto_point1_pwm); | ||
1689 | device_create_file(&new_client->dev, &dev_attr_temp1_auto_point2_pwm); | ||
1690 | device_create_file(&new_client->dev, &dev_attr_temp2_auto_point2_pwm); | ||
1691 | device_create_file(&new_client->dev, &dev_attr_temp3_auto_point2_pwm); | ||
1692 | device_create_file(&new_client->dev, &dev_attr_analog_out); | ||
1693 | return 0; | 1686 | return 0; |
1694 | 1687 | ||
1695 | /* Error out and cleanup code */ | 1688 | /* Error out and cleanup code */ |
1689 | exitremove: | ||
1690 | sysfs_remove_group(&new_client->dev.kobj, &adm1026_group); | ||
1696 | exitdetach: | 1691 | exitdetach: |
1697 | i2c_detach_client(new_client); | 1692 | i2c_detach_client(new_client); |
1698 | exitfree: | 1693 | exitfree: |
@@ -1700,6 +1695,17 @@ exitfree: | |||
1700 | exit: | 1695 | exit: |
1701 | return err; | 1696 | return err; |
1702 | } | 1697 | } |
1698 | |||
1699 | static int adm1026_detach_client(struct i2c_client *client) | ||
1700 | { | ||
1701 | struct adm1026_data *data = i2c_get_clientdata(client); | ||
1702 | hwmon_device_unregister(data->class_dev); | ||
1703 | sysfs_remove_group(&client->dev.kobj, &adm1026_group); | ||
1704 | i2c_detach_client(client); | ||
1705 | kfree(data); | ||
1706 | return 0; | ||
1707 | } | ||
1708 | |||
1703 | static int __init sm_adm1026_init(void) | 1709 | static int __init sm_adm1026_init(void) |
1704 | { | 1710 | { |
1705 | return i2c_add_driver(&adm1026_driver); | 1711 | return i2c_add_driver(&adm1026_driver); |
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 3bf2da621aed..122683fc91d0 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c | |||
@@ -730,6 +730,61 @@ static int adm1031_attach_adapter(struct i2c_adapter *adapter) | |||
730 | return i2c_probe(adapter, &addr_data, adm1031_detect); | 730 | return i2c_probe(adapter, &addr_data, adm1031_detect); |
731 | } | 731 | } |
732 | 732 | ||
733 | static struct attribute *adm1031_attributes[] = { | ||
734 | &dev_attr_fan1_input.attr, | ||
735 | &dev_attr_fan1_div.attr, | ||
736 | &dev_attr_fan1_min.attr, | ||
737 | &dev_attr_pwm1.attr, | ||
738 | &dev_attr_auto_fan1_channel.attr, | ||
739 | &dev_attr_temp1_input.attr, | ||
740 | &dev_attr_temp1_min.attr, | ||
741 | &dev_attr_temp1_max.attr, | ||
742 | &dev_attr_temp1_crit.attr, | ||
743 | &dev_attr_temp2_input.attr, | ||
744 | &dev_attr_temp2_min.attr, | ||
745 | &dev_attr_temp2_max.attr, | ||
746 | &dev_attr_temp2_crit.attr, | ||
747 | |||
748 | &dev_attr_auto_temp1_off.attr, | ||
749 | &dev_attr_auto_temp1_min.attr, | ||
750 | &dev_attr_auto_temp1_max.attr, | ||
751 | |||
752 | &dev_attr_auto_temp2_off.attr, | ||
753 | &dev_attr_auto_temp2_min.attr, | ||
754 | &dev_attr_auto_temp2_max.attr, | ||
755 | |||
756 | &dev_attr_auto_fan1_min_pwm.attr, | ||
757 | |||
758 | &dev_attr_alarms.attr, | ||
759 | |||
760 | NULL | ||
761 | }; | ||
762 | |||
763 | static const struct attribute_group adm1031_group = { | ||
764 | .attrs = adm1031_attributes, | ||
765 | }; | ||
766 | |||
767 | static struct attribute *adm1031_attributes_opt[] = { | ||
768 | &dev_attr_fan2_input.attr, | ||
769 | &dev_attr_fan2_div.attr, | ||
770 | &dev_attr_fan2_min.attr, | ||
771 | &dev_attr_pwm2.attr, | ||
772 | &dev_attr_auto_fan2_channel.attr, | ||
773 | &dev_attr_temp3_input.attr, | ||
774 | &dev_attr_temp3_min.attr, | ||
775 | &dev_attr_temp3_max.attr, | ||
776 | &dev_attr_temp3_crit.attr, | ||
777 | &dev_attr_auto_temp3_off.attr, | ||
778 | &dev_attr_auto_temp3_min.attr, | ||
779 | &dev_attr_auto_temp3_max.attr, | ||
780 | &dev_attr_auto_fan2_min_pwm.attr, | ||
781 | NULL | ||
782 | }; | ||
783 | |||
784 | static const struct attribute_group adm1031_group_opt = { | ||
785 | .attrs = adm1031_attributes_opt, | ||
786 | }; | ||
787 | |||
733 | /* This function is called by i2c_probe */ | 788 | /* This function is called by i2c_probe */ |
734 | static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) | 789 | static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) |
735 | { | 790 | { |
@@ -789,57 +844,26 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) | |||
789 | adm1031_init_client(new_client); | 844 | adm1031_init_client(new_client); |
790 | 845 | ||
791 | /* Register sysfs hooks */ | 846 | /* Register sysfs hooks */ |
792 | data->class_dev = hwmon_device_register(&new_client->dev); | 847 | if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1031_group))) |
793 | if (IS_ERR(data->class_dev)) { | ||
794 | err = PTR_ERR(data->class_dev); | ||
795 | goto exit_detach; | 848 | goto exit_detach; |
796 | } | ||
797 | |||
798 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | ||
799 | device_create_file(&new_client->dev, &dev_attr_fan1_div); | ||
800 | device_create_file(&new_client->dev, &dev_attr_fan1_min); | ||
801 | device_create_file(&new_client->dev, &dev_attr_pwm1); | ||
802 | device_create_file(&new_client->dev, &dev_attr_auto_fan1_channel); | ||
803 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
804 | device_create_file(&new_client->dev, &dev_attr_temp1_min); | ||
805 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
806 | device_create_file(&new_client->dev, &dev_attr_temp1_crit); | ||
807 | device_create_file(&new_client->dev, &dev_attr_temp2_input); | ||
808 | device_create_file(&new_client->dev, &dev_attr_temp2_min); | ||
809 | device_create_file(&new_client->dev, &dev_attr_temp2_max); | ||
810 | device_create_file(&new_client->dev, &dev_attr_temp2_crit); | ||
811 | |||
812 | device_create_file(&new_client->dev, &dev_attr_auto_temp1_off); | ||
813 | device_create_file(&new_client->dev, &dev_attr_auto_temp1_min); | ||
814 | device_create_file(&new_client->dev, &dev_attr_auto_temp1_max); | ||
815 | |||
816 | device_create_file(&new_client->dev, &dev_attr_auto_temp2_off); | ||
817 | device_create_file(&new_client->dev, &dev_attr_auto_temp2_min); | ||
818 | device_create_file(&new_client->dev, &dev_attr_auto_temp2_max); | ||
819 | |||
820 | device_create_file(&new_client->dev, &dev_attr_auto_fan1_min_pwm); | ||
821 | |||
822 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
823 | 849 | ||
824 | if (kind == adm1031) { | 850 | if (kind == adm1031) { |
825 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | 851 | if ((err = sysfs_create_group(&new_client->dev.kobj, |
826 | device_create_file(&new_client->dev, &dev_attr_fan2_div); | 852 | &adm1031_group_opt))) |
827 | device_create_file(&new_client->dev, &dev_attr_fan2_min); | 853 | goto exit_remove; |
828 | device_create_file(&new_client->dev, &dev_attr_pwm2); | 854 | } |
829 | device_create_file(&new_client->dev, | 855 | |
830 | &dev_attr_auto_fan2_channel); | 856 | data->class_dev = hwmon_device_register(&new_client->dev); |
831 | device_create_file(&new_client->dev, &dev_attr_temp3_input); | 857 | if (IS_ERR(data->class_dev)) { |
832 | device_create_file(&new_client->dev, &dev_attr_temp3_min); | 858 | err = PTR_ERR(data->class_dev); |
833 | device_create_file(&new_client->dev, &dev_attr_temp3_max); | 859 | goto exit_remove; |
834 | device_create_file(&new_client->dev, &dev_attr_temp3_crit); | ||
835 | device_create_file(&new_client->dev, &dev_attr_auto_temp3_off); | ||
836 | device_create_file(&new_client->dev, &dev_attr_auto_temp3_min); | ||
837 | device_create_file(&new_client->dev, &dev_attr_auto_temp3_max); | ||
838 | device_create_file(&new_client->dev, &dev_attr_auto_fan2_min_pwm); | ||
839 | } | 860 | } |
840 | 861 | ||
841 | return 0; | 862 | return 0; |
842 | 863 | ||
864 | exit_remove: | ||
865 | sysfs_remove_group(&new_client->dev.kobj, &adm1031_group); | ||
866 | sysfs_remove_group(&new_client->dev.kobj, &adm1031_group_opt); | ||
843 | exit_detach: | 867 | exit_detach: |
844 | i2c_detach_client(new_client); | 868 | i2c_detach_client(new_client); |
845 | exit_free: | 869 | exit_free: |
@@ -854,6 +878,8 @@ static int adm1031_detach_client(struct i2c_client *client) | |||
854 | int ret; | 878 | int ret; |
855 | 879 | ||
856 | hwmon_device_unregister(data->class_dev); | 880 | hwmon_device_unregister(data->class_dev); |
881 | sysfs_remove_group(&client->dev.kobj, &adm1031_group); | ||
882 | sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); | ||
857 | if ((ret = i2c_detach_client(client)) != 0) { | 883 | if ((ret = i2c_detach_client(client)) != 0) { |
858 | return ret; | 884 | return ret; |
859 | } | 885 | } |
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 43f6991b588c..377961c4a41e 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c | |||
@@ -465,6 +465,45 @@ static ssize_t chassis_clear(struct device *dev, | |||
465 | } | 465 | } |
466 | static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear); | 466 | static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear); |
467 | 467 | ||
468 | static struct attribute *adm9240_attributes[] = { | ||
469 | &sensor_dev_attr_in0_input.dev_attr.attr, | ||
470 | &sensor_dev_attr_in0_min.dev_attr.attr, | ||
471 | &sensor_dev_attr_in0_max.dev_attr.attr, | ||
472 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
473 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
474 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
475 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
476 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
477 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
478 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
479 | &sensor_dev_attr_in3_min.dev_attr.attr, | ||
480 | &sensor_dev_attr_in3_max.dev_attr.attr, | ||
481 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
482 | &sensor_dev_attr_in4_min.dev_attr.attr, | ||
483 | &sensor_dev_attr_in4_max.dev_attr.attr, | ||
484 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
485 | &sensor_dev_attr_in5_min.dev_attr.attr, | ||
486 | &sensor_dev_attr_in5_max.dev_attr.attr, | ||
487 | &dev_attr_temp1_input.attr, | ||
488 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
489 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | ||
490 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
491 | &sensor_dev_attr_fan1_div.dev_attr.attr, | ||
492 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
493 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
494 | &sensor_dev_attr_fan2_div.dev_attr.attr, | ||
495 | &sensor_dev_attr_fan2_min.dev_attr.attr, | ||
496 | &dev_attr_alarms.attr, | ||
497 | &dev_attr_aout_output.attr, | ||
498 | &dev_attr_chassis_clear.attr, | ||
499 | &dev_attr_cpu0_vid.attr, | ||
500 | NULL | ||
501 | }; | ||
502 | |||
503 | static const struct attribute_group adm9240_group = { | ||
504 | .attrs = adm9240_attributes, | ||
505 | }; | ||
506 | |||
468 | 507 | ||
469 | /*** sensor chip detect and driver install ***/ | 508 | /*** sensor chip detect and driver install ***/ |
470 | 509 | ||
@@ -548,72 +587,19 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) | |||
548 | adm9240_init_client(new_client); | 587 | adm9240_init_client(new_client); |
549 | 588 | ||
550 | /* populate sysfs filesystem */ | 589 | /* populate sysfs filesystem */ |
590 | if ((err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group))) | ||
591 | goto exit_detach; | ||
592 | |||
551 | data->class_dev = hwmon_device_register(&new_client->dev); | 593 | data->class_dev = hwmon_device_register(&new_client->dev); |
552 | if (IS_ERR(data->class_dev)) { | 594 | if (IS_ERR(data->class_dev)) { |
553 | err = PTR_ERR(data->class_dev); | 595 | err = PTR_ERR(data->class_dev); |
554 | goto exit_detach; | 596 | goto exit_remove; |
555 | } | 597 | } |
556 | 598 | ||
557 | device_create_file(&new_client->dev, | ||
558 | &sensor_dev_attr_in0_input.dev_attr); | ||
559 | device_create_file(&new_client->dev, | ||
560 | &sensor_dev_attr_in0_min.dev_attr); | ||
561 | device_create_file(&new_client->dev, | ||
562 | &sensor_dev_attr_in0_max.dev_attr); | ||
563 | device_create_file(&new_client->dev, | ||
564 | &sensor_dev_attr_in1_input.dev_attr); | ||
565 | device_create_file(&new_client->dev, | ||
566 | &sensor_dev_attr_in1_min.dev_attr); | ||
567 | device_create_file(&new_client->dev, | ||
568 | &sensor_dev_attr_in1_max.dev_attr); | ||
569 | device_create_file(&new_client->dev, | ||
570 | &sensor_dev_attr_in2_input.dev_attr); | ||
571 | device_create_file(&new_client->dev, | ||
572 | &sensor_dev_attr_in2_min.dev_attr); | ||
573 | device_create_file(&new_client->dev, | ||
574 | &sensor_dev_attr_in2_max.dev_attr); | ||
575 | device_create_file(&new_client->dev, | ||
576 | &sensor_dev_attr_in3_input.dev_attr); | ||
577 | device_create_file(&new_client->dev, | ||
578 | &sensor_dev_attr_in3_min.dev_attr); | ||
579 | device_create_file(&new_client->dev, | ||
580 | &sensor_dev_attr_in3_max.dev_attr); | ||
581 | device_create_file(&new_client->dev, | ||
582 | &sensor_dev_attr_in4_input.dev_attr); | ||
583 | device_create_file(&new_client->dev, | ||
584 | &sensor_dev_attr_in4_min.dev_attr); | ||
585 | device_create_file(&new_client->dev, | ||
586 | &sensor_dev_attr_in4_max.dev_attr); | ||
587 | device_create_file(&new_client->dev, | ||
588 | &sensor_dev_attr_in5_input.dev_attr); | ||
589 | device_create_file(&new_client->dev, | ||
590 | &sensor_dev_attr_in5_min.dev_attr); | ||
591 | device_create_file(&new_client->dev, | ||
592 | &sensor_dev_attr_in5_max.dev_attr); | ||
593 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
594 | device_create_file(&new_client->dev, | ||
595 | &sensor_dev_attr_temp1_max.dev_attr); | ||
596 | device_create_file(&new_client->dev, | ||
597 | &sensor_dev_attr_temp1_max_hyst.dev_attr); | ||
598 | device_create_file(&new_client->dev, | ||
599 | &sensor_dev_attr_fan1_input.dev_attr); | ||
600 | device_create_file(&new_client->dev, | ||
601 | &sensor_dev_attr_fan1_div.dev_attr); | ||
602 | device_create_file(&new_client->dev, | ||
603 | &sensor_dev_attr_fan1_min.dev_attr); | ||
604 | device_create_file(&new_client->dev, | ||
605 | &sensor_dev_attr_fan2_input.dev_attr); | ||
606 | device_create_file(&new_client->dev, | ||
607 | &sensor_dev_attr_fan2_div.dev_attr); | ||
608 | device_create_file(&new_client->dev, | ||
609 | &sensor_dev_attr_fan2_min.dev_attr); | ||
610 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
611 | device_create_file(&new_client->dev, &dev_attr_aout_output); | ||
612 | device_create_file(&new_client->dev, &dev_attr_chassis_clear); | ||
613 | device_create_file(&new_client->dev, &dev_attr_cpu0_vid); | ||
614 | |||
615 | return 0; | 599 | return 0; |
616 | 600 | ||
601 | exit_remove: | ||
602 | sysfs_remove_group(&new_client->dev.kobj, &adm9240_group); | ||
617 | exit_detach: | 603 | exit_detach: |
618 | i2c_detach_client(new_client); | 604 | i2c_detach_client(new_client); |
619 | exit_free: | 605 | exit_free: |
@@ -635,6 +621,7 @@ static int adm9240_detach_client(struct i2c_client *client) | |||
635 | int err; | 621 | int err; |
636 | 622 | ||
637 | hwmon_device_unregister(data->class_dev); | 623 | hwmon_device_unregister(data->class_dev); |
624 | sysfs_remove_group(&client->dev.kobj, &adm9240_group); | ||
638 | 625 | ||
639 | if ((err = i2c_detach_client(client))) | 626 | if ((err = i2c_detach_client(client))) |
640 | return err; | 627 | return err; |
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index facc1ccb8338..57b1c7b7ac3f 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c | |||
@@ -298,12 +298,6 @@ sysfs_in(4); | |||
298 | sysfs_in(5); | 298 | sysfs_in(5); |
299 | sysfs_in(6); | 299 | sysfs_in(6); |
300 | 300 | ||
301 | #define device_create_file_in(client, offset) do { \ | ||
302 | device_create_file(&client->dev, &dev_attr_in##offset##_input); \ | ||
303 | device_create_file(&client->dev, &dev_attr_in##offset##_min); \ | ||
304 | device_create_file(&client->dev, &dev_attr_in##offset##_max); \ | ||
305 | } while (0) | ||
306 | |||
307 | /* 3 Fans */ | 301 | /* 3 Fans */ |
308 | static ssize_t show_fan(struct device *dev, char *buf, int nr) | 302 | static ssize_t show_fan(struct device *dev, char *buf, int nr) |
309 | { | 303 | { |
@@ -421,12 +415,6 @@ sysfs_fan(1); | |||
421 | sysfs_fan(2); | 415 | sysfs_fan(2); |
422 | sysfs_fan(3); | 416 | sysfs_fan(3); |
423 | 417 | ||
424 | #define device_create_file_fan(client, offset) do { \ | ||
425 | device_create_file(&client->dev, &dev_attr_fan##offset##_input); \ | ||
426 | device_create_file(&client->dev, &dev_attr_fan##offset##_min); \ | ||
427 | device_create_file(&client->dev, &dev_attr_fan##offset##_div); \ | ||
428 | } while (0) | ||
429 | |||
430 | /* 4 Temp. Sensors */ | 418 | /* 4 Temp. Sensors */ |
431 | static int sprintf_temp_from_reg(u16 reg, char *buf, int nr) | 419 | static int sprintf_temp_from_reg(u16 reg, char *buf, int nr) |
432 | { | 420 | { |
@@ -515,12 +503,6 @@ sysfs_temp(3); | |||
515 | sysfs_temp(4); | 503 | sysfs_temp(4); |
516 | 504 | ||
517 | /* VID */ | 505 | /* VID */ |
518 | #define device_create_file_temp(client, num) do { \ | ||
519 | device_create_file(&client->dev, &dev_attr_temp##num##_input); \ | ||
520 | device_create_file(&client->dev, &dev_attr_temp##num##_max); \ | ||
521 | device_create_file(&client->dev, &dev_attr_temp##num##_max_hyst); \ | ||
522 | } while (0) | ||
523 | |||
524 | static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) | 506 | static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) |
525 | { | 507 | { |
526 | struct asb100_data *data = asb100_update_device(dev); | 508 | struct asb100_data *data = asb100_update_device(dev); |
@@ -528,8 +510,6 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char | |||
528 | } | 510 | } |
529 | 511 | ||
530 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); | 512 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); |
531 | #define device_create_file_vid(client) \ | ||
532 | device_create_file(&client->dev, &dev_attr_cpu0_vid) | ||
533 | 513 | ||
534 | /* VRM */ | 514 | /* VRM */ |
535 | static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) | 515 | static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -549,8 +529,6 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const | |||
549 | 529 | ||
550 | /* Alarms */ | 530 | /* Alarms */ |
551 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); | 531 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); |
552 | #define device_create_file_vrm(client) \ | ||
553 | device_create_file(&client->dev, &dev_attr_vrm); | ||
554 | 532 | ||
555 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 533 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) |
556 | { | 534 | { |
@@ -559,8 +537,6 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch | |||
559 | } | 537 | } |
560 | 538 | ||
561 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 539 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
562 | #define device_create_file_alarms(client) \ | ||
563 | device_create_file(&client->dev, &dev_attr_alarms) | ||
564 | 540 | ||
565 | /* 1 PWM */ | 541 | /* 1 PWM */ |
566 | static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf) | 542 | static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -607,10 +583,65 @@ static ssize_t set_pwm_enable1(struct device *dev, struct device_attribute *attr | |||
607 | static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1); | 583 | static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1); |
608 | static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, | 584 | static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, |
609 | show_pwm_enable1, set_pwm_enable1); | 585 | show_pwm_enable1, set_pwm_enable1); |
610 | #define device_create_file_pwm1(client) do { \ | 586 | |
611 | device_create_file(&new_client->dev, &dev_attr_pwm1); \ | 587 | static struct attribute *asb100_attributes[] = { |
612 | device_create_file(&new_client->dev, &dev_attr_pwm1_enable); \ | 588 | &dev_attr_in0_input.attr, |
613 | } while (0) | 589 | &dev_attr_in0_min.attr, |
590 | &dev_attr_in0_max.attr, | ||
591 | &dev_attr_in1_input.attr, | ||
592 | &dev_attr_in1_min.attr, | ||
593 | &dev_attr_in1_max.attr, | ||
594 | &dev_attr_in2_input.attr, | ||
595 | &dev_attr_in2_min.attr, | ||
596 | &dev_attr_in2_max.attr, | ||
597 | &dev_attr_in3_input.attr, | ||
598 | &dev_attr_in3_min.attr, | ||
599 | &dev_attr_in3_max.attr, | ||
600 | &dev_attr_in4_input.attr, | ||
601 | &dev_attr_in4_min.attr, | ||
602 | &dev_attr_in4_max.attr, | ||
603 | &dev_attr_in5_input.attr, | ||
604 | &dev_attr_in5_min.attr, | ||
605 | &dev_attr_in5_max.attr, | ||
606 | &dev_attr_in6_input.attr, | ||
607 | &dev_attr_in6_min.attr, | ||
608 | &dev_attr_in6_max.attr, | ||
609 | |||
610 | &dev_attr_fan1_input.attr, | ||
611 | &dev_attr_fan1_min.attr, | ||
612 | &dev_attr_fan1_div.attr, | ||
613 | &dev_attr_fan2_input.attr, | ||
614 | &dev_attr_fan2_min.attr, | ||
615 | &dev_attr_fan2_div.attr, | ||
616 | &dev_attr_fan3_input.attr, | ||
617 | &dev_attr_fan3_min.attr, | ||
618 | &dev_attr_fan3_div.attr, | ||
619 | |||
620 | &dev_attr_temp1_input.attr, | ||
621 | &dev_attr_temp1_max.attr, | ||
622 | &dev_attr_temp1_max_hyst.attr, | ||
623 | &dev_attr_temp2_input.attr, | ||
624 | &dev_attr_temp2_max.attr, | ||
625 | &dev_attr_temp2_max_hyst.attr, | ||
626 | &dev_attr_temp3_input.attr, | ||
627 | &dev_attr_temp3_max.attr, | ||
628 | &dev_attr_temp3_max_hyst.attr, | ||
629 | &dev_attr_temp4_input.attr, | ||
630 | &dev_attr_temp4_max.attr, | ||
631 | &dev_attr_temp4_max_hyst.attr, | ||
632 | |||
633 | &dev_attr_cpu0_vid.attr, | ||
634 | &dev_attr_vrm.attr, | ||
635 | &dev_attr_alarms.attr, | ||
636 | &dev_attr_pwm1.attr, | ||
637 | &dev_attr_pwm1_enable.attr, | ||
638 | |||
639 | NULL | ||
640 | }; | ||
641 | |||
642 | static const struct attribute_group asb100_group = { | ||
643 | .attrs = asb100_attributes, | ||
644 | }; | ||
614 | 645 | ||
615 | /* This function is called when: | 646 | /* This function is called when: |
616 | asb100_driver is inserted (when this module is loaded), for each | 647 | asb100_driver is inserted (when this module is loaded), for each |
@@ -810,38 +841,19 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) | |||
810 | data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2)); | 841 | data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2)); |
811 | 842 | ||
812 | /* Register sysfs hooks */ | 843 | /* Register sysfs hooks */ |
844 | if ((err = sysfs_create_group(&new_client->dev.kobj, &asb100_group))) | ||
845 | goto ERROR3; | ||
846 | |||
813 | data->class_dev = hwmon_device_register(&new_client->dev); | 847 | data->class_dev = hwmon_device_register(&new_client->dev); |
814 | if (IS_ERR(data->class_dev)) { | 848 | if (IS_ERR(data->class_dev)) { |
815 | err = PTR_ERR(data->class_dev); | 849 | err = PTR_ERR(data->class_dev); |
816 | goto ERROR3; | 850 | goto ERROR4; |
817 | } | 851 | } |
818 | 852 | ||
819 | device_create_file_in(new_client, 0); | ||
820 | device_create_file_in(new_client, 1); | ||
821 | device_create_file_in(new_client, 2); | ||
822 | device_create_file_in(new_client, 3); | ||
823 | device_create_file_in(new_client, 4); | ||
824 | device_create_file_in(new_client, 5); | ||
825 | device_create_file_in(new_client, 6); | ||
826 | |||
827 | device_create_file_fan(new_client, 1); | ||
828 | device_create_file_fan(new_client, 2); | ||
829 | device_create_file_fan(new_client, 3); | ||
830 | |||
831 | device_create_file_temp(new_client, 1); | ||
832 | device_create_file_temp(new_client, 2); | ||
833 | device_create_file_temp(new_client, 3); | ||
834 | device_create_file_temp(new_client, 4); | ||
835 | |||
836 | device_create_file_vid(new_client); | ||
837 | device_create_file_vrm(new_client); | ||
838 | |||
839 | device_create_file_alarms(new_client); | ||
840 | |||
841 | device_create_file_pwm1(new_client); | ||
842 | |||
843 | return 0; | 853 | return 0; |
844 | 854 | ||
855 | ERROR4: | ||
856 | sysfs_remove_group(&new_client->dev.kobj, &asb100_group); | ||
845 | ERROR3: | 857 | ERROR3: |
846 | i2c_detach_client(data->lm75[1]); | 858 | i2c_detach_client(data->lm75[1]); |
847 | i2c_detach_client(data->lm75[0]); | 859 | i2c_detach_client(data->lm75[0]); |
@@ -861,8 +873,10 @@ static int asb100_detach_client(struct i2c_client *client) | |||
861 | int err; | 873 | int err; |
862 | 874 | ||
863 | /* main client */ | 875 | /* main client */ |
864 | if (data) | 876 | if (data) { |
865 | hwmon_device_unregister(data->class_dev); | 877 | hwmon_device_unregister(data->class_dev); |
878 | sysfs_remove_group(&client->dev.kobj, &asb100_group); | ||
879 | } | ||
866 | 880 | ||
867 | if ((err = i2c_detach_client(client))) | 881 | if ((err = i2c_detach_client(client))) |
868 | return err; | 882 | return err; |
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index 728a1e8b9190..0ccdd0750c44 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/hwmon-vid.h> | 27 | #include <linux/hwmon-vid.h> |
28 | #include <linux/err.h> | 28 | #include <linux/err.h> |
29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
30 | #include <linux/sysfs.h> | ||
30 | 31 | ||
31 | MODULE_LICENSE("GPL"); | 32 | MODULE_LICENSE("GPL"); |
32 | MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); | 33 | MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); |
@@ -116,8 +117,7 @@ static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *att | |||
116 | { | 117 | { |
117 | struct atxp1_data *data; | 118 | struct atxp1_data *data; |
118 | struct i2c_client *client; | 119 | struct i2c_client *client; |
119 | char vid; | 120 | int vid, cvid; |
120 | char cvid; | ||
121 | unsigned int vcore; | 121 | unsigned int vcore; |
122 | 122 | ||
123 | client = to_i2c_client(dev); | 123 | client = to_i2c_client(dev); |
@@ -251,6 +251,17 @@ static ssize_t atxp1_storegpio2(struct device *dev, struct device_attribute *att | |||
251 | */ | 251 | */ |
252 | static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2); | 252 | static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2); |
253 | 253 | ||
254 | static struct attribute *atxp1_attributes[] = { | ||
255 | &dev_attr_gpio1.attr, | ||
256 | &dev_attr_gpio2.attr, | ||
257 | &dev_attr_cpu0_vid.attr, | ||
258 | NULL | ||
259 | }; | ||
260 | |||
261 | static const struct attribute_group atxp1_group = { | ||
262 | .attrs = atxp1_attributes, | ||
263 | }; | ||
264 | |||
254 | 265 | ||
255 | static int atxp1_attach_adapter(struct i2c_adapter *adapter) | 266 | static int atxp1_attach_adapter(struct i2c_adapter *adapter) |
256 | { | 267 | { |
@@ -320,21 +331,23 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) | |||
320 | goto exit_free; | 331 | goto exit_free; |
321 | } | 332 | } |
322 | 333 | ||
334 | /* Register sysfs hooks */ | ||
335 | if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group))) | ||
336 | goto exit_detach; | ||
337 | |||
323 | data->class_dev = hwmon_device_register(&new_client->dev); | 338 | data->class_dev = hwmon_device_register(&new_client->dev); |
324 | if (IS_ERR(data->class_dev)) { | 339 | if (IS_ERR(data->class_dev)) { |
325 | err = PTR_ERR(data->class_dev); | 340 | err = PTR_ERR(data->class_dev); |
326 | goto exit_detach; | 341 | goto exit_remove_files; |
327 | } | 342 | } |
328 | 343 | ||
329 | device_create_file(&new_client->dev, &dev_attr_gpio1); | ||
330 | device_create_file(&new_client->dev, &dev_attr_gpio2); | ||
331 | device_create_file(&new_client->dev, &dev_attr_cpu0_vid); | ||
332 | |||
333 | dev_info(&new_client->dev, "Using VRM: %d.%d\n", | 344 | dev_info(&new_client->dev, "Using VRM: %d.%d\n", |
334 | data->vrm / 10, data->vrm % 10); | 345 | data->vrm / 10, data->vrm % 10); |
335 | 346 | ||
336 | return 0; | 347 | return 0; |
337 | 348 | ||
349 | exit_remove_files: | ||
350 | sysfs_remove_group(&new_client->dev.kobj, &atxp1_group); | ||
338 | exit_detach: | 351 | exit_detach: |
339 | i2c_detach_client(new_client); | 352 | i2c_detach_client(new_client); |
340 | exit_free: | 353 | exit_free: |
@@ -349,6 +362,7 @@ static int atxp1_detach_client(struct i2c_client * client) | |||
349 | int err; | 362 | int err; |
350 | 363 | ||
351 | hwmon_device_unregister(data->class_dev); | 364 | hwmon_device_unregister(data->class_dev); |
365 | sysfs_remove_group(&client->dev.kobj, &atxp1_group); | ||
352 | 366 | ||
353 | err = i2c_detach_client(client); | 367 | err = i2c_detach_client(client); |
354 | 368 | ||
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index 478eb4bb8570..c849c0c6ee9c 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/hwmon.h> | 29 | #include <linux/hwmon.h> |
30 | #include <linux/err.h> | 30 | #include <linux/err.h> |
31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
32 | #include <linux/sysfs.h> | ||
32 | #include "lm75.h" | 33 | #include "lm75.h" |
33 | 34 | ||
34 | /* Addresses to scan */ | 35 | /* Addresses to scan */ |
@@ -178,6 +179,18 @@ static DEVICE_ATTR(temp1_input, S_IRUGO , show_temp, NULL); | |||
178 | static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO , show_temp_min, set_temp_min); | 179 | static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO , show_temp_min, set_temp_min); |
179 | static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); | 180 | static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); |
180 | 181 | ||
182 | static struct attribute *ds1621_attributes[] = { | ||
183 | &dev_attr_temp1_input.attr, | ||
184 | &dev_attr_temp1_min.attr, | ||
185 | &dev_attr_temp1_max.attr, | ||
186 | &dev_attr_alarms.attr, | ||
187 | NULL | ||
188 | }; | ||
189 | |||
190 | static const struct attribute_group ds1621_group = { | ||
191 | .attrs = ds1621_attributes, | ||
192 | }; | ||
193 | |||
181 | 194 | ||
182 | static int ds1621_attach_adapter(struct i2c_adapter *adapter) | 195 | static int ds1621_attach_adapter(struct i2c_adapter *adapter) |
183 | { | 196 | { |
@@ -253,21 +266,19 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address, | |||
253 | ds1621_init_client(new_client); | 266 | ds1621_init_client(new_client); |
254 | 267 | ||
255 | /* Register sysfs hooks */ | 268 | /* Register sysfs hooks */ |
269 | if ((err = sysfs_create_group(&new_client->dev.kobj, &ds1621_group))) | ||
270 | goto exit_detach; | ||
271 | |||
256 | data->class_dev = hwmon_device_register(&new_client->dev); | 272 | data->class_dev = hwmon_device_register(&new_client->dev); |
257 | if (IS_ERR(data->class_dev)) { | 273 | if (IS_ERR(data->class_dev)) { |
258 | err = PTR_ERR(data->class_dev); | 274 | err = PTR_ERR(data->class_dev); |
259 | goto exit_detach; | 275 | goto exit_remove_files; |
260 | } | 276 | } |
261 | 277 | ||
262 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
263 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
264 | device_create_file(&new_client->dev, &dev_attr_temp1_min); | ||
265 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
266 | |||
267 | return 0; | 278 | return 0; |
268 | 279 | ||
269 | /* OK, this is not exactly good programming practice, usually. But it is | 280 | exit_remove_files: |
270 | very code-efficient in this case. */ | 281 | sysfs_remove_group(&new_client->dev.kobj, &ds1621_group); |
271 | exit_detach: | 282 | exit_detach: |
272 | i2c_detach_client(new_client); | 283 | i2c_detach_client(new_client); |
273 | exit_free: | 284 | exit_free: |
@@ -282,6 +293,7 @@ static int ds1621_detach_client(struct i2c_client *client) | |||
282 | int err; | 293 | int err; |
283 | 294 | ||
284 | hwmon_device_unregister(data->class_dev); | 295 | hwmon_device_unregister(data->class_dev); |
296 | sysfs_remove_group(&client->dev.kobj, &ds1621_group); | ||
285 | 297 | ||
286 | if ((err = i2c_detach_client(client))) | 298 | if ((err = i2c_detach_client(client))) |
287 | return err; | 299 | return err; |
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index fd72440faf76..de17a72149d9 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated | 2 | * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated |
3 | * hardware monitoring features | 3 | * hardware monitoring features |
4 | * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2005-2006 Jean Delvare <khali@linux-fr.org> |
5 | * | 5 | * |
6 | * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates | 6 | * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates |
7 | * complete hardware monitoring features: voltage, fan and temperature | 7 | * complete hardware monitoring features: voltage, fan and temperature |
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/hwmon-sysfs.h> | 31 | #include <linux/hwmon-sysfs.h> |
32 | #include <linux/err.h> | 32 | #include <linux/err.h> |
33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
34 | #include <linux/sysfs.h> | ||
34 | #include <asm/io.h> | 35 | #include <asm/io.h> |
35 | 36 | ||
36 | static struct platform_device *pdev; | 37 | static struct platform_device *pdev; |
@@ -147,7 +148,7 @@ struct f71805f_data { | |||
147 | u8 temp_high[3]; | 148 | u8 temp_high[3]; |
148 | u8 temp_hyst[3]; | 149 | u8 temp_hyst[3]; |
149 | u8 temp_mode; | 150 | u8 temp_mode; |
150 | u8 alarms[3]; | 151 | unsigned long alarms; |
151 | }; | 152 | }; |
152 | 153 | ||
153 | static inline long in_from_reg(u8 reg) | 154 | static inline long in_from_reg(u8 reg) |
@@ -311,10 +312,9 @@ static struct f71805f_data *f71805f_update_device(struct device *dev) | |||
311 | data->temp[nr] = f71805f_read8(data, | 312 | data->temp[nr] = f71805f_read8(data, |
312 | F71805F_REG_TEMP(nr)); | 313 | F71805F_REG_TEMP(nr)); |
313 | } | 314 | } |
314 | for (nr = 0; nr < 3; nr++) { | 315 | data->alarms = f71805f_read8(data, F71805F_REG_STATUS(0)) |
315 | data->alarms[nr] = f71805f_read8(data, | 316 | + (f71805f_read8(data, F71805F_REG_STATUS(1)) << 8) |
316 | F71805F_REG_STATUS(nr)); | 317 | + (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16); |
317 | } | ||
318 | 318 | ||
319 | data->last_updated = jiffies; | 319 | data->last_updated = jiffies; |
320 | data->valid = 1; | 320 | data->valid = 1; |
@@ -557,8 +557,7 @@ static ssize_t show_alarms_in(struct device *dev, struct device_attribute | |||
557 | { | 557 | { |
558 | struct f71805f_data *data = f71805f_update_device(dev); | 558 | struct f71805f_data *data = f71805f_update_device(dev); |
559 | 559 | ||
560 | return sprintf(buf, "%d\n", data->alarms[0] | | 560 | return sprintf(buf, "%lu\n", data->alarms & 0x1ff); |
561 | ((data->alarms[1] & 0x01) << 8)); | ||
562 | } | 561 | } |
563 | 562 | ||
564 | static ssize_t show_alarms_fan(struct device *dev, struct device_attribute | 563 | static ssize_t show_alarms_fan(struct device *dev, struct device_attribute |
@@ -566,7 +565,7 @@ static ssize_t show_alarms_fan(struct device *dev, struct device_attribute | |||
566 | { | 565 | { |
567 | struct f71805f_data *data = f71805f_update_device(dev); | 566 | struct f71805f_data *data = f71805f_update_device(dev); |
568 | 567 | ||
569 | return sprintf(buf, "%d\n", data->alarms[2] & 0x07); | 568 | return sprintf(buf, "%lu\n", (data->alarms >> 16) & 0x07); |
570 | } | 569 | } |
571 | 570 | ||
572 | static ssize_t show_alarms_temp(struct device *dev, struct device_attribute | 571 | static ssize_t show_alarms_temp(struct device *dev, struct device_attribute |
@@ -574,7 +573,17 @@ static ssize_t show_alarms_temp(struct device *dev, struct device_attribute | |||
574 | { | 573 | { |
575 | struct f71805f_data *data = f71805f_update_device(dev); | 574 | struct f71805f_data *data = f71805f_update_device(dev); |
576 | 575 | ||
577 | return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07); | 576 | return sprintf(buf, "%lu\n", (data->alarms >> 11) & 0x07); |
577 | } | ||
578 | |||
579 | static ssize_t show_alarm(struct device *dev, struct device_attribute | ||
580 | *devattr, char *buf) | ||
581 | { | ||
582 | struct f71805f_data *data = f71805f_update_device(dev); | ||
583 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
584 | int bitnr = attr->index; | ||
585 | |||
586 | return sprintf(buf, "%lu\n", (data->alarms >> bitnr) & 1); | ||
578 | } | 587 | } |
579 | 588 | ||
580 | static ssize_t show_name(struct device *dev, struct device_attribute | 589 | static ssize_t show_name(struct device *dev, struct device_attribute |
@@ -585,88 +594,189 @@ static ssize_t show_name(struct device *dev, struct device_attribute | |||
585 | return sprintf(buf, "%s\n", data->name); | 594 | return sprintf(buf, "%s\n", data->name); |
586 | } | 595 | } |
587 | 596 | ||
588 | static struct device_attribute f71805f_dev_attr[] = { | 597 | static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL); |
589 | __ATTR(in0_input, S_IRUGO, show_in0, NULL), | 598 | static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max); |
590 | __ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max), | 599 | static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min); |
591 | __ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min), | 600 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1); |
592 | __ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL), | 601 | static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, |
593 | __ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL), | 602 | show_in_max, set_in_max, 1); |
594 | __ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL), | 603 | static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, |
595 | __ATTR(name, S_IRUGO, show_name, NULL), | 604 | show_in_min, set_in_min, 1); |
605 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2); | ||
606 | static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR, | ||
607 | show_in_max, set_in_max, 2); | ||
608 | static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR, | ||
609 | show_in_min, set_in_min, 2); | ||
610 | static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3); | ||
611 | static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR, | ||
612 | show_in_max, set_in_max, 3); | ||
613 | static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR, | ||
614 | show_in_min, set_in_min, 3); | ||
615 | static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4); | ||
616 | static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR, | ||
617 | show_in_max, set_in_max, 4); | ||
618 | static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR, | ||
619 | show_in_min, set_in_min, 4); | ||
620 | static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5); | ||
621 | static SENSOR_DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR, | ||
622 | show_in_max, set_in_max, 5); | ||
623 | static SENSOR_DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR, | ||
624 | show_in_min, set_in_min, 5); | ||
625 | static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6); | ||
626 | static SENSOR_DEVICE_ATTR(in6_max, S_IRUGO | S_IWUSR, | ||
627 | show_in_max, set_in_max, 6); | ||
628 | static SENSOR_DEVICE_ATTR(in6_min, S_IRUGO | S_IWUSR, | ||
629 | show_in_min, set_in_min, 6); | ||
630 | static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7); | ||
631 | static SENSOR_DEVICE_ATTR(in7_max, S_IRUGO | S_IWUSR, | ||
632 | show_in_max, set_in_max, 7); | ||
633 | static SENSOR_DEVICE_ATTR(in7_min, S_IRUGO | S_IWUSR, | ||
634 | show_in_min, set_in_min, 7); | ||
635 | static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8); | ||
636 | static SENSOR_DEVICE_ATTR(in8_max, S_IRUGO | S_IWUSR, | ||
637 | show_in_max, set_in_max, 8); | ||
638 | static SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR, | ||
639 | show_in_min, set_in_min, 8); | ||
640 | |||
641 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); | ||
642 | static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, | ||
643 | show_fan_min, set_fan_min, 0); | ||
644 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); | ||
645 | static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, | ||
646 | show_fan_min, set_fan_min, 1); | ||
647 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); | ||
648 | static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR, | ||
649 | show_fan_min, set_fan_min, 2); | ||
650 | |||
651 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
652 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, | ||
653 | show_temp_max, set_temp_max, 0); | ||
654 | static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, | ||
655 | show_temp_hyst, set_temp_hyst, 0); | ||
656 | static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0); | ||
657 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); | ||
658 | static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, | ||
659 | show_temp_max, set_temp_max, 1); | ||
660 | static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, | ||
661 | show_temp_hyst, set_temp_hyst, 1); | ||
662 | static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1); | ||
663 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); | ||
664 | static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR, | ||
665 | show_temp_max, set_temp_max, 2); | ||
666 | static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, | ||
667 | show_temp_hyst, set_temp_hyst, 2); | ||
668 | static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2); | ||
669 | |||
670 | static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); | ||
671 | static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); | ||
672 | static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); | ||
673 | static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); | ||
674 | static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4); | ||
675 | static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5); | ||
676 | static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6); | ||
677 | static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7); | ||
678 | static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8); | ||
679 | static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 11); | ||
680 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12); | ||
681 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13); | ||
682 | static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16); | ||
683 | static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17); | ||
684 | static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18); | ||
685 | static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL); | ||
686 | static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL); | ||
687 | static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL); | ||
688 | |||
689 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
690 | |||
691 | static struct attribute *f71805f_attributes[] = { | ||
692 | &dev_attr_in0_input.attr, | ||
693 | &dev_attr_in0_max.attr, | ||
694 | &dev_attr_in0_min.attr, | ||
695 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
696 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
697 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
698 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
699 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
700 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
701 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
702 | &sensor_dev_attr_in3_max.dev_attr.attr, | ||
703 | &sensor_dev_attr_in3_min.dev_attr.attr, | ||
704 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
705 | &sensor_dev_attr_in4_max.dev_attr.attr, | ||
706 | &sensor_dev_attr_in4_min.dev_attr.attr, | ||
707 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
708 | &sensor_dev_attr_in5_max.dev_attr.attr, | ||
709 | &sensor_dev_attr_in5_min.dev_attr.attr, | ||
710 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
711 | &sensor_dev_attr_in6_max.dev_attr.attr, | ||
712 | &sensor_dev_attr_in6_min.dev_attr.attr, | ||
713 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
714 | &sensor_dev_attr_in7_max.dev_attr.attr, | ||
715 | &sensor_dev_attr_in7_min.dev_attr.attr, | ||
716 | &sensor_dev_attr_in8_input.dev_attr.attr, | ||
717 | &sensor_dev_attr_in8_max.dev_attr.attr, | ||
718 | &sensor_dev_attr_in8_min.dev_attr.attr, | ||
719 | |||
720 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
721 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
722 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | ||
723 | &sensor_dev_attr_temp1_type.dev_attr.attr, | ||
724 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
725 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
726 | &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, | ||
727 | &sensor_dev_attr_temp2_type.dev_attr.attr, | ||
728 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
729 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
730 | &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, | ||
731 | &sensor_dev_attr_temp3_type.dev_attr.attr, | ||
732 | |||
733 | &sensor_dev_attr_in0_alarm.dev_attr.attr, | ||
734 | &sensor_dev_attr_in1_alarm.dev_attr.attr, | ||
735 | &sensor_dev_attr_in2_alarm.dev_attr.attr, | ||
736 | &sensor_dev_attr_in3_alarm.dev_attr.attr, | ||
737 | &sensor_dev_attr_in4_alarm.dev_attr.attr, | ||
738 | &sensor_dev_attr_in5_alarm.dev_attr.attr, | ||
739 | &sensor_dev_attr_in6_alarm.dev_attr.attr, | ||
740 | &sensor_dev_attr_in7_alarm.dev_attr.attr, | ||
741 | &sensor_dev_attr_in8_alarm.dev_attr.attr, | ||
742 | &dev_attr_alarms_in.attr, | ||
743 | &sensor_dev_attr_temp1_alarm.dev_attr.attr, | ||
744 | &sensor_dev_attr_temp2_alarm.dev_attr.attr, | ||
745 | &sensor_dev_attr_temp3_alarm.dev_attr.attr, | ||
746 | &dev_attr_alarms_temp.attr, | ||
747 | &dev_attr_alarms_fan.attr, | ||
748 | |||
749 | &dev_attr_name.attr, | ||
750 | NULL | ||
596 | }; | 751 | }; |
597 | 752 | ||
598 | static struct sensor_device_attribute f71805f_sensor_attr[] = { | 753 | static const struct attribute_group f71805f_group = { |
599 | SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), | 754 | .attrs = f71805f_attributes, |
600 | SENSOR_ATTR(in1_max, S_IRUGO | S_IWUSR, | ||
601 | show_in_max, set_in_max, 1), | ||
602 | SENSOR_ATTR(in1_min, S_IRUGO | S_IWUSR, | ||
603 | show_in_min, set_in_min, 1), | ||
604 | SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), | ||
605 | SENSOR_ATTR(in2_max, S_IRUGO | S_IWUSR, | ||
606 | show_in_max, set_in_max, 2), | ||
607 | SENSOR_ATTR(in2_min, S_IRUGO | S_IWUSR, | ||
608 | show_in_min, set_in_min, 2), | ||
609 | SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), | ||
610 | SENSOR_ATTR(in3_max, S_IRUGO | S_IWUSR, | ||
611 | show_in_max, set_in_max, 3), | ||
612 | SENSOR_ATTR(in3_min, S_IRUGO | S_IWUSR, | ||
613 | show_in_min, set_in_min, 3), | ||
614 | SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), | ||
615 | SENSOR_ATTR(in4_max, S_IRUGO | S_IWUSR, | ||
616 | show_in_max, set_in_max, 4), | ||
617 | SENSOR_ATTR(in4_min, S_IRUGO | S_IWUSR, | ||
618 | show_in_min, set_in_min, 4), | ||
619 | SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), | ||
620 | SENSOR_ATTR(in5_max, S_IRUGO | S_IWUSR, | ||
621 | show_in_max, set_in_max, 5), | ||
622 | SENSOR_ATTR(in5_min, S_IRUGO | S_IWUSR, | ||
623 | show_in_min, set_in_min, 5), | ||
624 | SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), | ||
625 | SENSOR_ATTR(in6_max, S_IRUGO | S_IWUSR, | ||
626 | show_in_max, set_in_max, 6), | ||
627 | SENSOR_ATTR(in6_min, S_IRUGO | S_IWUSR, | ||
628 | show_in_min, set_in_min, 6), | ||
629 | SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), | ||
630 | SENSOR_ATTR(in7_max, S_IRUGO | S_IWUSR, | ||
631 | show_in_max, set_in_max, 7), | ||
632 | SENSOR_ATTR(in7_min, S_IRUGO | S_IWUSR, | ||
633 | show_in_min, set_in_min, 7), | ||
634 | SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), | ||
635 | SENSOR_ATTR(in8_max, S_IRUGO | S_IWUSR, | ||
636 | show_in_max, set_in_max, 8), | ||
637 | SENSOR_ATTR(in8_min, S_IRUGO | S_IWUSR, | ||
638 | show_in_min, set_in_min, 8), | ||
639 | |||
640 | SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0), | ||
641 | SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, | ||
642 | show_temp_max, set_temp_max, 0), | ||
643 | SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, | ||
644 | show_temp_hyst, set_temp_hyst, 0), | ||
645 | SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), | ||
646 | SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1), | ||
647 | SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, | ||
648 | show_temp_max, set_temp_max, 1), | ||
649 | SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, | ||
650 | show_temp_hyst, set_temp_hyst, 1), | ||
651 | SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), | ||
652 | SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2), | ||
653 | SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, | ||
654 | show_temp_max, set_temp_max, 2), | ||
655 | SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, | ||
656 | show_temp_hyst, set_temp_hyst, 2), | ||
657 | SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), | ||
658 | }; | 755 | }; |
659 | 756 | ||
660 | static struct sensor_device_attribute f71805f_fan_attr[] = { | 757 | static struct attribute *f71805f_attributes_fan[3][4] = { |
661 | SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), | 758 | { |
662 | SENSOR_ATTR(fan1_min, S_IRUGO | S_IWUSR, | 759 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
663 | show_fan_min, set_fan_min, 0), | 760 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
664 | SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), | 761 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, |
665 | SENSOR_ATTR(fan2_min, S_IRUGO | S_IWUSR, | 762 | NULL |
666 | show_fan_min, set_fan_min, 1), | 763 | }, { |
667 | SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), | 764 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
668 | SENSOR_ATTR(fan3_min, S_IRUGO | S_IWUSR, | 765 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
669 | show_fan_min, set_fan_min, 2), | 766 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, |
767 | NULL | ||
768 | }, { | ||
769 | &sensor_dev_attr_fan3_input.dev_attr.attr, | ||
770 | &sensor_dev_attr_fan3_min.dev_attr.attr, | ||
771 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | ||
772 | NULL | ||
773 | } | ||
774 | }; | ||
775 | |||
776 | static const struct attribute_group f71805f_group_fan[3] = { | ||
777 | { .attrs = f71805f_attributes_fan[0] }, | ||
778 | { .attrs = f71805f_attributes_fan[1] }, | ||
779 | { .attrs = f71805f_attributes_fan[2] }, | ||
670 | }; | 780 | }; |
671 | 781 | ||
672 | /* | 782 | /* |
@@ -714,43 +824,35 @@ static int __devinit f71805f_probe(struct platform_device *pdev) | |||
714 | 824 | ||
715 | platform_set_drvdata(pdev, data); | 825 | platform_set_drvdata(pdev, data); |
716 | 826 | ||
717 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
718 | if (IS_ERR(data->class_dev)) { | ||
719 | err = PTR_ERR(data->class_dev); | ||
720 | dev_err(&pdev->dev, "Class registration failed (%d)\n", err); | ||
721 | goto exit_free; | ||
722 | } | ||
723 | |||
724 | /* Initialize the F71805F chip */ | 827 | /* Initialize the F71805F chip */ |
725 | f71805f_init_device(data); | 828 | f71805f_init_device(data); |
726 | 829 | ||
727 | /* Register sysfs interface files */ | 830 | /* Register sysfs interface files */ |
728 | for (i = 0; i < ARRAY_SIZE(f71805f_dev_attr); i++) { | 831 | if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group))) |
729 | err = device_create_file(&pdev->dev, &f71805f_dev_attr[i]); | 832 | goto exit_free; |
730 | if (err) | 833 | for (i = 0; i < 3; i++) { |
731 | goto exit_class; | 834 | if (!(data->fan_enabled & (1 << i))) |
732 | } | ||
733 | for (i = 0; i < ARRAY_SIZE(f71805f_sensor_attr); i++) { | ||
734 | err = device_create_file(&pdev->dev, | ||
735 | &f71805f_sensor_attr[i].dev_attr); | ||
736 | if (err) | ||
737 | goto exit_class; | ||
738 | } | ||
739 | for (i = 0; i < ARRAY_SIZE(f71805f_fan_attr); i++) { | ||
740 | if (!(data->fan_enabled & (1 << (i / 2)))) | ||
741 | continue; | 835 | continue; |
742 | err = device_create_file(&pdev->dev, | 836 | if ((err = sysfs_create_group(&pdev->dev.kobj, |
743 | &f71805f_fan_attr[i].dev_attr); | 837 | &f71805f_group_fan[i]))) |
744 | if (err) | 838 | goto exit_remove_files; |
745 | goto exit_class; | 839 | } |
840 | |||
841 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
842 | if (IS_ERR(data->class_dev)) { | ||
843 | err = PTR_ERR(data->class_dev); | ||
844 | dev_err(&pdev->dev, "Class registration failed (%d)\n", err); | ||
845 | goto exit_remove_files; | ||
746 | } | 846 | } |
747 | 847 | ||
748 | return 0; | 848 | return 0; |
749 | 849 | ||
750 | exit_class: | 850 | exit_remove_files: |
751 | dev_err(&pdev->dev, "Sysfs interface creation failed\n"); | 851 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group); |
752 | hwmon_device_unregister(data->class_dev); | 852 | for (i = 0; i < 3; i++) |
853 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]); | ||
753 | exit_free: | 854 | exit_free: |
855 | platform_set_drvdata(pdev, NULL); | ||
754 | kfree(data); | 856 | kfree(data); |
755 | exit: | 857 | exit: |
756 | return err; | 858 | return err; |
@@ -759,9 +861,13 @@ exit: | |||
759 | static int __devexit f71805f_remove(struct platform_device *pdev) | 861 | static int __devexit f71805f_remove(struct platform_device *pdev) |
760 | { | 862 | { |
761 | struct f71805f_data *data = platform_get_drvdata(pdev); | 863 | struct f71805f_data *data = platform_get_drvdata(pdev); |
864 | int i; | ||
762 | 865 | ||
763 | platform_set_drvdata(pdev, NULL); | 866 | platform_set_drvdata(pdev, NULL); |
764 | hwmon_device_unregister(data->class_dev); | 867 | hwmon_device_unregister(data->class_dev); |
868 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group); | ||
869 | for (i = 0; i < 3; i++) | ||
870 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_fan[i]); | ||
765 | kfree(data); | 871 | kfree(data); |
766 | 872 | ||
767 | return 0; | 873 | return 0; |
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c index 6bc76b407636..19717752cfca 100644 --- a/drivers/hwmon/fscher.c +++ b/drivers/hwmon/fscher.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/hwmon.h> | 34 | #include <linux/hwmon.h> |
35 | #include <linux/err.h> | 35 | #include <linux/err.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/sysfs.h> | ||
37 | 38 | ||
38 | /* | 39 | /* |
39 | * Addresses to scan | 40 | * Addresses to scan |
@@ -240,47 +241,45 @@ sysfs_alarms(FSCHER_REG_EVENTS) | |||
240 | sysfs_control(FSCHER_REG_CONTROL) | 241 | sysfs_control(FSCHER_REG_CONTROL) |
241 | sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_PRESET) | 242 | sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_PRESET) |
242 | 243 | ||
243 | #define device_create_file_fan(client, offset) \ | 244 | static struct attribute *fscher_attributes[] = { |
244 | do { \ | 245 | &dev_attr_revision.attr, |
245 | device_create_file(&client->dev, &dev_attr_fan##offset##_status); \ | 246 | &dev_attr_alarms.attr, |
246 | device_create_file(&client->dev, &dev_attr_pwm##offset); \ | 247 | &dev_attr_control.attr, |
247 | device_create_file(&client->dev, &dev_attr_fan##offset##_div); \ | 248 | |
248 | device_create_file(&client->dev, &dev_attr_fan##offset##_input); \ | 249 | &dev_attr_watchdog_status.attr, |
249 | } while (0) | 250 | &dev_attr_watchdog_control.attr, |
250 | 251 | &dev_attr_watchdog_preset.attr, | |
251 | #define device_create_file_temp(client, offset) \ | 252 | |
252 | do { \ | 253 | &dev_attr_in0_input.attr, |
253 | device_create_file(&client->dev, &dev_attr_temp##offset##_status); \ | 254 | &dev_attr_in1_input.attr, |
254 | device_create_file(&client->dev, &dev_attr_temp##offset##_input); \ | 255 | &dev_attr_in2_input.attr, |
255 | } while (0) | 256 | |
256 | 257 | &dev_attr_fan1_status.attr, | |
257 | #define device_create_file_in(client, offset) \ | 258 | &dev_attr_fan1_div.attr, |
258 | do { \ | 259 | &dev_attr_fan1_input.attr, |
259 | device_create_file(&client->dev, &dev_attr_in##offset##_input); \ | 260 | &dev_attr_pwm1.attr, |
260 | } while (0) | 261 | &dev_attr_fan2_status.attr, |
261 | 262 | &dev_attr_fan2_div.attr, | |
262 | #define device_create_file_revision(client) \ | 263 | &dev_attr_fan2_input.attr, |
263 | do { \ | 264 | &dev_attr_pwm2.attr, |
264 | device_create_file(&client->dev, &dev_attr_revision); \ | 265 | &dev_attr_fan3_status.attr, |
265 | } while (0) | 266 | &dev_attr_fan3_div.attr, |
266 | 267 | &dev_attr_fan3_input.attr, | |
267 | #define device_create_file_alarms(client) \ | 268 | &dev_attr_pwm3.attr, |
268 | do { \ | 269 | |
269 | device_create_file(&client->dev, &dev_attr_alarms); \ | 270 | &dev_attr_temp1_status.attr, |
270 | } while (0) | 271 | &dev_attr_temp1_input.attr, |
271 | 272 | &dev_attr_temp2_status.attr, | |
272 | #define device_create_file_control(client) \ | 273 | &dev_attr_temp2_input.attr, |
273 | do { \ | 274 | &dev_attr_temp3_status.attr, |
274 | device_create_file(&client->dev, &dev_attr_control); \ | 275 | &dev_attr_temp3_input.attr, |
275 | } while (0) | 276 | NULL |
276 | 277 | }; | |
277 | #define device_create_file_watchdog(client) \ | 278 | |
278 | do { \ | 279 | static const struct attribute_group fscher_group = { |
279 | device_create_file(&client->dev, &dev_attr_watchdog_status); \ | 280 | .attrs = fscher_attributes, |
280 | device_create_file(&client->dev, &dev_attr_watchdog_control); \ | 281 | }; |
281 | device_create_file(&client->dev, &dev_attr_watchdog_preset); \ | 282 | |
282 | } while (0) | ||
283 | |||
284 | /* | 283 | /* |
285 | * Real code | 284 | * Real code |
286 | */ | 285 | */ |
@@ -342,31 +341,19 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) | |||
342 | fscher_init_client(new_client); | 341 | fscher_init_client(new_client); |
343 | 342 | ||
344 | /* Register sysfs hooks */ | 343 | /* Register sysfs hooks */ |
344 | if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group))) | ||
345 | goto exit_detach; | ||
346 | |||
345 | data->class_dev = hwmon_device_register(&new_client->dev); | 347 | data->class_dev = hwmon_device_register(&new_client->dev); |
346 | if (IS_ERR(data->class_dev)) { | 348 | if (IS_ERR(data->class_dev)) { |
347 | err = PTR_ERR(data->class_dev); | 349 | err = PTR_ERR(data->class_dev); |
348 | goto exit_detach; | 350 | goto exit_remove_files; |
349 | } | 351 | } |
350 | 352 | ||
351 | device_create_file_revision(new_client); | ||
352 | device_create_file_alarms(new_client); | ||
353 | device_create_file_control(new_client); | ||
354 | device_create_file_watchdog(new_client); | ||
355 | |||
356 | device_create_file_in(new_client, 0); | ||
357 | device_create_file_in(new_client, 1); | ||
358 | device_create_file_in(new_client, 2); | ||
359 | |||
360 | device_create_file_fan(new_client, 1); | ||
361 | device_create_file_fan(new_client, 2); | ||
362 | device_create_file_fan(new_client, 3); | ||
363 | |||
364 | device_create_file_temp(new_client, 1); | ||
365 | device_create_file_temp(new_client, 2); | ||
366 | device_create_file_temp(new_client, 3); | ||
367 | |||
368 | return 0; | 353 | return 0; |
369 | 354 | ||
355 | exit_remove_files: | ||
356 | sysfs_remove_group(&new_client->dev.kobj, &fscher_group); | ||
370 | exit_detach: | 357 | exit_detach: |
371 | i2c_detach_client(new_client); | 358 | i2c_detach_client(new_client); |
372 | exit_free: | 359 | exit_free: |
@@ -381,6 +368,7 @@ static int fscher_detach_client(struct i2c_client *client) | |||
381 | int err; | 368 | int err; |
382 | 369 | ||
383 | hwmon_device_unregister(data->class_dev); | 370 | hwmon_device_unregister(data->class_dev); |
371 | sysfs_remove_group(&client->dev.kobj, &fscher_group); | ||
384 | 372 | ||
385 | if ((err = i2c_detach_client(client))) | 373 | if ((err = i2c_detach_client(client))) |
386 | return err; | 374 | return err; |
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c index 6dc4846b9eeb..ea506a77f9c9 100644 --- a/drivers/hwmon/fscpos.c +++ b/drivers/hwmon/fscpos.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/hwmon.h> | 38 | #include <linux/hwmon.h> |
39 | #include <linux/err.h> | 39 | #include <linux/err.h> |
40 | #include <linux/mutex.h> | 40 | #include <linux/mutex.h> |
41 | #include <linux/sysfs.h> | ||
41 | 42 | ||
42 | /* | 43 | /* |
43 | * Addresses to scan | 44 | * Addresses to scan |
@@ -432,6 +433,44 @@ static DEVICE_ATTR(in0_input, S_IRUGO, show_volt_12, NULL); | |||
432 | static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL); | 433 | static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL); |
433 | static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL); | 434 | static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL); |
434 | 435 | ||
436 | static struct attribute *fscpos_attributes[] = { | ||
437 | &dev_attr_event.attr, | ||
438 | &dev_attr_in0_input.attr, | ||
439 | &dev_attr_in1_input.attr, | ||
440 | &dev_attr_in2_input.attr, | ||
441 | |||
442 | &dev_attr_wdog_control.attr, | ||
443 | &dev_attr_wdog_preset.attr, | ||
444 | &dev_attr_wdog_state.attr, | ||
445 | |||
446 | &dev_attr_temp1_input.attr, | ||
447 | &dev_attr_temp1_status.attr, | ||
448 | &dev_attr_temp1_reset.attr, | ||
449 | &dev_attr_temp2_input.attr, | ||
450 | &dev_attr_temp2_status.attr, | ||
451 | &dev_attr_temp2_reset.attr, | ||
452 | &dev_attr_temp3_input.attr, | ||
453 | &dev_attr_temp3_status.attr, | ||
454 | &dev_attr_temp3_reset.attr, | ||
455 | |||
456 | &dev_attr_fan1_input.attr, | ||
457 | &dev_attr_fan1_status.attr, | ||
458 | &dev_attr_fan1_ripple.attr, | ||
459 | &dev_attr_pwm1.attr, | ||
460 | &dev_attr_fan2_input.attr, | ||
461 | &dev_attr_fan2_status.attr, | ||
462 | &dev_attr_fan2_ripple.attr, | ||
463 | &dev_attr_pwm2.attr, | ||
464 | &dev_attr_fan3_input.attr, | ||
465 | &dev_attr_fan3_status.attr, | ||
466 | &dev_attr_fan3_ripple.attr, | ||
467 | NULL | ||
468 | }; | ||
469 | |||
470 | static const struct attribute_group fscpos_group = { | ||
471 | .attrs = fscpos_attributes, | ||
472 | }; | ||
473 | |||
435 | static int fscpos_attach_adapter(struct i2c_adapter *adapter) | 474 | static int fscpos_attach_adapter(struct i2c_adapter *adapter) |
436 | { | 475 | { |
437 | if (!(adapter->class & I2C_CLASS_HWMON)) | 476 | if (!(adapter->class & I2C_CLASS_HWMON)) |
@@ -497,42 +536,19 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) | |||
497 | dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision); | 536 | dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision); |
498 | 537 | ||
499 | /* Register sysfs hooks */ | 538 | /* Register sysfs hooks */ |
539 | if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group))) | ||
540 | goto exit_detach; | ||
541 | |||
500 | data->class_dev = hwmon_device_register(&new_client->dev); | 542 | data->class_dev = hwmon_device_register(&new_client->dev); |
501 | if (IS_ERR(data->class_dev)) { | 543 | if (IS_ERR(data->class_dev)) { |
502 | err = PTR_ERR(data->class_dev); | 544 | err = PTR_ERR(data->class_dev); |
503 | goto exit_detach; | 545 | goto exit_remove_files; |
504 | } | 546 | } |
505 | 547 | ||
506 | device_create_file(&new_client->dev, &dev_attr_event); | ||
507 | device_create_file(&new_client->dev, &dev_attr_in0_input); | ||
508 | device_create_file(&new_client->dev, &dev_attr_in1_input); | ||
509 | device_create_file(&new_client->dev, &dev_attr_in2_input); | ||
510 | device_create_file(&new_client->dev, &dev_attr_wdog_control); | ||
511 | device_create_file(&new_client->dev, &dev_attr_wdog_preset); | ||
512 | device_create_file(&new_client->dev, &dev_attr_wdog_state); | ||
513 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
514 | device_create_file(&new_client->dev, &dev_attr_temp1_status); | ||
515 | device_create_file(&new_client->dev, &dev_attr_temp1_reset); | ||
516 | device_create_file(&new_client->dev, &dev_attr_temp2_input); | ||
517 | device_create_file(&new_client->dev, &dev_attr_temp2_status); | ||
518 | device_create_file(&new_client->dev, &dev_attr_temp2_reset); | ||
519 | device_create_file(&new_client->dev, &dev_attr_temp3_input); | ||
520 | device_create_file(&new_client->dev, &dev_attr_temp3_status); | ||
521 | device_create_file(&new_client->dev, &dev_attr_temp3_reset); | ||
522 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | ||
523 | device_create_file(&new_client->dev, &dev_attr_fan1_status); | ||
524 | device_create_file(&new_client->dev, &dev_attr_fan1_ripple); | ||
525 | device_create_file(&new_client->dev, &dev_attr_pwm1); | ||
526 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | ||
527 | device_create_file(&new_client->dev, &dev_attr_fan2_status); | ||
528 | device_create_file(&new_client->dev, &dev_attr_fan2_ripple); | ||
529 | device_create_file(&new_client->dev, &dev_attr_pwm2); | ||
530 | device_create_file(&new_client->dev, &dev_attr_fan3_input); | ||
531 | device_create_file(&new_client->dev, &dev_attr_fan3_status); | ||
532 | device_create_file(&new_client->dev, &dev_attr_fan3_ripple); | ||
533 | |||
534 | return 0; | 548 | return 0; |
535 | 549 | ||
550 | exit_remove_files: | ||
551 | sysfs_remove_group(&new_client->dev.kobj, &fscpos_group); | ||
536 | exit_detach: | 552 | exit_detach: |
537 | i2c_detach_client(new_client); | 553 | i2c_detach_client(new_client); |
538 | exit_free: | 554 | exit_free: |
@@ -547,6 +563,7 @@ static int fscpos_detach_client(struct i2c_client *client) | |||
547 | int err; | 563 | int err; |
548 | 564 | ||
549 | hwmon_device_unregister(data->class_dev); | 565 | hwmon_device_unregister(data->class_dev); |
566 | sysfs_remove_group(&client->dev.kobj, &fscpos_group); | ||
550 | 567 | ||
551 | if ((err = i2c_detach_client(client))) | 568 | if ((err = i2c_detach_client(client))) |
552 | return err; | 569 | return err; |
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 6606aabdb49d..c103640455a3 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/hwmon.h> | 44 | #include <linux/hwmon.h> |
45 | #include <linux/err.h> | 45 | #include <linux/err.h> |
46 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
47 | #include <linux/sysfs.h> | ||
47 | 48 | ||
48 | /* Addresses to scan */ | 49 | /* Addresses to scan */ |
49 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; | 50 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; |
@@ -340,6 +341,42 @@ static DEVICE_ATTR(beep_enable, S_IWUSR|S_IRUGO, | |||
340 | static DEVICE_ATTR(beep_mask, S_IWUSR|S_IRUGO, | 341 | static DEVICE_ATTR(beep_mask, S_IWUSR|S_IRUGO, |
341 | show_beep_mask, set_beep_mask); | 342 | show_beep_mask, set_beep_mask); |
342 | 343 | ||
344 | static struct attribute *gl518_attributes[] = { | ||
345 | &dev_attr_in0_input.attr, | ||
346 | &dev_attr_in1_input.attr, | ||
347 | &dev_attr_in2_input.attr, | ||
348 | &dev_attr_in3_input.attr, | ||
349 | &dev_attr_in0_min.attr, | ||
350 | &dev_attr_in1_min.attr, | ||
351 | &dev_attr_in2_min.attr, | ||
352 | &dev_attr_in3_min.attr, | ||
353 | &dev_attr_in0_max.attr, | ||
354 | &dev_attr_in1_max.attr, | ||
355 | &dev_attr_in2_max.attr, | ||
356 | &dev_attr_in3_max.attr, | ||
357 | |||
358 | &dev_attr_fan1_auto.attr, | ||
359 | &dev_attr_fan1_input.attr, | ||
360 | &dev_attr_fan2_input.attr, | ||
361 | &dev_attr_fan1_min.attr, | ||
362 | &dev_attr_fan2_min.attr, | ||
363 | &dev_attr_fan1_div.attr, | ||
364 | &dev_attr_fan2_div.attr, | ||
365 | |||
366 | &dev_attr_temp1_input.attr, | ||
367 | &dev_attr_temp1_max.attr, | ||
368 | &dev_attr_temp1_max_hyst.attr, | ||
369 | |||
370 | &dev_attr_alarms.attr, | ||
371 | &dev_attr_beep_enable.attr, | ||
372 | &dev_attr_beep_mask.attr, | ||
373 | NULL | ||
374 | }; | ||
375 | |||
376 | static const struct attribute_group gl518_group = { | ||
377 | .attrs = gl518_attributes, | ||
378 | }; | ||
379 | |||
343 | /* | 380 | /* |
344 | * Real code | 381 | * Real code |
345 | */ | 382 | */ |
@@ -420,43 +457,19 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) | |||
420 | gl518_init_client((struct i2c_client *) new_client); | 457 | gl518_init_client((struct i2c_client *) new_client); |
421 | 458 | ||
422 | /* Register sysfs hooks */ | 459 | /* Register sysfs hooks */ |
460 | if ((err = sysfs_create_group(&new_client->dev.kobj, &gl518_group))) | ||
461 | goto exit_detach; | ||
462 | |||
423 | data->class_dev = hwmon_device_register(&new_client->dev); | 463 | data->class_dev = hwmon_device_register(&new_client->dev); |
424 | if (IS_ERR(data->class_dev)) { | 464 | if (IS_ERR(data->class_dev)) { |
425 | err = PTR_ERR(data->class_dev); | 465 | err = PTR_ERR(data->class_dev); |
426 | goto exit_detach; | 466 | goto exit_remove_files; |
427 | } | 467 | } |
428 | 468 | ||
429 | device_create_file(&new_client->dev, &dev_attr_in0_input); | ||
430 | device_create_file(&new_client->dev, &dev_attr_in1_input); | ||
431 | device_create_file(&new_client->dev, &dev_attr_in2_input); | ||
432 | device_create_file(&new_client->dev, &dev_attr_in3_input); | ||
433 | device_create_file(&new_client->dev, &dev_attr_in0_min); | ||
434 | device_create_file(&new_client->dev, &dev_attr_in1_min); | ||
435 | device_create_file(&new_client->dev, &dev_attr_in2_min); | ||
436 | device_create_file(&new_client->dev, &dev_attr_in3_min); | ||
437 | device_create_file(&new_client->dev, &dev_attr_in0_max); | ||
438 | device_create_file(&new_client->dev, &dev_attr_in1_max); | ||
439 | device_create_file(&new_client->dev, &dev_attr_in2_max); | ||
440 | device_create_file(&new_client->dev, &dev_attr_in3_max); | ||
441 | device_create_file(&new_client->dev, &dev_attr_fan1_auto); | ||
442 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | ||
443 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | ||
444 | device_create_file(&new_client->dev, &dev_attr_fan1_min); | ||
445 | device_create_file(&new_client->dev, &dev_attr_fan2_min); | ||
446 | device_create_file(&new_client->dev, &dev_attr_fan1_div); | ||
447 | device_create_file(&new_client->dev, &dev_attr_fan2_div); | ||
448 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
449 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
450 | device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst); | ||
451 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
452 | device_create_file(&new_client->dev, &dev_attr_beep_enable); | ||
453 | device_create_file(&new_client->dev, &dev_attr_beep_mask); | ||
454 | |||
455 | return 0; | 469 | return 0; |
456 | 470 | ||
457 | /* OK, this is not exactly good programming practice, usually. But it is | 471 | exit_remove_files: |
458 | very code-efficient in this case. */ | 472 | sysfs_remove_group(&new_client->dev.kobj, &gl518_group); |
459 | |||
460 | exit_detach: | 473 | exit_detach: |
461 | i2c_detach_client(new_client); | 474 | i2c_detach_client(new_client); |
462 | exit_free: | 475 | exit_free: |
@@ -490,6 +503,7 @@ static int gl518_detach_client(struct i2c_client *client) | |||
490 | int err; | 503 | int err; |
491 | 504 | ||
492 | hwmon_device_unregister(data->class_dev); | 505 | hwmon_device_unregister(data->class_dev); |
506 | sysfs_remove_group(&client->dev.kobj, &gl518_group); | ||
493 | 507 | ||
494 | if ((err = i2c_detach_client(client))) | 508 | if ((err = i2c_detach_client(client))) |
495 | return err; | 509 | return err; |
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index 14e810f3c2c0..ebe7b9aaa916 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/hwmon-vid.h> | 30 | #include <linux/hwmon-vid.h> |
31 | #include <linux/err.h> | 31 | #include <linux/err.h> |
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/sysfs.h> | ||
33 | 34 | ||
34 | /* Type of the extra sensor */ | 35 | /* Type of the extra sensor */ |
35 | static unsigned short extra_sensor_type; | 36 | static unsigned short extra_sensor_type; |
@@ -190,55 +191,29 @@ static DEVICE_ATTR(type##item, S_IRUGO, get_##type##0##item, NULL); | |||
190 | #define sysfs_vid(n) \ | 191 | #define sysfs_vid(n) \ |
191 | sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT) | 192 | sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT) |
192 | 193 | ||
193 | #define device_create_file_vid(client, n) \ | ||
194 | device_create_file(&client->dev, &dev_attr_cpu##n##_vid) | ||
195 | |||
196 | #define sysfs_in(n) \ | 194 | #define sysfs_in(n) \ |
197 | sysfs_ro_n(in, n, _input, GL520_REG_IN##n##INPUT) \ | 195 | sysfs_ro_n(in, n, _input, GL520_REG_IN##n##INPUT) \ |
198 | sysfs_rw_n(in, n, _min, GL520_REG_IN##n##_MIN) \ | 196 | sysfs_rw_n(in, n, _min, GL520_REG_IN##n##_MIN) \ |
199 | sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) \ | 197 | sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) \ |
200 | 198 | ||
201 | #define device_create_file_in(client, n) \ | ||
202 | ({device_create_file(&client->dev, &dev_attr_in##n##_input); \ | ||
203 | device_create_file(&client->dev, &dev_attr_in##n##_min); \ | ||
204 | device_create_file(&client->dev, &dev_attr_in##n##_max);}) | ||
205 | |||
206 | #define sysfs_fan(n) \ | 199 | #define sysfs_fan(n) \ |
207 | sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \ | 200 | sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \ |
208 | sysfs_rw_n(fan, n, _min, GL520_REG_FAN_MIN) \ | 201 | sysfs_rw_n(fan, n, _min, GL520_REG_FAN_MIN) \ |
209 | sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV) | 202 | sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV) |
210 | 203 | ||
211 | #define device_create_file_fan(client, n) \ | ||
212 | ({device_create_file(&client->dev, &dev_attr_fan##n##_input); \ | ||
213 | device_create_file(&client->dev, &dev_attr_fan##n##_min); \ | ||
214 | device_create_file(&client->dev, &dev_attr_fan##n##_div);}) | ||
215 | |||
216 | #define sysfs_fan_off(n) \ | 204 | #define sysfs_fan_off(n) \ |
217 | sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) \ | 205 | sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) \ |
218 | 206 | ||
219 | #define device_create_file_fan_off(client, n) \ | ||
220 | device_create_file(&client->dev, &dev_attr_fan##n##_off) | ||
221 | |||
222 | #define sysfs_temp(n) \ | 207 | #define sysfs_temp(n) \ |
223 | sysfs_ro_n(temp, n, _input, GL520_REG_TEMP##n##_INPUT) \ | 208 | sysfs_ro_n(temp, n, _input, GL520_REG_TEMP##n##_INPUT) \ |
224 | sysfs_rw_n(temp, n, _max, GL520_REG_TEMP##n##_MAX) \ | 209 | sysfs_rw_n(temp, n, _max, GL520_REG_TEMP##n##_MAX) \ |
225 | sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP##n##_MAX_HYST) | 210 | sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP##n##_MAX_HYST) |
226 | 211 | ||
227 | #define device_create_file_temp(client, n) \ | ||
228 | ({device_create_file(&client->dev, &dev_attr_temp##n##_input); \ | ||
229 | device_create_file(&client->dev, &dev_attr_temp##n##_max); \ | ||
230 | device_create_file(&client->dev, &dev_attr_temp##n##_max_hyst);}) | ||
231 | |||
232 | #define sysfs_alarms() \ | 212 | #define sysfs_alarms() \ |
233 | sysfs_ro(alarms, , GL520_REG_ALARMS) \ | 213 | sysfs_ro(alarms, , GL520_REG_ALARMS) \ |
234 | sysfs_rw(beep_enable, , GL520_REG_BEEP_ENABLE) \ | 214 | sysfs_rw(beep_enable, , GL520_REG_BEEP_ENABLE) \ |
235 | sysfs_rw(beep_mask, , GL520_REG_BEEP_MASK) | 215 | sysfs_rw(beep_mask, , GL520_REG_BEEP_MASK) |
236 | 216 | ||
237 | #define device_create_file_alarms(client) \ | ||
238 | ({device_create_file(&client->dev, &dev_attr_alarms); \ | ||
239 | device_create_file(&client->dev, &dev_attr_beep_enable); \ | ||
240 | device_create_file(&client->dev, &dev_attr_beep_mask);}) | ||
241 | |||
242 | 217 | ||
243 | sysfs_vid(0) | 218 | sysfs_vid(0) |
244 | 219 | ||
@@ -511,6 +486,59 @@ static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data, | |||
511 | return count; | 486 | return count; |
512 | } | 487 | } |
513 | 488 | ||
489 | static struct attribute *gl520_attributes[] = { | ||
490 | &dev_attr_cpu0_vid.attr, | ||
491 | |||
492 | &dev_attr_in0_input.attr, | ||
493 | &dev_attr_in0_min.attr, | ||
494 | &dev_attr_in0_max.attr, | ||
495 | &dev_attr_in1_input.attr, | ||
496 | &dev_attr_in1_min.attr, | ||
497 | &dev_attr_in1_max.attr, | ||
498 | &dev_attr_in2_input.attr, | ||
499 | &dev_attr_in2_min.attr, | ||
500 | &dev_attr_in2_max.attr, | ||
501 | &dev_attr_in3_input.attr, | ||
502 | &dev_attr_in3_min.attr, | ||
503 | &dev_attr_in3_max.attr, | ||
504 | |||
505 | &dev_attr_fan1_input.attr, | ||
506 | &dev_attr_fan1_min.attr, | ||
507 | &dev_attr_fan1_div.attr, | ||
508 | &dev_attr_fan1_off.attr, | ||
509 | &dev_attr_fan2_input.attr, | ||
510 | &dev_attr_fan2_min.attr, | ||
511 | &dev_attr_fan2_div.attr, | ||
512 | |||
513 | &dev_attr_temp1_input.attr, | ||
514 | &dev_attr_temp1_max.attr, | ||
515 | &dev_attr_temp1_max_hyst.attr, | ||
516 | |||
517 | &dev_attr_alarms.attr, | ||
518 | &dev_attr_beep_enable.attr, | ||
519 | &dev_attr_beep_mask.attr, | ||
520 | NULL | ||
521 | }; | ||
522 | |||
523 | static const struct attribute_group gl520_group = { | ||
524 | .attrs = gl520_attributes, | ||
525 | }; | ||
526 | |||
527 | static struct attribute *gl520_attributes_opt[] = { | ||
528 | &dev_attr_in4_input.attr, | ||
529 | &dev_attr_in4_min.attr, | ||
530 | &dev_attr_in4_max.attr, | ||
531 | |||
532 | &dev_attr_temp2_input.attr, | ||
533 | &dev_attr_temp2_max.attr, | ||
534 | &dev_attr_temp2_max_hyst.attr, | ||
535 | NULL | ||
536 | }; | ||
537 | |||
538 | static const struct attribute_group gl520_group_opt = { | ||
539 | .attrs = gl520_attributes_opt, | ||
540 | }; | ||
541 | |||
514 | 542 | ||
515 | /* | 543 | /* |
516 | * Real code | 544 | * Real code |
@@ -572,33 +600,39 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) | |||
572 | gl520_init_client(new_client); | 600 | gl520_init_client(new_client); |
573 | 601 | ||
574 | /* Register sysfs hooks */ | 602 | /* Register sysfs hooks */ |
575 | data->class_dev = hwmon_device_register(&new_client->dev); | 603 | if ((err = sysfs_create_group(&new_client->dev.kobj, &gl520_group))) |
576 | if (IS_ERR(data->class_dev)) { | ||
577 | err = PTR_ERR(data->class_dev); | ||
578 | goto exit_detach; | 604 | goto exit_detach; |
579 | } | ||
580 | |||
581 | device_create_file_vid(new_client, 0); | ||
582 | 605 | ||
583 | device_create_file_in(new_client, 0); | 606 | if (data->two_temps) { |
584 | device_create_file_in(new_client, 1); | 607 | if ((err = device_create_file(&new_client->dev, |
585 | device_create_file_in(new_client, 2); | 608 | &dev_attr_temp2_input)) |
586 | device_create_file_in(new_client, 3); | 609 | || (err = device_create_file(&new_client->dev, |
587 | if (!data->two_temps) | 610 | &dev_attr_temp2_max)) |
588 | device_create_file_in(new_client, 4); | 611 | || (err = device_create_file(&new_client->dev, |
589 | 612 | &dev_attr_temp2_max_hyst))) | |
590 | device_create_file_fan(new_client, 1); | 613 | goto exit_remove_files; |
591 | device_create_file_fan(new_client, 2); | 614 | } else { |
592 | device_create_file_fan_off(new_client, 1); | 615 | if ((err = device_create_file(&new_client->dev, |
616 | &dev_attr_in4_input)) | ||
617 | || (err = device_create_file(&new_client->dev, | ||
618 | &dev_attr_in4_min)) | ||
619 | || (err = device_create_file(&new_client->dev, | ||
620 | &dev_attr_in4_max))) | ||
621 | goto exit_remove_files; | ||
622 | } | ||
593 | 623 | ||
594 | device_create_file_temp(new_client, 1); | ||
595 | if (data->two_temps) | ||
596 | device_create_file_temp(new_client, 2); | ||
597 | 624 | ||
598 | device_create_file_alarms(new_client); | 625 | data->class_dev = hwmon_device_register(&new_client->dev); |
626 | if (IS_ERR(data->class_dev)) { | ||
627 | err = PTR_ERR(data->class_dev); | ||
628 | goto exit_remove_files; | ||
629 | } | ||
599 | 630 | ||
600 | return 0; | 631 | return 0; |
601 | 632 | ||
633 | exit_remove_files: | ||
634 | sysfs_remove_group(&new_client->dev.kobj, &gl520_group); | ||
635 | sysfs_remove_group(&new_client->dev.kobj, &gl520_group_opt); | ||
602 | exit_detach: | 636 | exit_detach: |
603 | i2c_detach_client(new_client); | 637 | i2c_detach_client(new_client); |
604 | exit_free: | 638 | exit_free: |
@@ -652,6 +686,8 @@ static int gl520_detach_client(struct i2c_client *client) | |||
652 | int err; | 686 | int err; |
653 | 687 | ||
654 | hwmon_device_unregister(data->class_dev); | 688 | hwmon_device_unregister(data->class_dev); |
689 | sysfs_remove_group(&client->dev.kobj, &gl520_group); | ||
690 | sysfs_remove_group(&client->dev.kobj, &gl520_group_opt); | ||
655 | 691 | ||
656 | if ((err = i2c_detach_client(client))) | 692 | if ((err = i2c_detach_client(client))) |
657 | return err; | 693 | return err; |
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 42b632889dd8..8e7b5607f5a1 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c | |||
@@ -587,7 +587,9 @@ static int __init hdaps_init(void) | |||
587 | input_set_abs_params(hdaps_idev, ABS_Y, | 587 | input_set_abs_params(hdaps_idev, ABS_Y, |
588 | -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); | 588 | -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT); |
589 | 589 | ||
590 | input_register_device(hdaps_idev); | 590 | ret = input_register_device(hdaps_idev); |
591 | if (ret) | ||
592 | goto out_idev; | ||
591 | 593 | ||
592 | /* start up our timer for the input device */ | 594 | /* start up our timer for the input device */ |
593 | init_timer(&hdaps_timer); | 595 | init_timer(&hdaps_timer); |
@@ -598,6 +600,8 @@ static int __init hdaps_init(void) | |||
598 | printk(KERN_INFO "hdaps: driver successfully loaded.\n"); | 600 | printk(KERN_INFO "hdaps: driver successfully loaded.\n"); |
599 | return 0; | 601 | return 0; |
600 | 602 | ||
603 | out_idev: | ||
604 | input_free_device(hdaps_idev); | ||
601 | out_group: | 605 | out_group: |
602 | sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); | 606 | sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); |
603 | out_device: | 607 | out_device: |
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index b0ee57492228..323ef06719c1 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -4,10 +4,12 @@ | |||
4 | 4 | ||
5 | Supports: IT8705F Super I/O chip w/LPC interface | 5 | Supports: IT8705F Super I/O chip w/LPC interface |
6 | IT8712F Super I/O chip w/LPC interface & SMBus | 6 | IT8712F Super I/O chip w/LPC interface & SMBus |
7 | IT8716F Super I/O chip w/LPC interface | ||
8 | IT8718F Super I/O chip w/LPC interface | ||
7 | Sis950 A clone of the IT8705F | 9 | Sis950 A clone of the IT8705F |
8 | 10 | ||
9 | Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com> | 11 | Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com> |
10 | Largely inspired by lm78.c of the same package | 12 | Copyright (C) 2005-2006 Jean Delvare <khali@linux-fr.org> |
11 | 13 | ||
12 | This program is free software; you can redistribute it and/or modify | 14 | This program is free software; you can redistribute it and/or modify |
13 | it under the terms of the GNU General Public License as published by | 15 | it under the terms of the GNU General Public License as published by |
@@ -24,13 +26,6 @@ | |||
24 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 26 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
25 | */ | 27 | */ |
26 | 28 | ||
27 | /* | ||
28 | djg@pdp8.net David Gesswein 7/18/01 | ||
29 | Modified to fix bug with not all alarms enabled. | ||
30 | Added ability to read battery voltage and select temperature sensor | ||
31 | type at module load time. | ||
32 | */ | ||
33 | |||
34 | #include <linux/module.h> | 29 | #include <linux/module.h> |
35 | #include <linux/init.h> | 30 | #include <linux/init.h> |
36 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
@@ -42,6 +37,7 @@ | |||
42 | #include <linux/hwmon-vid.h> | 37 | #include <linux/hwmon-vid.h> |
43 | #include <linux/err.h> | 38 | #include <linux/err.h> |
44 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
40 | #include <linux/sysfs.h> | ||
45 | #include <asm/io.h> | 41 | #include <asm/io.h> |
46 | 42 | ||
47 | 43 | ||
@@ -50,12 +46,13 @@ static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; | |||
50 | static unsigned short isa_address; | 46 | static unsigned short isa_address; |
51 | 47 | ||
52 | /* Insmod parameters */ | 48 | /* Insmod parameters */ |
53 | I2C_CLIENT_INSMOD_2(it87, it8712); | 49 | I2C_CLIENT_INSMOD_4(it87, it8712, it8716, it8718); |
54 | 50 | ||
55 | #define REG 0x2e /* The register to read/write */ | 51 | #define REG 0x2e /* The register to read/write */ |
56 | #define DEV 0x07 /* Register: Logical device select */ | 52 | #define DEV 0x07 /* Register: Logical device select */ |
57 | #define VAL 0x2f /* The value to read/write */ | 53 | #define VAL 0x2f /* The value to read/write */ |
58 | #define PME 0x04 /* The device with the fan registers in it */ | 54 | #define PME 0x04 /* The device with the fan registers in it */ |
55 | #define GPIO 0x07 /* The device with the IT8718F VID value in it */ | ||
59 | #define DEVID 0x20 /* Register: Device ID */ | 56 | #define DEVID 0x20 /* Register: Device ID */ |
60 | #define DEVREV 0x22 /* Register: Device Revision */ | 57 | #define DEVREV 0x22 /* Register: Device Revision */ |
61 | 58 | ||
@@ -77,10 +74,10 @@ static int superio_inw(int reg) | |||
77 | } | 74 | } |
78 | 75 | ||
79 | static inline void | 76 | static inline void |
80 | superio_select(void) | 77 | superio_select(int ldn) |
81 | { | 78 | { |
82 | outb(DEV, REG); | 79 | outb(DEV, REG); |
83 | outb(PME, VAL); | 80 | outb(ldn, VAL); |
84 | } | 81 | } |
85 | 82 | ||
86 | static inline void | 83 | static inline void |
@@ -99,20 +96,27 @@ superio_exit(void) | |||
99 | outb(0x02, VAL); | 96 | outb(0x02, VAL); |
100 | } | 97 | } |
101 | 98 | ||
99 | /* Logical device 4 registers */ | ||
102 | #define IT8712F_DEVID 0x8712 | 100 | #define IT8712F_DEVID 0x8712 |
103 | #define IT8705F_DEVID 0x8705 | 101 | #define IT8705F_DEVID 0x8705 |
102 | #define IT8716F_DEVID 0x8716 | ||
103 | #define IT8718F_DEVID 0x8718 | ||
104 | #define IT87_ACT_REG 0x30 | 104 | #define IT87_ACT_REG 0x30 |
105 | #define IT87_BASE_REG 0x60 | 105 | #define IT87_BASE_REG 0x60 |
106 | 106 | ||
107 | /* Logical device 7 registers (IT8712F and later) */ | ||
108 | #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ | ||
109 | #define IT87_SIO_VID_REG 0xfc /* VID value */ | ||
110 | |||
107 | /* Update battery voltage after every reading if true */ | 111 | /* Update battery voltage after every reading if true */ |
108 | static int update_vbat; | 112 | static int update_vbat; |
109 | 113 | ||
110 | /* Not all BIOSes properly configure the PWM registers */ | 114 | /* Not all BIOSes properly configure the PWM registers */ |
111 | static int fix_pwm_polarity; | 115 | static int fix_pwm_polarity; |
112 | 116 | ||
113 | /* Chip Type */ | 117 | /* Values read from Super-I/O config space */ |
114 | |||
115 | static u16 chip_type; | 118 | static u16 chip_type; |
119 | static u8 vid_value; | ||
116 | 120 | ||
117 | /* Many IT87 constants specified below */ | 121 | /* Many IT87 constants specified below */ |
118 | 122 | ||
@@ -131,13 +135,21 @@ static u16 chip_type; | |||
131 | #define IT87_REG_ALARM2 0x02 | 135 | #define IT87_REG_ALARM2 0x02 |
132 | #define IT87_REG_ALARM3 0x03 | 136 | #define IT87_REG_ALARM3 0x03 |
133 | 137 | ||
138 | /* The IT8718F has the VID value in a different register, in Super-I/O | ||
139 | configuration space. */ | ||
134 | #define IT87_REG_VID 0x0a | 140 | #define IT87_REG_VID 0x0a |
141 | /* Warning: register 0x0b is used for something completely different in | ||
142 | new chips/revisions. I suspect only 16-bit tachometer mode will work | ||
143 | for these. */ | ||
135 | #define IT87_REG_FAN_DIV 0x0b | 144 | #define IT87_REG_FAN_DIV 0x0b |
145 | #define IT87_REG_FAN_16BIT 0x0c | ||
136 | 146 | ||
137 | /* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */ | 147 | /* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */ |
138 | 148 | ||
139 | #define IT87_REG_FAN(nr) (0x0d + (nr)) | 149 | #define IT87_REG_FAN(nr) (0x0d + (nr)) |
140 | #define IT87_REG_FAN_MIN(nr) (0x10 + (nr)) | 150 | #define IT87_REG_FAN_MIN(nr) (0x10 + (nr)) |
151 | #define IT87_REG_FANX(nr) (0x18 + (nr)) | ||
152 | #define IT87_REG_FANX_MIN(nr) (0x1b + (nr)) | ||
141 | #define IT87_REG_FAN_MAIN_CTRL 0x13 | 153 | #define IT87_REG_FAN_MAIN_CTRL 0x13 |
142 | #define IT87_REG_FAN_CTL 0x14 | 154 | #define IT87_REG_FAN_CTL 0x14 |
143 | #define IT87_REG_PWM(nr) (0x15 + (nr)) | 155 | #define IT87_REG_PWM(nr) (0x15 + (nr)) |
@@ -169,7 +181,16 @@ static inline u8 FAN_TO_REG(long rpm, int div) | |||
169 | 254); | 181 | 254); |
170 | } | 182 | } |
171 | 183 | ||
184 | static inline u16 FAN16_TO_REG(long rpm) | ||
185 | { | ||
186 | if (rpm == 0) | ||
187 | return 0xffff; | ||
188 | return SENSORS_LIMIT((1350000 + rpm) / (rpm * 2), 1, 0xfffe); | ||
189 | } | ||
190 | |||
172 | #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div))) | 191 | #define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div))) |
192 | /* The divider is fixed to 2 in 16-bit mode */ | ||
193 | #define FAN16_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:1350000/((val)*2)) | ||
173 | 194 | ||
174 | #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\ | 195 | #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\ |
175 | ((val)+500)/1000),-128,127)) | 196 | ((val)+500)/1000),-128,127)) |
@@ -181,7 +202,7 @@ static inline u8 FAN_TO_REG(long rpm, int div) | |||
181 | static int DIV_TO_REG(int val) | 202 | static int DIV_TO_REG(int val) |
182 | { | 203 | { |
183 | int answer = 0; | 204 | int answer = 0; |
184 | while ((val >>= 1) != 0) | 205 | while (answer < 7 && (val >>= 1)) |
185 | answer++; | 206 | answer++; |
186 | return answer; | 207 | return answer; |
187 | } | 208 | } |
@@ -203,10 +224,11 @@ struct it87_data { | |||
203 | unsigned long last_updated; /* In jiffies */ | 224 | unsigned long last_updated; /* In jiffies */ |
204 | 225 | ||
205 | u8 in[9]; /* Register value */ | 226 | u8 in[9]; /* Register value */ |
206 | u8 in_max[9]; /* Register value */ | 227 | u8 in_max[8]; /* Register value */ |
207 | u8 in_min[9]; /* Register value */ | 228 | u8 in_min[8]; /* Register value */ |
208 | u8 fan[3]; /* Register value */ | 229 | u8 has_fan; /* Bitfield, fans enabled */ |
209 | u8 fan_min[3]; /* Register value */ | 230 | u16 fan[3]; /* Register values, possibly combined */ |
231 | u16 fan_min[3]; /* Register values, possibly combined */ | ||
210 | u8 temp[3]; /* Register value */ | 232 | u8 temp[3]; /* Register value */ |
211 | u8 temp_high[3]; /* Register value */ | 233 | u8 temp_high[3]; /* Register value */ |
212 | u8 temp_low[3]; /* Register value */ | 234 | u8 temp_low[3]; /* Register value */ |
@@ -545,15 +567,15 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | |||
545 | 567 | ||
546 | struct i2c_client *client = to_i2c_client(dev); | 568 | struct i2c_client *client = to_i2c_client(dev); |
547 | struct it87_data *data = i2c_get_clientdata(client); | 569 | struct it87_data *data = i2c_get_clientdata(client); |
548 | int val = simple_strtol(buf, NULL, 10); | 570 | unsigned long val = simple_strtoul(buf, NULL, 10); |
549 | int i, min[3]; | 571 | int min; |
550 | u8 old; | 572 | u8 old; |
551 | 573 | ||
552 | mutex_lock(&data->update_lock); | 574 | mutex_lock(&data->update_lock); |
553 | old = it87_read_value(client, IT87_REG_FAN_DIV); | 575 | old = it87_read_value(client, IT87_REG_FAN_DIV); |
554 | 576 | ||
555 | for (i = 0; i < 3; i++) | 577 | /* Save fan min limit */ |
556 | min[i] = FAN_FROM_REG(data->fan_min[i], DIV_FROM_REG(data->fan_div[i])); | 578 | min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); |
557 | 579 | ||
558 | switch (nr) { | 580 | switch (nr) { |
559 | case 0: | 581 | case 0: |
@@ -573,10 +595,10 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | |||
573 | val |= 0x1 << 6; | 595 | val |= 0x1 << 6; |
574 | it87_write_value(client, IT87_REG_FAN_DIV, val); | 596 | it87_write_value(client, IT87_REG_FAN_DIV, val); |
575 | 597 | ||
576 | for (i = 0; i < 3; i++) { | 598 | /* Restore fan min limit */ |
577 | data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i])); | 599 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); |
578 | it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]); | 600 | it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); |
579 | } | 601 | |
580 | mutex_unlock(&data->update_lock); | 602 | mutex_unlock(&data->update_lock); |
581 | return count; | 603 | return count; |
582 | } | 604 | } |
@@ -657,6 +679,59 @@ show_pwm_offset(1); | |||
657 | show_pwm_offset(2); | 679 | show_pwm_offset(2); |
658 | show_pwm_offset(3); | 680 | show_pwm_offset(3); |
659 | 681 | ||
682 | /* A different set of callbacks for 16-bit fans */ | ||
683 | static ssize_t show_fan16(struct device *dev, struct device_attribute *attr, | ||
684 | char *buf) | ||
685 | { | ||
686 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
687 | int nr = sensor_attr->index; | ||
688 | struct it87_data *data = it87_update_device(dev); | ||
689 | return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan[nr])); | ||
690 | } | ||
691 | |||
692 | static ssize_t show_fan16_min(struct device *dev, struct device_attribute *attr, | ||
693 | char *buf) | ||
694 | { | ||
695 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
696 | int nr = sensor_attr->index; | ||
697 | struct it87_data *data = it87_update_device(dev); | ||
698 | return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan_min[nr])); | ||
699 | } | ||
700 | |||
701 | static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr, | ||
702 | const char *buf, size_t count) | ||
703 | { | ||
704 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
705 | int nr = sensor_attr->index; | ||
706 | struct i2c_client *client = to_i2c_client(dev); | ||
707 | struct it87_data *data = i2c_get_clientdata(client); | ||
708 | int val = simple_strtol(buf, NULL, 10); | ||
709 | |||
710 | mutex_lock(&data->update_lock); | ||
711 | data->fan_min[nr] = FAN16_TO_REG(val); | ||
712 | it87_write_value(client, IT87_REG_FAN_MIN(nr), | ||
713 | data->fan_min[nr] & 0xff); | ||
714 | it87_write_value(client, IT87_REG_FANX_MIN(nr), | ||
715 | data->fan_min[nr] >> 8); | ||
716 | mutex_unlock(&data->update_lock); | ||
717 | return count; | ||
718 | } | ||
719 | |||
720 | /* We want to use the same sysfs file names as 8-bit fans, but we need | ||
721 | different variable names, so we have to use SENSOR_ATTR instead of | ||
722 | SENSOR_DEVICE_ATTR. */ | ||
723 | #define show_fan16_offset(offset) \ | ||
724 | static struct sensor_device_attribute sensor_dev_attr_fan##offset##_input16 \ | ||
725 | = SENSOR_ATTR(fan##offset##_input, S_IRUGO, \ | ||
726 | show_fan16, NULL, offset - 1); \ | ||
727 | static struct sensor_device_attribute sensor_dev_attr_fan##offset##_min16 \ | ||
728 | = SENSOR_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ | ||
729 | show_fan16_min, set_fan16_min, offset - 1) | ||
730 | |||
731 | show_fan16_offset(1); | ||
732 | show_fan16_offset(2); | ||
733 | show_fan16_offset(3); | ||
734 | |||
660 | /* Alarms */ | 735 | /* Alarms */ |
661 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 736 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) |
662 | { | 737 | { |
@@ -684,8 +759,6 @@ store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf | |||
684 | return count; | 759 | return count; |
685 | } | 760 | } |
686 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); | 761 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); |
687 | #define device_create_file_vrm(client) \ | ||
688 | device_create_file(&client->dev, &dev_attr_vrm) | ||
689 | 762 | ||
690 | static ssize_t | 763 | static ssize_t |
691 | show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) | 764 | show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -694,8 +767,88 @@ show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) | |||
694 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); | 767 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); |
695 | } | 768 | } |
696 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); | 769 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); |
697 | #define device_create_file_vid(client) \ | 770 | |
698 | device_create_file(&client->dev, &dev_attr_cpu0_vid) | 771 | static struct attribute *it87_attributes[] = { |
772 | &sensor_dev_attr_in0_input.dev_attr.attr, | ||
773 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
774 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
775 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
776 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
777 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
778 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
779 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
780 | &sensor_dev_attr_in8_input.dev_attr.attr, | ||
781 | &sensor_dev_attr_in0_min.dev_attr.attr, | ||
782 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
783 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
784 | &sensor_dev_attr_in3_min.dev_attr.attr, | ||
785 | &sensor_dev_attr_in4_min.dev_attr.attr, | ||
786 | &sensor_dev_attr_in5_min.dev_attr.attr, | ||
787 | &sensor_dev_attr_in6_min.dev_attr.attr, | ||
788 | &sensor_dev_attr_in7_min.dev_attr.attr, | ||
789 | &sensor_dev_attr_in0_max.dev_attr.attr, | ||
790 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
791 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
792 | &sensor_dev_attr_in3_max.dev_attr.attr, | ||
793 | &sensor_dev_attr_in4_max.dev_attr.attr, | ||
794 | &sensor_dev_attr_in5_max.dev_attr.attr, | ||
795 | &sensor_dev_attr_in6_max.dev_attr.attr, | ||
796 | &sensor_dev_attr_in7_max.dev_attr.attr, | ||
797 | |||
798 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
799 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
800 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
801 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
802 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
803 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
804 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
805 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
806 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
807 | &sensor_dev_attr_temp1_type.dev_attr.attr, | ||
808 | &sensor_dev_attr_temp2_type.dev_attr.attr, | ||
809 | &sensor_dev_attr_temp3_type.dev_attr.attr, | ||
810 | |||
811 | &dev_attr_alarms.attr, | ||
812 | NULL | ||
813 | }; | ||
814 | |||
815 | static const struct attribute_group it87_group = { | ||
816 | .attrs = it87_attributes, | ||
817 | }; | ||
818 | |||
819 | static struct attribute *it87_attributes_opt[] = { | ||
820 | &sensor_dev_attr_fan1_input16.dev_attr.attr, | ||
821 | &sensor_dev_attr_fan1_min16.dev_attr.attr, | ||
822 | &sensor_dev_attr_fan2_input16.dev_attr.attr, | ||
823 | &sensor_dev_attr_fan2_min16.dev_attr.attr, | ||
824 | &sensor_dev_attr_fan3_input16.dev_attr.attr, | ||
825 | &sensor_dev_attr_fan3_min16.dev_attr.attr, | ||
826 | |||
827 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
828 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
829 | &sensor_dev_attr_fan1_div.dev_attr.attr, | ||
830 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
831 | &sensor_dev_attr_fan2_min.dev_attr.attr, | ||
832 | &sensor_dev_attr_fan2_div.dev_attr.attr, | ||
833 | &sensor_dev_attr_fan3_input.dev_attr.attr, | ||
834 | &sensor_dev_attr_fan3_min.dev_attr.attr, | ||
835 | &sensor_dev_attr_fan3_div.dev_attr.attr, | ||
836 | |||
837 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
838 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
839 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
840 | &sensor_dev_attr_pwm1.dev_attr.attr, | ||
841 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
842 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
843 | |||
844 | &dev_attr_vrm.attr, | ||
845 | &dev_attr_cpu0_vid.attr, | ||
846 | NULL | ||
847 | }; | ||
848 | |||
849 | static const struct attribute_group it87_group_opt = { | ||
850 | .attrs = it87_attributes_opt, | ||
851 | }; | ||
699 | 852 | ||
700 | /* This function is called when: | 853 | /* This function is called when: |
701 | * it87_driver is inserted (when this module is loaded), for each | 854 | * it87_driver is inserted (when this module is loaded), for each |
@@ -721,10 +874,12 @@ static int __init it87_find(unsigned short *address) | |||
721 | superio_enter(); | 874 | superio_enter(); |
722 | chip_type = superio_inw(DEVID); | 875 | chip_type = superio_inw(DEVID); |
723 | if (chip_type != IT8712F_DEVID | 876 | if (chip_type != IT8712F_DEVID |
877 | && chip_type != IT8716F_DEVID | ||
878 | && chip_type != IT8718F_DEVID | ||
724 | && chip_type != IT8705F_DEVID) | 879 | && chip_type != IT8705F_DEVID) |
725 | goto exit; | 880 | goto exit; |
726 | 881 | ||
727 | superio_select(); | 882 | superio_select(PME); |
728 | if (!(superio_inb(IT87_ACT_REG) & 0x01)) { | 883 | if (!(superio_inb(IT87_ACT_REG) & 0x01)) { |
729 | pr_info("it87: Device not activated, skipping\n"); | 884 | pr_info("it87: Device not activated, skipping\n"); |
730 | goto exit; | 885 | goto exit; |
@@ -740,6 +895,21 @@ static int __init it87_find(unsigned short *address) | |||
740 | pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", | 895 | pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", |
741 | chip_type, *address, superio_inb(DEVREV) & 0x0f); | 896 | chip_type, *address, superio_inb(DEVREV) & 0x0f); |
742 | 897 | ||
898 | /* Read GPIO config and VID value from LDN 7 (GPIO) */ | ||
899 | if (chip_type != IT8705F_DEVID) { | ||
900 | int reg; | ||
901 | |||
902 | superio_select(GPIO); | ||
903 | if (chip_type == it8718) | ||
904 | vid_value = superio_inb(IT87_SIO_VID_REG); | ||
905 | |||
906 | reg = superio_inb(IT87_SIO_PINX2_REG); | ||
907 | if (reg & (1 << 0)) | ||
908 | pr_info("it87: in3 is VCC (+5V)\n"); | ||
909 | if (reg & (1 << 1)) | ||
910 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); | ||
911 | } | ||
912 | |||
743 | exit: | 913 | exit: |
744 | superio_exit(); | 914 | superio_exit(); |
745 | return err; | 915 | return err; |
@@ -800,8 +970,19 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
800 | i = it87_read_value(new_client, IT87_REG_CHIPID); | 970 | i = it87_read_value(new_client, IT87_REG_CHIPID); |
801 | if (i == 0x90) { | 971 | if (i == 0x90) { |
802 | kind = it87; | 972 | kind = it87; |
803 | if ((is_isa) && (chip_type == IT8712F_DEVID)) | 973 | if (is_isa) { |
804 | kind = it8712; | 974 | switch (chip_type) { |
975 | case IT8712F_DEVID: | ||
976 | kind = it8712; | ||
977 | break; | ||
978 | case IT8716F_DEVID: | ||
979 | kind = it8716; | ||
980 | break; | ||
981 | case IT8718F_DEVID: | ||
982 | kind = it8718; | ||
983 | break; | ||
984 | } | ||
985 | } | ||
805 | } | 986 | } |
806 | else { | 987 | else { |
807 | if (kind == 0) | 988 | if (kind == 0) |
@@ -818,6 +999,10 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
818 | name = "it87"; | 999 | name = "it87"; |
819 | } else if (kind == it8712) { | 1000 | } else if (kind == it8712) { |
820 | name = "it8712"; | 1001 | name = "it8712"; |
1002 | } else if (kind == it8716) { | ||
1003 | name = "it8716"; | ||
1004 | } else if (kind == it8718) { | ||
1005 | name = "it8718"; | ||
821 | } | 1006 | } |
822 | 1007 | ||
823 | /* Fill in the remaining client fields and put it into the global list */ | 1008 | /* Fill in the remaining client fields and put it into the global list */ |
@@ -842,76 +1027,103 @@ static int it87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
842 | it87_init_client(new_client, data); | 1027 | it87_init_client(new_client, data); |
843 | 1028 | ||
844 | /* Register sysfs hooks */ | 1029 | /* Register sysfs hooks */ |
845 | data->class_dev = hwmon_device_register(&new_client->dev); | 1030 | if ((err = sysfs_create_group(&new_client->dev.kobj, &it87_group))) |
846 | if (IS_ERR(data->class_dev)) { | ||
847 | err = PTR_ERR(data->class_dev); | ||
848 | goto ERROR3; | 1031 | goto ERROR3; |
1032 | |||
1033 | /* Do not create fan files for disabled fans */ | ||
1034 | if (data->type == it8716 || data->type == it8718) { | ||
1035 | /* 16-bit tachometers */ | ||
1036 | if (data->has_fan & (1 << 0)) { | ||
1037 | if ((err = device_create_file(&new_client->dev, | ||
1038 | &sensor_dev_attr_fan1_input16.dev_attr)) | ||
1039 | || (err = device_create_file(&new_client->dev, | ||
1040 | &sensor_dev_attr_fan1_min16.dev_attr))) | ||
1041 | goto ERROR4; | ||
1042 | } | ||
1043 | if (data->has_fan & (1 << 1)) { | ||
1044 | if ((err = device_create_file(&new_client->dev, | ||
1045 | &sensor_dev_attr_fan2_input16.dev_attr)) | ||
1046 | || (err = device_create_file(&new_client->dev, | ||
1047 | &sensor_dev_attr_fan2_min16.dev_attr))) | ||
1048 | goto ERROR4; | ||
1049 | } | ||
1050 | if (data->has_fan & (1 << 2)) { | ||
1051 | if ((err = device_create_file(&new_client->dev, | ||
1052 | &sensor_dev_attr_fan3_input16.dev_attr)) | ||
1053 | || (err = device_create_file(&new_client->dev, | ||
1054 | &sensor_dev_attr_fan3_min16.dev_attr))) | ||
1055 | goto ERROR4; | ||
1056 | } | ||
1057 | } else { | ||
1058 | /* 8-bit tachometers with clock divider */ | ||
1059 | if (data->has_fan & (1 << 0)) { | ||
1060 | if ((err = device_create_file(&new_client->dev, | ||
1061 | &sensor_dev_attr_fan1_input.dev_attr)) | ||
1062 | || (err = device_create_file(&new_client->dev, | ||
1063 | &sensor_dev_attr_fan1_min.dev_attr)) | ||
1064 | || (err = device_create_file(&new_client->dev, | ||
1065 | &sensor_dev_attr_fan1_div.dev_attr))) | ||
1066 | goto ERROR4; | ||
1067 | } | ||
1068 | if (data->has_fan & (1 << 1)) { | ||
1069 | if ((err = device_create_file(&new_client->dev, | ||
1070 | &sensor_dev_attr_fan2_input.dev_attr)) | ||
1071 | || (err = device_create_file(&new_client->dev, | ||
1072 | &sensor_dev_attr_fan2_min.dev_attr)) | ||
1073 | || (err = device_create_file(&new_client->dev, | ||
1074 | &sensor_dev_attr_fan2_div.dev_attr))) | ||
1075 | goto ERROR4; | ||
1076 | } | ||
1077 | if (data->has_fan & (1 << 2)) { | ||
1078 | if ((err = device_create_file(&new_client->dev, | ||
1079 | &sensor_dev_attr_fan3_input.dev_attr)) | ||
1080 | || (err = device_create_file(&new_client->dev, | ||
1081 | &sensor_dev_attr_fan3_min.dev_attr)) | ||
1082 | || (err = device_create_file(&new_client->dev, | ||
1083 | &sensor_dev_attr_fan3_div.dev_attr))) | ||
1084 | goto ERROR4; | ||
1085 | } | ||
849 | } | 1086 | } |
850 | 1087 | ||
851 | device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr); | ||
852 | device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr); | ||
853 | device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr); | ||
854 | device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr); | ||
855 | device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr); | ||
856 | device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr); | ||
857 | device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr); | ||
858 | device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr); | ||
859 | device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr); | ||
860 | device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr); | ||
861 | device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr); | ||
862 | device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr); | ||
863 | device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr); | ||
864 | device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr); | ||
865 | device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr); | ||
866 | device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr); | ||
867 | device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr); | ||
868 | device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr); | ||
869 | device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr); | ||
870 | device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr); | ||
871 | device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr); | ||
872 | device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr); | ||
873 | device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr); | ||
874 | device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr); | ||
875 | device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr); | ||
876 | device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr); | ||
877 | device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr); | ||
878 | device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr); | ||
879 | device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr); | ||
880 | device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr); | ||
881 | device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr); | ||
882 | device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr); | ||
883 | device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr); | ||
884 | device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr); | ||
885 | device_create_file(&new_client->dev, &sensor_dev_attr_temp1_type.dev_attr); | ||
886 | device_create_file(&new_client->dev, &sensor_dev_attr_temp2_type.dev_attr); | ||
887 | device_create_file(&new_client->dev, &sensor_dev_attr_temp3_type.dev_attr); | ||
888 | device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr); | ||
889 | device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr); | ||
890 | device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr); | ||
891 | device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr); | ||
892 | device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr); | ||
893 | device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr); | ||
894 | device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr); | ||
895 | device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr); | ||
896 | device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr); | ||
897 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
898 | if (enable_pwm_interface) { | 1088 | if (enable_pwm_interface) { |
899 | device_create_file(&new_client->dev, &sensor_dev_attr_pwm1_enable.dev_attr); | 1089 | if ((err = device_create_file(&new_client->dev, |
900 | device_create_file(&new_client->dev, &sensor_dev_attr_pwm2_enable.dev_attr); | 1090 | &sensor_dev_attr_pwm1_enable.dev_attr)) |
901 | device_create_file(&new_client->dev, &sensor_dev_attr_pwm3_enable.dev_attr); | 1091 | || (err = device_create_file(&new_client->dev, |
902 | device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr); | 1092 | &sensor_dev_attr_pwm2_enable.dev_attr)) |
903 | device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr); | 1093 | || (err = device_create_file(&new_client->dev, |
904 | device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr); | 1094 | &sensor_dev_attr_pwm3_enable.dev_attr)) |
1095 | || (err = device_create_file(&new_client->dev, | ||
1096 | &sensor_dev_attr_pwm1.dev_attr)) | ||
1097 | || (err = device_create_file(&new_client->dev, | ||
1098 | &sensor_dev_attr_pwm2.dev_attr)) | ||
1099 | || (err = device_create_file(&new_client->dev, | ||
1100 | &sensor_dev_attr_pwm3.dev_attr))) | ||
1101 | goto ERROR4; | ||
905 | } | 1102 | } |
906 | 1103 | ||
907 | if (data->type == it8712) { | 1104 | if (data->type == it8712 || data->type == it8716 |
1105 | || data->type == it8718) { | ||
908 | data->vrm = vid_which_vrm(); | 1106 | data->vrm = vid_which_vrm(); |
909 | device_create_file_vrm(new_client); | 1107 | /* VID reading from Super-I/O config space if available */ |
910 | device_create_file_vid(new_client); | 1108 | data->vid = vid_value; |
1109 | if ((err = device_create_file(&new_client->dev, | ||
1110 | &dev_attr_vrm)) | ||
1111 | || (err = device_create_file(&new_client->dev, | ||
1112 | &dev_attr_cpu0_vid))) | ||
1113 | goto ERROR4; | ||
1114 | } | ||
1115 | |||
1116 | data->class_dev = hwmon_device_register(&new_client->dev); | ||
1117 | if (IS_ERR(data->class_dev)) { | ||
1118 | err = PTR_ERR(data->class_dev); | ||
1119 | goto ERROR4; | ||
911 | } | 1120 | } |
912 | 1121 | ||
913 | return 0; | 1122 | return 0; |
914 | 1123 | ||
1124 | ERROR4: | ||
1125 | sysfs_remove_group(&new_client->dev.kobj, &it87_group); | ||
1126 | sysfs_remove_group(&new_client->dev.kobj, &it87_group_opt); | ||
915 | ERROR3: | 1127 | ERROR3: |
916 | i2c_detach_client(new_client); | 1128 | i2c_detach_client(new_client); |
917 | ERROR2: | 1129 | ERROR2: |
@@ -929,6 +1141,8 @@ static int it87_detach_client(struct i2c_client *client) | |||
929 | int err; | 1141 | int err; |
930 | 1142 | ||
931 | hwmon_device_unregister(data->class_dev); | 1143 | hwmon_device_unregister(data->class_dev); |
1144 | sysfs_remove_group(&client->dev.kobj, &it87_group); | ||
1145 | sysfs_remove_group(&client->dev.kobj, &it87_group_opt); | ||
932 | 1146 | ||
933 | if ((err = i2c_detach_client(client))) | 1147 | if ((err = i2c_detach_client(client))) |
934 | return err; | 1148 | return err; |
@@ -1045,6 +1259,22 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data) | |||
1045 | data->manual_pwm_ctl[i] = 0xff; | 1259 | data->manual_pwm_ctl[i] = 0xff; |
1046 | } | 1260 | } |
1047 | 1261 | ||
1262 | /* Some chips seem to have default value 0xff for all limit | ||
1263 | * registers. For low voltage limits it makes no sense and triggers | ||
1264 | * alarms, so change to 0 instead. For high temperature limits, it | ||
1265 | * means -1 degree C, which surprisingly doesn't trigger an alarm, | ||
1266 | * but is still confusing, so change to 127 degrees C. */ | ||
1267 | for (i = 0; i < 8; i++) { | ||
1268 | tmp = it87_read_value(client, IT87_REG_VIN_MIN(i)); | ||
1269 | if (tmp == 0xff) | ||
1270 | it87_write_value(client, IT87_REG_VIN_MIN(i), 0); | ||
1271 | } | ||
1272 | for (i = 0; i < 3; i++) { | ||
1273 | tmp = it87_read_value(client, IT87_REG_TEMP_HIGH(i)); | ||
1274 | if (tmp == 0xff) | ||
1275 | it87_write_value(client, IT87_REG_TEMP_HIGH(i), 127); | ||
1276 | } | ||
1277 | |||
1048 | /* Check if temperature channnels are reset manually or by some reason */ | 1278 | /* Check if temperature channnels are reset manually or by some reason */ |
1049 | tmp = it87_read_value(client, IT87_REG_TEMP_ENABLE); | 1279 | tmp = it87_read_value(client, IT87_REG_TEMP_ENABLE); |
1050 | if ((tmp & 0x3f) == 0) { | 1280 | if ((tmp & 0x3f) == 0) { |
@@ -1068,6 +1298,18 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data) | |||
1068 | data->fan_main_ctrl |= 0x70; | 1298 | data->fan_main_ctrl |= 0x70; |
1069 | it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 1299 | it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); |
1070 | } | 1300 | } |
1301 | data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; | ||
1302 | |||
1303 | /* Set tachometers to 16-bit mode if needed */ | ||
1304 | if (data->type == it8716 || data->type == it8718) { | ||
1305 | tmp = it87_read_value(client, IT87_REG_FAN_16BIT); | ||
1306 | if (~tmp & 0x07 & data->has_fan) { | ||
1307 | dev_dbg(&client->dev, | ||
1308 | "Setting fan1-3 to 16-bit mode\n"); | ||
1309 | it87_write_value(client, IT87_REG_FAN_16BIT, | ||
1310 | tmp | 0x07); | ||
1311 | } | ||
1312 | } | ||
1071 | 1313 | ||
1072 | /* Set current fan mode registers and the default settings for the | 1314 | /* Set current fan mode registers and the default settings for the |
1073 | * other mode registers */ | 1315 | * other mode registers */ |
@@ -1118,18 +1360,26 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1118 | data->in_max[i] = | 1360 | data->in_max[i] = |
1119 | it87_read_value(client, IT87_REG_VIN_MAX(i)); | 1361 | it87_read_value(client, IT87_REG_VIN_MAX(i)); |
1120 | } | 1362 | } |
1363 | /* in8 (battery) has no limit registers */ | ||
1121 | data->in[8] = | 1364 | data->in[8] = |
1122 | it87_read_value(client, IT87_REG_VIN(8)); | 1365 | it87_read_value(client, IT87_REG_VIN(8)); |
1123 | /* Temperature sensor doesn't have limit registers, set | ||
1124 | to min and max value */ | ||
1125 | data->in_min[8] = 0; | ||
1126 | data->in_max[8] = 255; | ||
1127 | 1366 | ||
1128 | for (i = 0; i < 3; i++) { | 1367 | for (i = 0; i < 3; i++) { |
1129 | data->fan[i] = | 1368 | /* Skip disabled fans */ |
1130 | it87_read_value(client, IT87_REG_FAN(i)); | 1369 | if (!(data->has_fan & (1 << i))) |
1370 | continue; | ||
1371 | |||
1131 | data->fan_min[i] = | 1372 | data->fan_min[i] = |
1132 | it87_read_value(client, IT87_REG_FAN_MIN(i)); | 1373 | it87_read_value(client, IT87_REG_FAN_MIN(i)); |
1374 | data->fan[i] = it87_read_value(client, | ||
1375 | IT87_REG_FAN(i)); | ||
1376 | /* Add high byte if in 16-bit mode */ | ||
1377 | if (data->type == it8716 || data->type == it8718) { | ||
1378 | data->fan[i] |= it87_read_value(client, | ||
1379 | IT87_REG_FANX(i)) << 8; | ||
1380 | data->fan_min[i] |= it87_read_value(client, | ||
1381 | IT87_REG_FANX_MIN(i)) << 8; | ||
1382 | } | ||
1133 | } | 1383 | } |
1134 | for (i = 0; i < 3; i++) { | 1384 | for (i = 0; i < 3; i++) { |
1135 | data->temp[i] = | 1385 | data->temp[i] = |
@@ -1140,10 +1390,14 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1140 | it87_read_value(client, IT87_REG_TEMP_LOW(i)); | 1390 | it87_read_value(client, IT87_REG_TEMP_LOW(i)); |
1141 | } | 1391 | } |
1142 | 1392 | ||
1143 | i = it87_read_value(client, IT87_REG_FAN_DIV); | 1393 | /* Newer chips don't have clock dividers */ |
1144 | data->fan_div[0] = i & 0x07; | 1394 | if ((data->has_fan & 0x07) && data->type != it8716 |
1145 | data->fan_div[1] = (i >> 3) & 0x07; | 1395 | && data->type != it8718) { |
1146 | data->fan_div[2] = (i & 0x40) ? 3 : 1; | 1396 | i = it87_read_value(client, IT87_REG_FAN_DIV); |
1397 | data->fan_div[0] = i & 0x07; | ||
1398 | data->fan_div[1] = (i >> 3) & 0x07; | ||
1399 | data->fan_div[2] = (i & 0x40) ? 3 : 1; | ||
1400 | } | ||
1147 | 1401 | ||
1148 | data->alarms = | 1402 | data->alarms = |
1149 | it87_read_value(client, IT87_REG_ALARM1) | | 1403 | it87_read_value(client, IT87_REG_ALARM1) | |
@@ -1153,9 +1407,11 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1153 | 1407 | ||
1154 | data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); | 1408 | data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); |
1155 | /* The 8705 does not have VID capability */ | 1409 | /* The 8705 does not have VID capability */ |
1156 | if (data->type == it8712) { | 1410 | if (data->type == it8712 || data->type == it8716) { |
1157 | data->vid = it87_read_value(client, IT87_REG_VID); | 1411 | data->vid = it87_read_value(client, IT87_REG_VID); |
1158 | data->vid &= 0x1f; | 1412 | /* The older IT8712F revisions had only 5 VID pins, |
1413 | but we assume it is always safe to read 6 bits. */ | ||
1414 | data->vid &= 0x3f; | ||
1159 | } | 1415 | } |
1160 | data->last_updated = jiffies; | 1416 | data->last_updated = jiffies; |
1161 | data->valid = 1; | 1417 | data->valid = 1; |
@@ -1193,8 +1449,9 @@ static void __exit sm_it87_exit(void) | |||
1193 | } | 1449 | } |
1194 | 1450 | ||
1195 | 1451 | ||
1196 | MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>"); | 1452 | MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>, " |
1197 | MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver"); | 1453 | "Jean Delvare <khali@linux-fr.org>"); |
1454 | MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F, SiS950 driver"); | ||
1198 | module_param(update_vbat, bool, 0); | 1455 | module_param(update_vbat, bool, 0); |
1199 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); | 1456 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); |
1200 | module_param(fix_pwm_polarity, bool, 0); | 1457 | module_param(fix_pwm_polarity, bool, 0); |
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c new file mode 100644 index 000000000000..f58b64ed09e3 --- /dev/null +++ b/drivers/hwmon/k8temp.c | |||
@@ -0,0 +1,294 @@ | |||
1 | /* | ||
2 | * k8temp.c - Linux kernel module for hardware monitoring | ||
3 | * | ||
4 | * Copyright (C) 2006 Rudolf Marek <r.marek@sh.cvut.cz> | ||
5 | * | ||
6 | * Inspired from the w83785 and amd756 drivers. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/jiffies.h> | ||
29 | #include <linux/pci.h> | ||
30 | #include <linux/hwmon.h> | ||
31 | #include <linux/hwmon-sysfs.h> | ||
32 | #include <linux/err.h> | ||
33 | #include <linux/mutex.h> | ||
34 | |||
35 | #define TEMP_FROM_REG(val) (((((val) >> 16) & 0xff) - 49) * 1000) | ||
36 | #define REG_TEMP 0xe4 | ||
37 | #define SEL_PLACE 0x40 | ||
38 | #define SEL_CORE 0x04 | ||
39 | |||
40 | struct k8temp_data { | ||
41 | struct class_device *class_dev; | ||
42 | struct mutex update_lock; | ||
43 | const char *name; | ||
44 | char valid; /* zero until following fields are valid */ | ||
45 | unsigned long last_updated; /* in jiffies */ | ||
46 | |||
47 | /* registers values */ | ||
48 | u8 sensorsp; /* sensor presence bits - SEL_CORE & SEL_PLACE */ | ||
49 | u32 temp[2][2]; /* core, place */ | ||
50 | }; | ||
51 | |||
52 | static struct k8temp_data *k8temp_update_device(struct device *dev) | ||
53 | { | ||
54 | struct k8temp_data *data = dev_get_drvdata(dev); | ||
55 | struct pci_dev *pdev = to_pci_dev(dev); | ||
56 | u8 tmp; | ||
57 | |||
58 | mutex_lock(&data->update_lock); | ||
59 | |||
60 | if (!data->valid | ||
61 | || time_after(jiffies, data->last_updated + HZ)) { | ||
62 | pci_read_config_byte(pdev, REG_TEMP, &tmp); | ||
63 | tmp &= ~(SEL_PLACE | SEL_CORE); /* Select sensor 0, core0 */ | ||
64 | pci_write_config_byte(pdev, REG_TEMP, tmp); | ||
65 | pci_read_config_dword(pdev, REG_TEMP, &data->temp[0][0]); | ||
66 | |||
67 | if (data->sensorsp & SEL_PLACE) { | ||
68 | tmp |= SEL_PLACE; /* Select sensor 1, core0 */ | ||
69 | pci_write_config_byte(pdev, REG_TEMP, tmp); | ||
70 | pci_read_config_dword(pdev, REG_TEMP, | ||
71 | &data->temp[0][1]); | ||
72 | } | ||
73 | |||
74 | if (data->sensorsp & SEL_CORE) { | ||
75 | tmp &= ~SEL_PLACE; /* Select sensor 0, core1 */ | ||
76 | tmp |= SEL_CORE; | ||
77 | pci_write_config_byte(pdev, REG_TEMP, tmp); | ||
78 | pci_read_config_dword(pdev, REG_TEMP, | ||
79 | &data->temp[1][0]); | ||
80 | |||
81 | if (data->sensorsp & SEL_PLACE) { | ||
82 | tmp |= SEL_PLACE; /* Select sensor 1, core1 */ | ||
83 | pci_write_config_byte(pdev, REG_TEMP, tmp); | ||
84 | pci_read_config_dword(pdev, REG_TEMP, | ||
85 | &data->temp[1][1]); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | data->last_updated = jiffies; | ||
90 | data->valid = 1; | ||
91 | } | ||
92 | |||
93 | mutex_unlock(&data->update_lock); | ||
94 | return data; | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * Sysfs stuff | ||
99 | */ | ||
100 | |||
101 | static ssize_t show_name(struct device *dev, struct device_attribute | ||
102 | *devattr, char *buf) | ||
103 | { | ||
104 | struct k8temp_data *data = dev_get_drvdata(dev); | ||
105 | |||
106 | return sprintf(buf, "%s\n", data->name); | ||
107 | } | ||
108 | |||
109 | |||
110 | static ssize_t show_temp(struct device *dev, | ||
111 | struct device_attribute *devattr, char *buf) | ||
112 | { | ||
113 | struct sensor_device_attribute_2 *attr = | ||
114 | to_sensor_dev_attr_2(devattr); | ||
115 | int core = attr->nr; | ||
116 | int place = attr->index; | ||
117 | struct k8temp_data *data = k8temp_update_device(dev); | ||
118 | |||
119 | return sprintf(buf, "%d\n", | ||
120 | TEMP_FROM_REG(data->temp[core][place])); | ||
121 | } | ||
122 | |||
123 | /* core, place */ | ||
124 | |||
125 | static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0); | ||
126 | static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1); | ||
127 | static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0); | ||
128 | static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1); | ||
129 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
130 | |||
131 | static struct pci_device_id k8temp_ids[] = { | ||
132 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, | ||
133 | { 0 }, | ||
134 | }; | ||
135 | |||
136 | MODULE_DEVICE_TABLE(pci, k8temp_ids); | ||
137 | |||
138 | static int __devinit k8temp_probe(struct pci_dev *pdev, | ||
139 | const struct pci_device_id *id) | ||
140 | { | ||
141 | int err; | ||
142 | u8 scfg; | ||
143 | u32 temp; | ||
144 | struct k8temp_data *data; | ||
145 | u32 cpuid = cpuid_eax(1); | ||
146 | |||
147 | /* this feature should be available since SH-C0 core */ | ||
148 | if ((cpuid == 0xf40) || (cpuid == 0xf50) || (cpuid == 0xf51)) { | ||
149 | err = -ENODEV; | ||
150 | goto exit; | ||
151 | } | ||
152 | |||
153 | if (!(data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL))) { | ||
154 | err = -ENOMEM; | ||
155 | goto exit; | ||
156 | } | ||
157 | |||
158 | pci_read_config_byte(pdev, REG_TEMP, &scfg); | ||
159 | scfg &= ~(SEL_PLACE | SEL_CORE); /* Select sensor 0, core0 */ | ||
160 | pci_write_config_byte(pdev, REG_TEMP, scfg); | ||
161 | pci_read_config_byte(pdev, REG_TEMP, &scfg); | ||
162 | |||
163 | if (scfg & (SEL_PLACE | SEL_CORE)) { | ||
164 | dev_err(&pdev->dev, "Configuration bit(s) stuck at 1!\n"); | ||
165 | err = -ENODEV; | ||
166 | goto exit_free; | ||
167 | } | ||
168 | |||
169 | scfg |= (SEL_PLACE | SEL_CORE); | ||
170 | pci_write_config_byte(pdev, REG_TEMP, scfg); | ||
171 | |||
172 | /* now we know if we can change core and/or sensor */ | ||
173 | pci_read_config_byte(pdev, REG_TEMP, &data->sensorsp); | ||
174 | |||
175 | if (data->sensorsp & SEL_PLACE) { | ||
176 | scfg &= ~SEL_CORE; /* Select sensor 1, core0 */ | ||
177 | pci_write_config_byte(pdev, REG_TEMP, scfg); | ||
178 | pci_read_config_dword(pdev, REG_TEMP, &temp); | ||
179 | scfg |= SEL_CORE; /* prepare for next selection */ | ||
180 | if (!((temp >> 16) & 0xff)) /* if temp is 0 -49C is not likely */ | ||
181 | data->sensorsp &= ~SEL_PLACE; | ||
182 | } | ||
183 | |||
184 | if (data->sensorsp & SEL_CORE) { | ||
185 | scfg &= ~SEL_PLACE; /* Select sensor 0, core1 */ | ||
186 | pci_write_config_byte(pdev, REG_TEMP, scfg); | ||
187 | pci_read_config_dword(pdev, REG_TEMP, &temp); | ||
188 | if (!((temp >> 16) & 0xff)) /* if temp is 0 -49C is not likely */ | ||
189 | data->sensorsp &= ~SEL_CORE; | ||
190 | } | ||
191 | |||
192 | data->name = "k8temp"; | ||
193 | mutex_init(&data->update_lock); | ||
194 | dev_set_drvdata(&pdev->dev, data); | ||
195 | |||
196 | /* Register sysfs hooks */ | ||
197 | err = device_create_file(&pdev->dev, | ||
198 | &sensor_dev_attr_temp1_input.dev_attr); | ||
199 | if (err) | ||
200 | goto exit_remove; | ||
201 | |||
202 | /* sensor can be changed and reports something */ | ||
203 | if (data->sensorsp & SEL_PLACE) { | ||
204 | err = device_create_file(&pdev->dev, | ||
205 | &sensor_dev_attr_temp2_input.dev_attr); | ||
206 | if (err) | ||
207 | goto exit_remove; | ||
208 | } | ||
209 | |||
210 | /* core can be changed and reports something */ | ||
211 | if (data->sensorsp & SEL_CORE) { | ||
212 | err = device_create_file(&pdev->dev, | ||
213 | &sensor_dev_attr_temp3_input.dev_attr); | ||
214 | if (err) | ||
215 | goto exit_remove; | ||
216 | if (data->sensorsp & SEL_PLACE) | ||
217 | err = device_create_file(&pdev->dev, | ||
218 | &sensor_dev_attr_temp4_input. | ||
219 | dev_attr); | ||
220 | if (err) | ||
221 | goto exit_remove; | ||
222 | } | ||
223 | |||
224 | err = device_create_file(&pdev->dev, &dev_attr_name); | ||
225 | if (err) | ||
226 | goto exit_remove; | ||
227 | |||
228 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
229 | |||
230 | if (IS_ERR(data->class_dev)) { | ||
231 | err = PTR_ERR(data->class_dev); | ||
232 | goto exit_remove; | ||
233 | } | ||
234 | |||
235 | return 0; | ||
236 | |||
237 | exit_remove: | ||
238 | device_remove_file(&pdev->dev, | ||
239 | &sensor_dev_attr_temp1_input.dev_attr); | ||
240 | device_remove_file(&pdev->dev, | ||
241 | &sensor_dev_attr_temp2_input.dev_attr); | ||
242 | device_remove_file(&pdev->dev, | ||
243 | &sensor_dev_attr_temp3_input.dev_attr); | ||
244 | device_remove_file(&pdev->dev, | ||
245 | &sensor_dev_attr_temp4_input.dev_attr); | ||
246 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
247 | exit_free: | ||
248 | dev_set_drvdata(&pdev->dev, NULL); | ||
249 | kfree(data); | ||
250 | exit: | ||
251 | return err; | ||
252 | } | ||
253 | |||
254 | static void __devexit k8temp_remove(struct pci_dev *pdev) | ||
255 | { | ||
256 | struct k8temp_data *data = dev_get_drvdata(&pdev->dev); | ||
257 | |||
258 | hwmon_device_unregister(data->class_dev); | ||
259 | device_remove_file(&pdev->dev, | ||
260 | &sensor_dev_attr_temp1_input.dev_attr); | ||
261 | device_remove_file(&pdev->dev, | ||
262 | &sensor_dev_attr_temp2_input.dev_attr); | ||
263 | device_remove_file(&pdev->dev, | ||
264 | &sensor_dev_attr_temp3_input.dev_attr); | ||
265 | device_remove_file(&pdev->dev, | ||
266 | &sensor_dev_attr_temp4_input.dev_attr); | ||
267 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
268 | dev_set_drvdata(&pdev->dev, NULL); | ||
269 | kfree(data); | ||
270 | } | ||
271 | |||
272 | static struct pci_driver k8temp_driver = { | ||
273 | .name = "k8temp", | ||
274 | .id_table = k8temp_ids, | ||
275 | .probe = k8temp_probe, | ||
276 | .remove = __devexit_p(k8temp_remove), | ||
277 | }; | ||
278 | |||
279 | static int __init k8temp_init(void) | ||
280 | { | ||
281 | return pci_register_driver(&k8temp_driver); | ||
282 | } | ||
283 | |||
284 | static void __exit k8temp_exit(void) | ||
285 | { | ||
286 | pci_unregister_driver(&k8temp_driver); | ||
287 | } | ||
288 | |||
289 | MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>"); | ||
290 | MODULE_DESCRIPTION("AMD K8 core temperature monitor"); | ||
291 | MODULE_LICENSE("GPL"); | ||
292 | |||
293 | module_init(k8temp_init) | ||
294 | module_exit(k8temp_exit) | ||
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 071f0fc6adec..d69f3cf07122 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * lm63.c - driver for the National Semiconductor LM63 temperature sensor | 2 | * lm63.c - driver for the National Semiconductor LM63 temperature sensor |
3 | * with integrated fan control | 3 | * with integrated fan control |
4 | * Copyright (C) 2004-2005 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2004-2006 Jean Delvare <khali@linux-fr.org> |
5 | * Based on the lm90 driver. | 5 | * Based on the lm90 driver. |
6 | * | 6 | * |
7 | * The LM63 is a sensor chip made by National Semiconductor. It measures | 7 | * The LM63 is a sensor chip made by National Semiconductor. It measures |
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/hwmon.h> | 46 | #include <linux/hwmon.h> |
47 | #include <linux/err.h> | 47 | #include <linux/err.h> |
48 | #include <linux/mutex.h> | 48 | #include <linux/mutex.h> |
49 | #include <linux/sysfs.h> | ||
49 | 50 | ||
50 | /* | 51 | /* |
51 | * Addresses to scan | 52 | * Addresses to scan |
@@ -330,6 +331,16 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, | |||
330 | return sprintf(buf, "%u\n", data->alarms); | 331 | return sprintf(buf, "%u\n", data->alarms); |
331 | } | 332 | } |
332 | 333 | ||
334 | static ssize_t show_alarm(struct device *dev, struct device_attribute *devattr, | ||
335 | char *buf) | ||
336 | { | ||
337 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
338 | struct lm63_data *data = lm63_update_device(dev); | ||
339 | int bitnr = attr->index; | ||
340 | |||
341 | return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); | ||
342 | } | ||
343 | |||
333 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); | 344 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); |
334 | static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan, | 345 | static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan, |
335 | set_fan, 1); | 346 | set_fan, 1); |
@@ -350,8 +361,52 @@ static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2); | |||
350 | static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, | 361 | static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, |
351 | set_temp2_crit_hyst); | 362 | set_temp2_crit_hyst); |
352 | 363 | ||
364 | /* Individual alarm files */ | ||
365 | static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0); | ||
366 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); | ||
367 | static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2); | ||
368 | static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); | ||
369 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); | ||
370 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); | ||
371 | /* Raw alarm file for compatibility */ | ||
353 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 372 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
354 | 373 | ||
374 | static struct attribute *lm63_attributes[] = { | ||
375 | &dev_attr_pwm1.attr, | ||
376 | &dev_attr_pwm1_enable.attr, | ||
377 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
378 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
379 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
380 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
381 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
382 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | ||
383 | &dev_attr_temp2_crit_hyst.attr, | ||
384 | |||
385 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | ||
386 | &sensor_dev_attr_temp2_input_fault.dev_attr.attr, | ||
387 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | ||
388 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | ||
389 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
390 | &dev_attr_alarms.attr, | ||
391 | NULL | ||
392 | }; | ||
393 | |||
394 | static const struct attribute_group lm63_group = { | ||
395 | .attrs = lm63_attributes, | ||
396 | }; | ||
397 | |||
398 | static struct attribute *lm63_attributes_fan1[] = { | ||
399 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
400 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
401 | |||
402 | &sensor_dev_attr_fan1_min_alarm.dev_attr.attr, | ||
403 | NULL | ||
404 | }; | ||
405 | |||
406 | static const struct attribute_group lm63_group_fan1 = { | ||
407 | .attrs = lm63_attributes_fan1, | ||
408 | }; | ||
409 | |||
355 | /* | 410 | /* |
356 | * Real code | 411 | * Real code |
357 | */ | 412 | */ |
@@ -438,37 +493,26 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) | |||
438 | lm63_init_client(new_client); | 493 | lm63_init_client(new_client); |
439 | 494 | ||
440 | /* Register sysfs hooks */ | 495 | /* Register sysfs hooks */ |
441 | data->class_dev = hwmon_device_register(&new_client->dev); | 496 | if ((err = sysfs_create_group(&new_client->dev.kobj, |
442 | if (IS_ERR(data->class_dev)) { | 497 | &lm63_group))) |
443 | err = PTR_ERR(data->class_dev); | ||
444 | goto exit_detach; | 498 | goto exit_detach; |
499 | if (data->config & 0x04) { /* tachometer enabled */ | ||
500 | if ((err = sysfs_create_group(&new_client->dev.kobj, | ||
501 | &lm63_group_fan1))) | ||
502 | goto exit_remove_files; | ||
445 | } | 503 | } |
446 | 504 | ||
447 | if (data->config & 0x04) { /* tachometer enabled */ | 505 | data->class_dev = hwmon_device_register(&new_client->dev); |
448 | device_create_file(&new_client->dev, | 506 | if (IS_ERR(data->class_dev)) { |
449 | &sensor_dev_attr_fan1_input.dev_attr); | 507 | err = PTR_ERR(data->class_dev); |
450 | device_create_file(&new_client->dev, | 508 | goto exit_remove_files; |
451 | &sensor_dev_attr_fan1_min.dev_attr); | ||
452 | } | 509 | } |
453 | device_create_file(&new_client->dev, &dev_attr_pwm1); | ||
454 | device_create_file(&new_client->dev, &dev_attr_pwm1_enable); | ||
455 | device_create_file(&new_client->dev, | ||
456 | &sensor_dev_attr_temp1_input.dev_attr); | ||
457 | device_create_file(&new_client->dev, | ||
458 | &sensor_dev_attr_temp2_input.dev_attr); | ||
459 | device_create_file(&new_client->dev, | ||
460 | &sensor_dev_attr_temp2_min.dev_attr); | ||
461 | device_create_file(&new_client->dev, | ||
462 | &sensor_dev_attr_temp1_max.dev_attr); | ||
463 | device_create_file(&new_client->dev, | ||
464 | &sensor_dev_attr_temp2_max.dev_attr); | ||
465 | device_create_file(&new_client->dev, | ||
466 | &sensor_dev_attr_temp2_crit.dev_attr); | ||
467 | device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst); | ||
468 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
469 | 510 | ||
470 | return 0; | 511 | return 0; |
471 | 512 | ||
513 | exit_remove_files: | ||
514 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group); | ||
515 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1); | ||
472 | exit_detach: | 516 | exit_detach: |
473 | i2c_detach_client(new_client); | 517 | i2c_detach_client(new_client); |
474 | exit_free: | 518 | exit_free: |
@@ -518,6 +562,8 @@ static int lm63_detach_client(struct i2c_client *client) | |||
518 | int err; | 562 | int err; |
519 | 563 | ||
520 | hwmon_device_unregister(data->class_dev); | 564 | hwmon_device_unregister(data->class_dev); |
565 | sysfs_remove_group(&client->dev.kobj, &lm63_group); | ||
566 | sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); | ||
521 | 567 | ||
522 | if ((err = i2c_detach_client(client))) | 568 | if ((err = i2c_detach_client(client))) |
523 | return err; | 569 | return err; |
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index fc25b90ec24a..7c65b8bb6d72 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c | |||
@@ -112,6 +112,18 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter) | |||
112 | return i2c_probe(adapter, &addr_data, lm75_detect); | 112 | return i2c_probe(adapter, &addr_data, lm75_detect); |
113 | } | 113 | } |
114 | 114 | ||
115 | static struct attribute *lm75_attributes[] = { | ||
116 | &dev_attr_temp1_input.attr, | ||
117 | &dev_attr_temp1_max.attr, | ||
118 | &dev_attr_temp1_max_hyst.attr, | ||
119 | |||
120 | NULL | ||
121 | }; | ||
122 | |||
123 | static const struct attribute_group lm75_group = { | ||
124 | .attrs = lm75_attributes, | ||
125 | }; | ||
126 | |||
115 | /* This function is called by i2c_probe */ | 127 | /* This function is called by i2c_probe */ |
116 | static int lm75_detect(struct i2c_adapter *adapter, int address, int kind) | 128 | static int lm75_detect(struct i2c_adapter *adapter, int address, int kind) |
117 | { | 129 | { |
@@ -199,18 +211,19 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind) | |||
199 | lm75_init_client(new_client); | 211 | lm75_init_client(new_client); |
200 | 212 | ||
201 | /* Register sysfs hooks */ | 213 | /* Register sysfs hooks */ |
214 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm75_group))) | ||
215 | goto exit_detach; | ||
216 | |||
202 | data->class_dev = hwmon_device_register(&new_client->dev); | 217 | data->class_dev = hwmon_device_register(&new_client->dev); |
203 | if (IS_ERR(data->class_dev)) { | 218 | if (IS_ERR(data->class_dev)) { |
204 | err = PTR_ERR(data->class_dev); | 219 | err = PTR_ERR(data->class_dev); |
205 | goto exit_detach; | 220 | goto exit_remove; |
206 | } | 221 | } |
207 | 222 | ||
208 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
209 | device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst); | ||
210 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
211 | |||
212 | return 0; | 223 | return 0; |
213 | 224 | ||
225 | exit_remove: | ||
226 | sysfs_remove_group(&new_client->dev.kobj, &lm75_group); | ||
214 | exit_detach: | 227 | exit_detach: |
215 | i2c_detach_client(new_client); | 228 | i2c_detach_client(new_client); |
216 | exit_free: | 229 | exit_free: |
@@ -223,6 +236,7 @@ static int lm75_detach_client(struct i2c_client *client) | |||
223 | { | 236 | { |
224 | struct lm75_data *data = i2c_get_clientdata(client); | 237 | struct lm75_data *data = i2c_get_clientdata(client); |
225 | hwmon_device_unregister(data->class_dev); | 238 | hwmon_device_unregister(data->class_dev); |
239 | sysfs_remove_group(&client->dev.kobj, &lm75_group); | ||
226 | i2c_detach_client(client); | 240 | i2c_detach_client(client); |
227 | kfree(data); | 241 | kfree(data); |
228 | return 0; | 242 | return 0; |
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 459cc977380a..dd969f1e8415 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c | |||
@@ -212,6 +212,23 @@ static int lm77_attach_adapter(struct i2c_adapter *adapter) | |||
212 | return i2c_probe(adapter, &addr_data, lm77_detect); | 212 | return i2c_probe(adapter, &addr_data, lm77_detect); |
213 | } | 213 | } |
214 | 214 | ||
215 | static struct attribute *lm77_attributes[] = { | ||
216 | &dev_attr_temp1_input.attr, | ||
217 | &dev_attr_temp1_crit.attr, | ||
218 | &dev_attr_temp1_min.attr, | ||
219 | &dev_attr_temp1_max.attr, | ||
220 | &dev_attr_temp1_crit_hyst.attr, | ||
221 | &dev_attr_temp1_min_hyst.attr, | ||
222 | &dev_attr_temp1_max_hyst.attr, | ||
223 | &dev_attr_alarms.attr, | ||
224 | |||
225 | NULL | ||
226 | }; | ||
227 | |||
228 | static const struct attribute_group lm77_group = { | ||
229 | .attrs = lm77_attributes, | ||
230 | }; | ||
231 | |||
215 | /* This function is called by i2c_probe */ | 232 | /* This function is called by i2c_probe */ |
216 | static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) | 233 | static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) |
217 | { | 234 | { |
@@ -317,22 +334,19 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) | |||
317 | lm77_init_client(new_client); | 334 | lm77_init_client(new_client); |
318 | 335 | ||
319 | /* Register sysfs hooks */ | 336 | /* Register sysfs hooks */ |
337 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group))) | ||
338 | goto exit_detach; | ||
339 | |||
320 | data->class_dev = hwmon_device_register(&new_client->dev); | 340 | data->class_dev = hwmon_device_register(&new_client->dev); |
321 | if (IS_ERR(data->class_dev)) { | 341 | if (IS_ERR(data->class_dev)) { |
322 | err = PTR_ERR(data->class_dev); | 342 | err = PTR_ERR(data->class_dev); |
323 | goto exit_detach; | 343 | goto exit_remove; |
324 | } | 344 | } |
325 | 345 | ||
326 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
327 | device_create_file(&new_client->dev, &dev_attr_temp1_crit); | ||
328 | device_create_file(&new_client->dev, &dev_attr_temp1_min); | ||
329 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
330 | device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst); | ||
331 | device_create_file(&new_client->dev, &dev_attr_temp1_min_hyst); | ||
332 | device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst); | ||
333 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
334 | return 0; | 346 | return 0; |
335 | 347 | ||
348 | exit_remove: | ||
349 | sysfs_remove_group(&new_client->dev.kobj, &lm77_group); | ||
336 | exit_detach: | 350 | exit_detach: |
337 | i2c_detach_client(new_client); | 351 | i2c_detach_client(new_client); |
338 | exit_free: | 352 | exit_free: |
@@ -345,6 +359,7 @@ static int lm77_detach_client(struct i2c_client *client) | |||
345 | { | 359 | { |
346 | struct lm77_data *data = i2c_get_clientdata(client); | 360 | struct lm77_data *data = i2c_get_clientdata(client); |
347 | hwmon_device_unregister(data->class_dev); | 361 | hwmon_device_unregister(data->class_dev); |
362 | sysfs_remove_group(&client->dev.kobj, &lm77_group); | ||
348 | i2c_detach_client(client); | 363 | i2c_detach_client(client); |
349 | kfree(data); | 364 | kfree(data); |
350 | return 0; | 365 | return 0; |
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index fa1715b9a996..ac1b746df6d0 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c | |||
@@ -482,6 +482,50 @@ static int lm78_isa_attach_adapter(struct i2c_adapter *adapter) | |||
482 | return lm78_detect(adapter, isa_address, -1); | 482 | return lm78_detect(adapter, isa_address, -1); |
483 | } | 483 | } |
484 | 484 | ||
485 | static struct attribute *lm78_attributes[] = { | ||
486 | &dev_attr_in0_input.attr, | ||
487 | &dev_attr_in0_min.attr, | ||
488 | &dev_attr_in0_max.attr, | ||
489 | &dev_attr_in1_input.attr, | ||
490 | &dev_attr_in1_min.attr, | ||
491 | &dev_attr_in1_max.attr, | ||
492 | &dev_attr_in2_input.attr, | ||
493 | &dev_attr_in2_min.attr, | ||
494 | &dev_attr_in2_max.attr, | ||
495 | &dev_attr_in3_input.attr, | ||
496 | &dev_attr_in3_min.attr, | ||
497 | &dev_attr_in3_max.attr, | ||
498 | &dev_attr_in4_input.attr, | ||
499 | &dev_attr_in4_min.attr, | ||
500 | &dev_attr_in4_max.attr, | ||
501 | &dev_attr_in5_input.attr, | ||
502 | &dev_attr_in5_min.attr, | ||
503 | &dev_attr_in5_max.attr, | ||
504 | &dev_attr_in6_input.attr, | ||
505 | &dev_attr_in6_min.attr, | ||
506 | &dev_attr_in6_max.attr, | ||
507 | &dev_attr_temp1_input.attr, | ||
508 | &dev_attr_temp1_max.attr, | ||
509 | &dev_attr_temp1_max_hyst.attr, | ||
510 | &dev_attr_fan1_input.attr, | ||
511 | &dev_attr_fan1_min.attr, | ||
512 | &dev_attr_fan1_div.attr, | ||
513 | &dev_attr_fan2_input.attr, | ||
514 | &dev_attr_fan2_min.attr, | ||
515 | &dev_attr_fan2_div.attr, | ||
516 | &dev_attr_fan3_input.attr, | ||
517 | &dev_attr_fan3_min.attr, | ||
518 | &dev_attr_fan3_div.attr, | ||
519 | &dev_attr_alarms.attr, | ||
520 | &dev_attr_cpu0_vid.attr, | ||
521 | |||
522 | NULL | ||
523 | }; | ||
524 | |||
525 | static const struct attribute_group lm78_group = { | ||
526 | .attrs = lm78_attributes, | ||
527 | }; | ||
528 | |||
485 | /* This function is called by i2c_probe */ | 529 | /* This function is called by i2c_probe */ |
486 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | 530 | static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) |
487 | { | 531 | { |
@@ -616,50 +660,19 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) | |||
616 | } | 660 | } |
617 | 661 | ||
618 | /* Register sysfs hooks */ | 662 | /* Register sysfs hooks */ |
663 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group))) | ||
664 | goto ERROR3; | ||
665 | |||
619 | data->class_dev = hwmon_device_register(&new_client->dev); | 666 | data->class_dev = hwmon_device_register(&new_client->dev); |
620 | if (IS_ERR(data->class_dev)) { | 667 | if (IS_ERR(data->class_dev)) { |
621 | err = PTR_ERR(data->class_dev); | 668 | err = PTR_ERR(data->class_dev); |
622 | goto ERROR3; | 669 | goto ERROR4; |
623 | } | 670 | } |
624 | 671 | ||
625 | device_create_file(&new_client->dev, &dev_attr_in0_input); | ||
626 | device_create_file(&new_client->dev, &dev_attr_in0_min); | ||
627 | device_create_file(&new_client->dev, &dev_attr_in0_max); | ||
628 | device_create_file(&new_client->dev, &dev_attr_in1_input); | ||
629 | device_create_file(&new_client->dev, &dev_attr_in1_min); | ||
630 | device_create_file(&new_client->dev, &dev_attr_in1_max); | ||
631 | device_create_file(&new_client->dev, &dev_attr_in2_input); | ||
632 | device_create_file(&new_client->dev, &dev_attr_in2_min); | ||
633 | device_create_file(&new_client->dev, &dev_attr_in2_max); | ||
634 | device_create_file(&new_client->dev, &dev_attr_in3_input); | ||
635 | device_create_file(&new_client->dev, &dev_attr_in3_min); | ||
636 | device_create_file(&new_client->dev, &dev_attr_in3_max); | ||
637 | device_create_file(&new_client->dev, &dev_attr_in4_input); | ||
638 | device_create_file(&new_client->dev, &dev_attr_in4_min); | ||
639 | device_create_file(&new_client->dev, &dev_attr_in4_max); | ||
640 | device_create_file(&new_client->dev, &dev_attr_in5_input); | ||
641 | device_create_file(&new_client->dev, &dev_attr_in5_min); | ||
642 | device_create_file(&new_client->dev, &dev_attr_in5_max); | ||
643 | device_create_file(&new_client->dev, &dev_attr_in6_input); | ||
644 | device_create_file(&new_client->dev, &dev_attr_in6_min); | ||
645 | device_create_file(&new_client->dev, &dev_attr_in6_max); | ||
646 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
647 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
648 | device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst); | ||
649 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | ||
650 | device_create_file(&new_client->dev, &dev_attr_fan1_min); | ||
651 | device_create_file(&new_client->dev, &dev_attr_fan1_div); | ||
652 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | ||
653 | device_create_file(&new_client->dev, &dev_attr_fan2_min); | ||
654 | device_create_file(&new_client->dev, &dev_attr_fan2_div); | ||
655 | device_create_file(&new_client->dev, &dev_attr_fan3_input); | ||
656 | device_create_file(&new_client->dev, &dev_attr_fan3_min); | ||
657 | device_create_file(&new_client->dev, &dev_attr_fan3_div); | ||
658 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
659 | device_create_file(&new_client->dev, &dev_attr_cpu0_vid); | ||
660 | |||
661 | return 0; | 672 | return 0; |
662 | 673 | ||
674 | ERROR4: | ||
675 | sysfs_remove_group(&new_client->dev.kobj, &lm78_group); | ||
663 | ERROR3: | 676 | ERROR3: |
664 | i2c_detach_client(new_client); | 677 | i2c_detach_client(new_client); |
665 | ERROR2: | 678 | ERROR2: |
@@ -677,6 +690,7 @@ static int lm78_detach_client(struct i2c_client *client) | |||
677 | int err; | 690 | int err; |
678 | 691 | ||
679 | hwmon_device_unregister(data->class_dev); | 692 | hwmon_device_unregister(data->class_dev); |
693 | sysfs_remove_group(&client->dev.kobj, &lm78_group); | ||
680 | 694 | ||
681 | if ((err = i2c_detach_client(client))) | 695 | if ((err = i2c_detach_client(client))) |
682 | return err; | 696 | return err; |
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index b4ccdfc01203..064516d824ad 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c | |||
@@ -394,6 +394,48 @@ static int lm80_attach_adapter(struct i2c_adapter *adapter) | |||
394 | return i2c_probe(adapter, &addr_data, lm80_detect); | 394 | return i2c_probe(adapter, &addr_data, lm80_detect); |
395 | } | 395 | } |
396 | 396 | ||
397 | static struct attribute *lm80_attributes[] = { | ||
398 | &dev_attr_in0_min.attr, | ||
399 | &dev_attr_in1_min.attr, | ||
400 | &dev_attr_in2_min.attr, | ||
401 | &dev_attr_in3_min.attr, | ||
402 | &dev_attr_in4_min.attr, | ||
403 | &dev_attr_in5_min.attr, | ||
404 | &dev_attr_in6_min.attr, | ||
405 | &dev_attr_in0_max.attr, | ||
406 | &dev_attr_in1_max.attr, | ||
407 | &dev_attr_in2_max.attr, | ||
408 | &dev_attr_in3_max.attr, | ||
409 | &dev_attr_in4_max.attr, | ||
410 | &dev_attr_in5_max.attr, | ||
411 | &dev_attr_in6_max.attr, | ||
412 | &dev_attr_in0_input.attr, | ||
413 | &dev_attr_in1_input.attr, | ||
414 | &dev_attr_in2_input.attr, | ||
415 | &dev_attr_in3_input.attr, | ||
416 | &dev_attr_in4_input.attr, | ||
417 | &dev_attr_in5_input.attr, | ||
418 | &dev_attr_in6_input.attr, | ||
419 | &dev_attr_fan1_min.attr, | ||
420 | &dev_attr_fan2_min.attr, | ||
421 | &dev_attr_fan1_input.attr, | ||
422 | &dev_attr_fan2_input.attr, | ||
423 | &dev_attr_fan1_div.attr, | ||
424 | &dev_attr_fan2_div.attr, | ||
425 | &dev_attr_temp1_input.attr, | ||
426 | &dev_attr_temp1_max.attr, | ||
427 | &dev_attr_temp1_max_hyst.attr, | ||
428 | &dev_attr_temp1_crit.attr, | ||
429 | &dev_attr_temp1_crit_hyst.attr, | ||
430 | &dev_attr_alarms.attr, | ||
431 | |||
432 | NULL | ||
433 | }; | ||
434 | |||
435 | static const struct attribute_group lm80_group = { | ||
436 | .attrs = lm80_attributes, | ||
437 | }; | ||
438 | |||
397 | static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) | 439 | static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) |
398 | { | 440 | { |
399 | int i, cur; | 441 | int i, cur; |
@@ -452,48 +494,19 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) | |||
452 | data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2)); | 494 | data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2)); |
453 | 495 | ||
454 | /* Register sysfs hooks */ | 496 | /* Register sysfs hooks */ |
497 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm80_group))) | ||
498 | goto error_detach; | ||
499 | |||
455 | data->class_dev = hwmon_device_register(&new_client->dev); | 500 | data->class_dev = hwmon_device_register(&new_client->dev); |
456 | if (IS_ERR(data->class_dev)) { | 501 | if (IS_ERR(data->class_dev)) { |
457 | err = PTR_ERR(data->class_dev); | 502 | err = PTR_ERR(data->class_dev); |
458 | goto error_detach; | 503 | goto error_remove; |
459 | } | 504 | } |
460 | 505 | ||
461 | device_create_file(&new_client->dev, &dev_attr_in0_min); | ||
462 | device_create_file(&new_client->dev, &dev_attr_in1_min); | ||
463 | device_create_file(&new_client->dev, &dev_attr_in2_min); | ||
464 | device_create_file(&new_client->dev, &dev_attr_in3_min); | ||
465 | device_create_file(&new_client->dev, &dev_attr_in4_min); | ||
466 | device_create_file(&new_client->dev, &dev_attr_in5_min); | ||
467 | device_create_file(&new_client->dev, &dev_attr_in6_min); | ||
468 | device_create_file(&new_client->dev, &dev_attr_in0_max); | ||
469 | device_create_file(&new_client->dev, &dev_attr_in1_max); | ||
470 | device_create_file(&new_client->dev, &dev_attr_in2_max); | ||
471 | device_create_file(&new_client->dev, &dev_attr_in3_max); | ||
472 | device_create_file(&new_client->dev, &dev_attr_in4_max); | ||
473 | device_create_file(&new_client->dev, &dev_attr_in5_max); | ||
474 | device_create_file(&new_client->dev, &dev_attr_in6_max); | ||
475 | device_create_file(&new_client->dev, &dev_attr_in0_input); | ||
476 | device_create_file(&new_client->dev, &dev_attr_in1_input); | ||
477 | device_create_file(&new_client->dev, &dev_attr_in2_input); | ||
478 | device_create_file(&new_client->dev, &dev_attr_in3_input); | ||
479 | device_create_file(&new_client->dev, &dev_attr_in4_input); | ||
480 | device_create_file(&new_client->dev, &dev_attr_in5_input); | ||
481 | device_create_file(&new_client->dev, &dev_attr_in6_input); | ||
482 | device_create_file(&new_client->dev, &dev_attr_fan1_min); | ||
483 | device_create_file(&new_client->dev, &dev_attr_fan2_min); | ||
484 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | ||
485 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | ||
486 | device_create_file(&new_client->dev, &dev_attr_fan1_div); | ||
487 | device_create_file(&new_client->dev, &dev_attr_fan2_div); | ||
488 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
489 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
490 | device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst); | ||
491 | device_create_file(&new_client->dev, &dev_attr_temp1_crit); | ||
492 | device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst); | ||
493 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
494 | |||
495 | return 0; | 506 | return 0; |
496 | 507 | ||
508 | error_remove: | ||
509 | sysfs_remove_group(&new_client->dev.kobj, &lm80_group); | ||
497 | error_detach: | 510 | error_detach: |
498 | i2c_detach_client(new_client); | 511 | i2c_detach_client(new_client); |
499 | error_free: | 512 | error_free: |
@@ -508,7 +521,7 @@ static int lm80_detach_client(struct i2c_client *client) | |||
508 | int err; | 521 | int err; |
509 | 522 | ||
510 | hwmon_device_unregister(data->class_dev); | 523 | hwmon_device_unregister(data->class_dev); |
511 | 524 | sysfs_remove_group(&client->dev.kobj, &lm80_group); | |
512 | if ((err = i2c_detach_client(client))) | 525 | if ((err = i2c_detach_client(client))) |
513 | return err; | 526 | return err; |
514 | 527 | ||
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index 2137d7879df6..feb87b41e986 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * lm83.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | * lm83.c - Part of lm_sensors, Linux kernel modules for hardware |
3 | * monitoring | 3 | * monitoring |
4 | * Copyright (C) 2003-2005 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2003-2006 Jean Delvare <khali@linux-fr.org> |
5 | * | 5 | * |
6 | * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is | 6 | * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is |
7 | * a sensor chip made by National Semiconductor. It reports up to four | 7 | * a sensor chip made by National Semiconductor. It reports up to four |
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/hwmon.h> | 40 | #include <linux/hwmon.h> |
41 | #include <linux/err.h> | 41 | #include <linux/err.h> |
42 | #include <linux/mutex.h> | 42 | #include <linux/mutex.h> |
43 | #include <linux/sysfs.h> | ||
43 | 44 | ||
44 | /* | 45 | /* |
45 | * Addresses to scan | 46 | * Addresses to scan |
@@ -191,6 +192,16 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, | |||
191 | return sprintf(buf, "%d\n", data->alarms); | 192 | return sprintf(buf, "%d\n", data->alarms); |
192 | } | 193 | } |
193 | 194 | ||
195 | static ssize_t show_alarm(struct device *dev, struct device_attribute | ||
196 | *devattr, char *buf) | ||
197 | { | ||
198 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
199 | struct lm83_data *data = lm83_update_device(dev); | ||
200 | int bitnr = attr->index; | ||
201 | |||
202 | return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); | ||
203 | } | ||
204 | |||
194 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | 205 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); |
195 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); | 206 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); |
196 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); | 207 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); |
@@ -208,8 +219,64 @@ static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp, NULL, 8); | |||
208 | static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp, | 219 | static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp, |
209 | set_temp, 8); | 220 | set_temp, 8); |
210 | static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8); | 221 | static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8); |
222 | |||
223 | /* Individual alarm files */ | ||
224 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); | ||
225 | static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 1); | ||
226 | static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 2); | ||
227 | static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4); | ||
228 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); | ||
229 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8); | ||
230 | static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 9); | ||
231 | static SENSOR_DEVICE_ATTR(temp4_input_fault, S_IRUGO, show_alarm, NULL, 10); | ||
232 | static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 12); | ||
233 | static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 13); | ||
234 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 15); | ||
235 | /* Raw alarm file for compatibility */ | ||
211 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 236 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
212 | 237 | ||
238 | static struct attribute *lm83_attributes[] = { | ||
239 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
240 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
241 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
242 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
243 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
244 | &sensor_dev_attr_temp3_crit.dev_attr.attr, | ||
245 | |||
246 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | ||
247 | &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, | ||
248 | &sensor_dev_attr_temp3_input_fault.dev_attr.attr, | ||
249 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, | ||
250 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
251 | &dev_attr_alarms.attr, | ||
252 | NULL | ||
253 | }; | ||
254 | |||
255 | static const struct attribute_group lm83_group = { | ||
256 | .attrs = lm83_attributes, | ||
257 | }; | ||
258 | |||
259 | static struct attribute *lm83_attributes_opt[] = { | ||
260 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
261 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
262 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
263 | &sensor_dev_attr_temp4_max.dev_attr.attr, | ||
264 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | ||
265 | &sensor_dev_attr_temp4_crit.dev_attr.attr, | ||
266 | |||
267 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | ||
268 | &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, | ||
269 | &sensor_dev_attr_temp4_input_fault.dev_attr.attr, | ||
270 | &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, | ||
271 | &sensor_dev_attr_temp2_input_fault.dev_attr.attr, | ||
272 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | ||
273 | NULL | ||
274 | }; | ||
275 | |||
276 | static const struct attribute_group lm83_group_opt = { | ||
277 | .attrs = lm83_attributes_opt, | ||
278 | }; | ||
279 | |||
213 | /* | 280 | /* |
214 | * Real code | 281 | * Real code |
215 | */ | 282 | */ |
@@ -318,59 +385,32 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) | |||
318 | goto exit_free; | 385 | goto exit_free; |
319 | 386 | ||
320 | /* | 387 | /* |
321 | * Initialize the LM83 chip | 388 | * Register sysfs hooks |
322 | * (Nothing to do for this one.) | ||
323 | */ | ||
324 | |||
325 | /* Register sysfs hooks */ | ||
326 | data->class_dev = hwmon_device_register(&new_client->dev); | ||
327 | if (IS_ERR(data->class_dev)) { | ||
328 | err = PTR_ERR(data->class_dev); | ||
329 | goto exit_detach; | ||
330 | } | ||
331 | |||
332 | /* | ||
333 | * The LM82 can only monitor one external diode which is | 389 | * The LM82 can only monitor one external diode which is |
334 | * at the same register as the LM83 temp3 entry - so we | 390 | * at the same register as the LM83 temp3 entry - so we |
335 | * declare 1 and 3 common, and then 2 and 4 only for the LM83. | 391 | * declare 1 and 3 common, and then 2 and 4 only for the LM83. |
336 | */ | 392 | */ |
337 | 393 | ||
338 | device_create_file(&new_client->dev, | 394 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group))) |
339 | &sensor_dev_attr_temp1_input.dev_attr); | 395 | goto exit_detach; |
340 | device_create_file(&new_client->dev, | ||
341 | &sensor_dev_attr_temp3_input.dev_attr); | ||
342 | |||
343 | device_create_file(&new_client->dev, | ||
344 | &sensor_dev_attr_temp1_max.dev_attr); | ||
345 | device_create_file(&new_client->dev, | ||
346 | &sensor_dev_attr_temp3_max.dev_attr); | ||
347 | |||
348 | device_create_file(&new_client->dev, | ||
349 | &sensor_dev_attr_temp1_crit.dev_attr); | ||
350 | device_create_file(&new_client->dev, | ||
351 | &sensor_dev_attr_temp3_crit.dev_attr); | ||
352 | |||
353 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
354 | 396 | ||
355 | if (kind == lm83) { | 397 | if (kind == lm83) { |
356 | device_create_file(&new_client->dev, | 398 | if ((err = sysfs_create_group(&new_client->dev.kobj, |
357 | &sensor_dev_attr_temp2_input.dev_attr); | 399 | &lm83_group_opt))) |
358 | device_create_file(&new_client->dev, | 400 | goto exit_remove_files; |
359 | &sensor_dev_attr_temp4_input.dev_attr); | 401 | } |
360 | 402 | ||
361 | device_create_file(&new_client->dev, | 403 | data->class_dev = hwmon_device_register(&new_client->dev); |
362 | &sensor_dev_attr_temp2_max.dev_attr); | 404 | if (IS_ERR(data->class_dev)) { |
363 | device_create_file(&new_client->dev, | 405 | err = PTR_ERR(data->class_dev); |
364 | &sensor_dev_attr_temp4_max.dev_attr); | 406 | goto exit_remove_files; |
365 | |||
366 | device_create_file(&new_client->dev, | ||
367 | &sensor_dev_attr_temp2_crit.dev_attr); | ||
368 | device_create_file(&new_client->dev, | ||
369 | &sensor_dev_attr_temp4_crit.dev_attr); | ||
370 | } | 407 | } |
371 | 408 | ||
372 | return 0; | 409 | return 0; |
373 | 410 | ||
411 | exit_remove_files: | ||
412 | sysfs_remove_group(&new_client->dev.kobj, &lm83_group); | ||
413 | sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt); | ||
374 | exit_detach: | 414 | exit_detach: |
375 | i2c_detach_client(new_client); | 415 | i2c_detach_client(new_client); |
376 | exit_free: | 416 | exit_free: |
@@ -385,6 +425,8 @@ static int lm83_detach_client(struct i2c_client *client) | |||
385 | int err; | 425 | int err; |
386 | 426 | ||
387 | hwmon_device_unregister(data->class_dev); | 427 | hwmon_device_unregister(data->class_dev); |
428 | sysfs_remove_group(&client->dev.kobj, &lm83_group); | ||
429 | sysfs_remove_group(&client->dev.kobj, &lm83_group_opt); | ||
388 | 430 | ||
389 | if ((err = i2c_detach_client(client))) | 431 | if ((err = i2c_detach_client(client))) |
390 | return err; | 432 | return err; |
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 342e9663119d..2c3293cf69d1 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c | |||
@@ -1025,6 +1025,89 @@ static int lm85_attach_adapter(struct i2c_adapter *adapter) | |||
1025 | return i2c_probe(adapter, &addr_data, lm85_detect); | 1025 | return i2c_probe(adapter, &addr_data, lm85_detect); |
1026 | } | 1026 | } |
1027 | 1027 | ||
1028 | static struct attribute *lm85_attributes[] = { | ||
1029 | &dev_attr_fan1_input.attr, | ||
1030 | &dev_attr_fan2_input.attr, | ||
1031 | &dev_attr_fan3_input.attr, | ||
1032 | &dev_attr_fan4_input.attr, | ||
1033 | &dev_attr_fan1_min.attr, | ||
1034 | &dev_attr_fan2_min.attr, | ||
1035 | &dev_attr_fan3_min.attr, | ||
1036 | &dev_attr_fan4_min.attr, | ||
1037 | &dev_attr_pwm1.attr, | ||
1038 | &dev_attr_pwm2.attr, | ||
1039 | &dev_attr_pwm3.attr, | ||
1040 | &dev_attr_pwm1_enable.attr, | ||
1041 | &dev_attr_pwm2_enable.attr, | ||
1042 | &dev_attr_pwm3_enable.attr, | ||
1043 | &dev_attr_in0_input.attr, | ||
1044 | &dev_attr_in1_input.attr, | ||
1045 | &dev_attr_in2_input.attr, | ||
1046 | &dev_attr_in3_input.attr, | ||
1047 | &dev_attr_in0_min.attr, | ||
1048 | &dev_attr_in1_min.attr, | ||
1049 | &dev_attr_in2_min.attr, | ||
1050 | &dev_attr_in3_min.attr, | ||
1051 | &dev_attr_in0_max.attr, | ||
1052 | &dev_attr_in1_max.attr, | ||
1053 | &dev_attr_in2_max.attr, | ||
1054 | &dev_attr_in3_max.attr, | ||
1055 | &dev_attr_temp1_input.attr, | ||
1056 | &dev_attr_temp2_input.attr, | ||
1057 | &dev_attr_temp3_input.attr, | ||
1058 | &dev_attr_temp1_min.attr, | ||
1059 | &dev_attr_temp2_min.attr, | ||
1060 | &dev_attr_temp3_min.attr, | ||
1061 | &dev_attr_temp1_max.attr, | ||
1062 | &dev_attr_temp2_max.attr, | ||
1063 | &dev_attr_temp3_max.attr, | ||
1064 | &dev_attr_vrm.attr, | ||
1065 | &dev_attr_cpu0_vid.attr, | ||
1066 | &dev_attr_alarms.attr, | ||
1067 | &dev_attr_pwm1_auto_channels.attr, | ||
1068 | &dev_attr_pwm2_auto_channels.attr, | ||
1069 | &dev_attr_pwm3_auto_channels.attr, | ||
1070 | &dev_attr_pwm1_auto_pwm_min.attr, | ||
1071 | &dev_attr_pwm2_auto_pwm_min.attr, | ||
1072 | &dev_attr_pwm3_auto_pwm_min.attr, | ||
1073 | &dev_attr_pwm1_auto_pwm_minctl.attr, | ||
1074 | &dev_attr_pwm2_auto_pwm_minctl.attr, | ||
1075 | &dev_attr_pwm3_auto_pwm_minctl.attr, | ||
1076 | &dev_attr_pwm1_auto_pwm_freq.attr, | ||
1077 | &dev_attr_pwm2_auto_pwm_freq.attr, | ||
1078 | &dev_attr_pwm3_auto_pwm_freq.attr, | ||
1079 | &dev_attr_temp1_auto_temp_off.attr, | ||
1080 | &dev_attr_temp2_auto_temp_off.attr, | ||
1081 | &dev_attr_temp3_auto_temp_off.attr, | ||
1082 | &dev_attr_temp1_auto_temp_min.attr, | ||
1083 | &dev_attr_temp2_auto_temp_min.attr, | ||
1084 | &dev_attr_temp3_auto_temp_min.attr, | ||
1085 | &dev_attr_temp1_auto_temp_max.attr, | ||
1086 | &dev_attr_temp2_auto_temp_max.attr, | ||
1087 | &dev_attr_temp3_auto_temp_max.attr, | ||
1088 | &dev_attr_temp1_auto_temp_crit.attr, | ||
1089 | &dev_attr_temp2_auto_temp_crit.attr, | ||
1090 | &dev_attr_temp3_auto_temp_crit.attr, | ||
1091 | |||
1092 | NULL | ||
1093 | }; | ||
1094 | |||
1095 | static const struct attribute_group lm85_group = { | ||
1096 | .attrs = lm85_attributes, | ||
1097 | }; | ||
1098 | |||
1099 | static struct attribute *lm85_attributes_opt[] = { | ||
1100 | &dev_attr_in4_input.attr, | ||
1101 | &dev_attr_in4_min.attr, | ||
1102 | &dev_attr_in4_max.attr, | ||
1103 | |||
1104 | NULL | ||
1105 | }; | ||
1106 | |||
1107 | static const struct attribute_group lm85_group_opt = { | ||
1108 | .attrs = lm85_attributes_opt, | ||
1109 | }; | ||
1110 | |||
1028 | static int lm85_detect(struct i2c_adapter *adapter, int address, | 1111 | static int lm85_detect(struct i2c_adapter *adapter, int address, |
1029 | int kind) | 1112 | int kind) |
1030 | { | 1113 | { |
@@ -1163,87 +1246,33 @@ static int lm85_detect(struct i2c_adapter *adapter, int address, | |||
1163 | lm85_init_client(new_client); | 1246 | lm85_init_client(new_client); |
1164 | 1247 | ||
1165 | /* Register sysfs hooks */ | 1248 | /* Register sysfs hooks */ |
1166 | data->class_dev = hwmon_device_register(&new_client->dev); | 1249 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm85_group))) |
1167 | if (IS_ERR(data->class_dev)) { | ||
1168 | err = PTR_ERR(data->class_dev); | ||
1169 | goto ERROR2; | 1250 | goto ERROR2; |
1170 | } | ||
1171 | |||
1172 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | ||
1173 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | ||
1174 | device_create_file(&new_client->dev, &dev_attr_fan3_input); | ||
1175 | device_create_file(&new_client->dev, &dev_attr_fan4_input); | ||
1176 | device_create_file(&new_client->dev, &dev_attr_fan1_min); | ||
1177 | device_create_file(&new_client->dev, &dev_attr_fan2_min); | ||
1178 | device_create_file(&new_client->dev, &dev_attr_fan3_min); | ||
1179 | device_create_file(&new_client->dev, &dev_attr_fan4_min); | ||
1180 | device_create_file(&new_client->dev, &dev_attr_pwm1); | ||
1181 | device_create_file(&new_client->dev, &dev_attr_pwm2); | ||
1182 | device_create_file(&new_client->dev, &dev_attr_pwm3); | ||
1183 | device_create_file(&new_client->dev, &dev_attr_pwm1_enable); | ||
1184 | device_create_file(&new_client->dev, &dev_attr_pwm2_enable); | ||
1185 | device_create_file(&new_client->dev, &dev_attr_pwm3_enable); | ||
1186 | device_create_file(&new_client->dev, &dev_attr_in0_input); | ||
1187 | device_create_file(&new_client->dev, &dev_attr_in1_input); | ||
1188 | device_create_file(&new_client->dev, &dev_attr_in2_input); | ||
1189 | device_create_file(&new_client->dev, &dev_attr_in3_input); | ||
1190 | device_create_file(&new_client->dev, &dev_attr_in0_min); | ||
1191 | device_create_file(&new_client->dev, &dev_attr_in1_min); | ||
1192 | device_create_file(&new_client->dev, &dev_attr_in2_min); | ||
1193 | device_create_file(&new_client->dev, &dev_attr_in3_min); | ||
1194 | device_create_file(&new_client->dev, &dev_attr_in0_max); | ||
1195 | device_create_file(&new_client->dev, &dev_attr_in1_max); | ||
1196 | device_create_file(&new_client->dev, &dev_attr_in2_max); | ||
1197 | device_create_file(&new_client->dev, &dev_attr_in3_max); | ||
1198 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
1199 | device_create_file(&new_client->dev, &dev_attr_temp2_input); | ||
1200 | device_create_file(&new_client->dev, &dev_attr_temp3_input); | ||
1201 | device_create_file(&new_client->dev, &dev_attr_temp1_min); | ||
1202 | device_create_file(&new_client->dev, &dev_attr_temp2_min); | ||
1203 | device_create_file(&new_client->dev, &dev_attr_temp3_min); | ||
1204 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
1205 | device_create_file(&new_client->dev, &dev_attr_temp2_max); | ||
1206 | device_create_file(&new_client->dev, &dev_attr_temp3_max); | ||
1207 | device_create_file(&new_client->dev, &dev_attr_vrm); | ||
1208 | device_create_file(&new_client->dev, &dev_attr_cpu0_vid); | ||
1209 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
1210 | device_create_file(&new_client->dev, &dev_attr_pwm1_auto_channels); | ||
1211 | device_create_file(&new_client->dev, &dev_attr_pwm2_auto_channels); | ||
1212 | device_create_file(&new_client->dev, &dev_attr_pwm3_auto_channels); | ||
1213 | device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_min); | ||
1214 | device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_min); | ||
1215 | device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_min); | ||
1216 | device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_minctl); | ||
1217 | device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_minctl); | ||
1218 | device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_minctl); | ||
1219 | device_create_file(&new_client->dev, &dev_attr_pwm1_auto_pwm_freq); | ||
1220 | device_create_file(&new_client->dev, &dev_attr_pwm2_auto_pwm_freq); | ||
1221 | device_create_file(&new_client->dev, &dev_attr_pwm3_auto_pwm_freq); | ||
1222 | device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_off); | ||
1223 | device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_off); | ||
1224 | device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_off); | ||
1225 | device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_min); | ||
1226 | device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_min); | ||
1227 | device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_min); | ||
1228 | device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_max); | ||
1229 | device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_max); | ||
1230 | device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_max); | ||
1231 | device_create_file(&new_client->dev, &dev_attr_temp1_auto_temp_crit); | ||
1232 | device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_crit); | ||
1233 | device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_crit); | ||
1234 | 1251 | ||
1235 | /* The ADT7463 has an optional VRM 10 mode where pin 21 is used | 1252 | /* The ADT7463 has an optional VRM 10 mode where pin 21 is used |
1236 | as a sixth digital VID input rather than an analog input. */ | 1253 | as a sixth digital VID input rather than an analog input. */ |
1237 | data->vid = lm85_read_value(new_client, LM85_REG_VID); | 1254 | data->vid = lm85_read_value(new_client, LM85_REG_VID); |
1238 | if (!(kind == adt7463 && (data->vid & 0x80))) { | 1255 | if (!(kind == adt7463 && (data->vid & 0x80))) |
1239 | device_create_file(&new_client->dev, &dev_attr_in4_input); | 1256 | if ((err = device_create_file(&new_client->dev, |
1240 | device_create_file(&new_client->dev, &dev_attr_in4_min); | 1257 | &dev_attr_in4_input)) |
1241 | device_create_file(&new_client->dev, &dev_attr_in4_max); | 1258 | || (err = device_create_file(&new_client->dev, |
1259 | &dev_attr_in4_min)) | ||
1260 | || (err = device_create_file(&new_client->dev, | ||
1261 | &dev_attr_in4_max))) | ||
1262 | goto ERROR3; | ||
1263 | |||
1264 | data->class_dev = hwmon_device_register(&new_client->dev); | ||
1265 | if (IS_ERR(data->class_dev)) { | ||
1266 | err = PTR_ERR(data->class_dev); | ||
1267 | goto ERROR3; | ||
1242 | } | 1268 | } |
1243 | 1269 | ||
1244 | return 0; | 1270 | return 0; |
1245 | 1271 | ||
1246 | /* Error out and cleanup code */ | 1272 | /* Error out and cleanup code */ |
1273 | ERROR3: | ||
1274 | sysfs_remove_group(&new_client->dev.kobj, &lm85_group); | ||
1275 | sysfs_remove_group(&new_client->dev.kobj, &lm85_group_opt); | ||
1247 | ERROR2: | 1276 | ERROR2: |
1248 | i2c_detach_client(new_client); | 1277 | i2c_detach_client(new_client); |
1249 | ERROR1: | 1278 | ERROR1: |
@@ -1256,6 +1285,8 @@ static int lm85_detach_client(struct i2c_client *client) | |||
1256 | { | 1285 | { |
1257 | struct lm85_data *data = i2c_get_clientdata(client); | 1286 | struct lm85_data *data = i2c_get_clientdata(client); |
1258 | hwmon_device_unregister(data->class_dev); | 1287 | hwmon_device_unregister(data->class_dev); |
1288 | sysfs_remove_group(&client->dev.kobj, &lm85_group); | ||
1289 | sysfs_remove_group(&client->dev.kobj, &lm85_group_opt); | ||
1259 | i2c_detach_client(client); | 1290 | i2c_detach_client(client); |
1260 | kfree(data); | 1291 | kfree(data); |
1261 | return 0; | 1292 | return 0; |
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index e6c1b638c971..3ce825489e34 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c | |||
@@ -542,6 +542,78 @@ static int lm87_attach_adapter(struct i2c_adapter *adapter) | |||
542 | return i2c_probe(adapter, &addr_data, lm87_detect); | 542 | return i2c_probe(adapter, &addr_data, lm87_detect); |
543 | } | 543 | } |
544 | 544 | ||
545 | static struct attribute *lm87_attributes[] = { | ||
546 | &dev_attr_in1_input.attr, | ||
547 | &dev_attr_in1_min.attr, | ||
548 | &dev_attr_in1_max.attr, | ||
549 | &dev_attr_in2_input.attr, | ||
550 | &dev_attr_in2_min.attr, | ||
551 | &dev_attr_in2_max.attr, | ||
552 | &dev_attr_in3_input.attr, | ||
553 | &dev_attr_in3_min.attr, | ||
554 | &dev_attr_in3_max.attr, | ||
555 | &dev_attr_in4_input.attr, | ||
556 | &dev_attr_in4_min.attr, | ||
557 | &dev_attr_in4_max.attr, | ||
558 | |||
559 | &dev_attr_temp1_input.attr, | ||
560 | &dev_attr_temp1_max.attr, | ||
561 | &dev_attr_temp1_min.attr, | ||
562 | &dev_attr_temp1_crit.attr, | ||
563 | &dev_attr_temp2_input.attr, | ||
564 | &dev_attr_temp2_max.attr, | ||
565 | &dev_attr_temp2_min.attr, | ||
566 | &dev_attr_temp2_crit.attr, | ||
567 | |||
568 | &dev_attr_alarms.attr, | ||
569 | &dev_attr_aout_output.attr, | ||
570 | |||
571 | NULL | ||
572 | }; | ||
573 | |||
574 | static const struct attribute_group lm87_group = { | ||
575 | .attrs = lm87_attributes, | ||
576 | }; | ||
577 | |||
578 | static struct attribute *lm87_attributes_opt[] = { | ||
579 | &dev_attr_in6_input.attr, | ||
580 | &dev_attr_in6_min.attr, | ||
581 | &dev_attr_in6_max.attr, | ||
582 | |||
583 | &dev_attr_fan1_input.attr, | ||
584 | &dev_attr_fan1_min.attr, | ||
585 | &dev_attr_fan1_div.attr, | ||
586 | |||
587 | &dev_attr_in7_input.attr, | ||
588 | &dev_attr_in7_min.attr, | ||
589 | &dev_attr_in7_max.attr, | ||
590 | |||
591 | &dev_attr_fan2_input.attr, | ||
592 | &dev_attr_fan2_min.attr, | ||
593 | &dev_attr_fan2_div.attr, | ||
594 | |||
595 | &dev_attr_temp3_input.attr, | ||
596 | &dev_attr_temp3_max.attr, | ||
597 | &dev_attr_temp3_min.attr, | ||
598 | &dev_attr_temp3_crit.attr, | ||
599 | |||
600 | &dev_attr_in0_input.attr, | ||
601 | &dev_attr_in0_min.attr, | ||
602 | &dev_attr_in0_max.attr, | ||
603 | &dev_attr_in5_input.attr, | ||
604 | &dev_attr_in5_min.attr, | ||
605 | &dev_attr_in5_max.attr, | ||
606 | |||
607 | &dev_attr_cpu0_vid.attr, | ||
608 | &dev_attr_vrm.attr, | ||
609 | |||
610 | NULL | ||
611 | }; | ||
612 | |||
613 | static const struct attribute_group lm87_group_opt = { | ||
614 | .attrs = lm87_attributes_opt, | ||
615 | }; | ||
616 | |||
545 | /* | 617 | /* |
546 | * The following function does more than just detection. If detection | 618 | * The following function does more than just detection. If detection |
547 | * succeeds, it also registers the new chip. | 619 | * succeeds, it also registers the new chip. |
@@ -609,77 +681,90 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) | |||
609 | data->in_scale[7] = 1875; | 681 | data->in_scale[7] = 1875; |
610 | 682 | ||
611 | /* Register sysfs hooks */ | 683 | /* Register sysfs hooks */ |
612 | data->class_dev = hwmon_device_register(&new_client->dev); | 684 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm87_group))) |
613 | if (IS_ERR(data->class_dev)) { | ||
614 | err = PTR_ERR(data->class_dev); | ||
615 | goto exit_detach; | 685 | goto exit_detach; |
616 | } | ||
617 | |||
618 | device_create_file(&new_client->dev, &dev_attr_in1_input); | ||
619 | device_create_file(&new_client->dev, &dev_attr_in1_min); | ||
620 | device_create_file(&new_client->dev, &dev_attr_in1_max); | ||
621 | device_create_file(&new_client->dev, &dev_attr_in2_input); | ||
622 | device_create_file(&new_client->dev, &dev_attr_in2_min); | ||
623 | device_create_file(&new_client->dev, &dev_attr_in2_max); | ||
624 | device_create_file(&new_client->dev, &dev_attr_in3_input); | ||
625 | device_create_file(&new_client->dev, &dev_attr_in3_min); | ||
626 | device_create_file(&new_client->dev, &dev_attr_in3_max); | ||
627 | device_create_file(&new_client->dev, &dev_attr_in4_input); | ||
628 | device_create_file(&new_client->dev, &dev_attr_in4_min); | ||
629 | device_create_file(&new_client->dev, &dev_attr_in4_max); | ||
630 | 686 | ||
631 | if (data->channel & CHAN_NO_FAN(0)) { | 687 | if (data->channel & CHAN_NO_FAN(0)) { |
632 | device_create_file(&new_client->dev, &dev_attr_in6_input); | 688 | if ((err = device_create_file(&new_client->dev, |
633 | device_create_file(&new_client->dev, &dev_attr_in6_min); | 689 | &dev_attr_in6_input)) |
634 | device_create_file(&new_client->dev, &dev_attr_in6_max); | 690 | || (err = device_create_file(&new_client->dev, |
691 | &dev_attr_in6_min)) | ||
692 | || (err = device_create_file(&new_client->dev, | ||
693 | &dev_attr_in6_max))) | ||
694 | goto exit_remove; | ||
635 | } else { | 695 | } else { |
636 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | 696 | if ((err = device_create_file(&new_client->dev, |
637 | device_create_file(&new_client->dev, &dev_attr_fan1_min); | 697 | &dev_attr_fan1_input)) |
638 | device_create_file(&new_client->dev, &dev_attr_fan1_div); | 698 | || (err = device_create_file(&new_client->dev, |
699 | &dev_attr_fan1_min)) | ||
700 | || (err = device_create_file(&new_client->dev, | ||
701 | &dev_attr_fan1_div))) | ||
702 | goto exit_remove; | ||
639 | } | 703 | } |
704 | |||
640 | if (data->channel & CHAN_NO_FAN(1)) { | 705 | if (data->channel & CHAN_NO_FAN(1)) { |
641 | device_create_file(&new_client->dev, &dev_attr_in7_input); | 706 | if ((err = device_create_file(&new_client->dev, |
642 | device_create_file(&new_client->dev, &dev_attr_in7_min); | 707 | &dev_attr_in7_input)) |
643 | device_create_file(&new_client->dev, &dev_attr_in7_max); | 708 | || (err = device_create_file(&new_client->dev, |
709 | &dev_attr_in7_min)) | ||
710 | || (err = device_create_file(&new_client->dev, | ||
711 | &dev_attr_in7_max))) | ||
712 | goto exit_remove; | ||
644 | } else { | 713 | } else { |
645 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | 714 | if ((err = device_create_file(&new_client->dev, |
646 | device_create_file(&new_client->dev, &dev_attr_fan2_min); | 715 | &dev_attr_fan2_input)) |
647 | device_create_file(&new_client->dev, &dev_attr_fan2_div); | 716 | || (err = device_create_file(&new_client->dev, |
717 | &dev_attr_fan2_min)) | ||
718 | || (err = device_create_file(&new_client->dev, | ||
719 | &dev_attr_fan2_div))) | ||
720 | goto exit_remove; | ||
648 | } | 721 | } |
649 | 722 | ||
650 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
651 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
652 | device_create_file(&new_client->dev, &dev_attr_temp1_min); | ||
653 | device_create_file(&new_client->dev, &dev_attr_temp1_crit); | ||
654 | device_create_file(&new_client->dev, &dev_attr_temp2_input); | ||
655 | device_create_file(&new_client->dev, &dev_attr_temp2_max); | ||
656 | device_create_file(&new_client->dev, &dev_attr_temp2_min); | ||
657 | device_create_file(&new_client->dev, &dev_attr_temp2_crit); | ||
658 | |||
659 | if (data->channel & CHAN_TEMP3) { | 723 | if (data->channel & CHAN_TEMP3) { |
660 | device_create_file(&new_client->dev, &dev_attr_temp3_input); | 724 | if ((err = device_create_file(&new_client->dev, |
661 | device_create_file(&new_client->dev, &dev_attr_temp3_max); | 725 | &dev_attr_temp3_input)) |
662 | device_create_file(&new_client->dev, &dev_attr_temp3_min); | 726 | || (err = device_create_file(&new_client->dev, |
663 | device_create_file(&new_client->dev, &dev_attr_temp3_crit); | 727 | &dev_attr_temp3_max)) |
728 | || (err = device_create_file(&new_client->dev, | ||
729 | &dev_attr_temp3_min)) | ||
730 | || (err = device_create_file(&new_client->dev, | ||
731 | &dev_attr_temp3_crit))) | ||
732 | goto exit_remove; | ||
664 | } else { | 733 | } else { |
665 | device_create_file(&new_client->dev, &dev_attr_in0_input); | 734 | if ((err = device_create_file(&new_client->dev, |
666 | device_create_file(&new_client->dev, &dev_attr_in0_min); | 735 | &dev_attr_in0_input)) |
667 | device_create_file(&new_client->dev, &dev_attr_in0_max); | 736 | || (err = device_create_file(&new_client->dev, |
668 | device_create_file(&new_client->dev, &dev_attr_in5_input); | 737 | &dev_attr_in0_min)) |
669 | device_create_file(&new_client->dev, &dev_attr_in5_min); | 738 | || (err = device_create_file(&new_client->dev, |
670 | device_create_file(&new_client->dev, &dev_attr_in5_max); | 739 | &dev_attr_in0_max)) |
740 | || (err = device_create_file(&new_client->dev, | ||
741 | &dev_attr_in5_input)) | ||
742 | || (err = device_create_file(&new_client->dev, | ||
743 | &dev_attr_in5_min)) | ||
744 | || (err = device_create_file(&new_client->dev, | ||
745 | &dev_attr_in5_max))) | ||
746 | goto exit_remove; | ||
671 | } | 747 | } |
672 | 748 | ||
673 | if (!(data->channel & CHAN_NO_VID)) { | 749 | if (!(data->channel & CHAN_NO_VID)) { |
674 | device_create_file(&new_client->dev, &dev_attr_cpu0_vid); | 750 | if ((err = device_create_file(&new_client->dev, |
675 | device_create_file(&new_client->dev, &dev_attr_vrm); | 751 | &dev_attr_cpu0_vid)) |
752 | || (err = device_create_file(&new_client->dev, | ||
753 | &dev_attr_vrm))) | ||
754 | goto exit_remove; | ||
676 | } | 755 | } |
677 | 756 | ||
678 | device_create_file(&new_client->dev, &dev_attr_alarms); | 757 | data->class_dev = hwmon_device_register(&new_client->dev); |
679 | device_create_file(&new_client->dev, &dev_attr_aout_output); | 758 | if (IS_ERR(data->class_dev)) { |
759 | err = PTR_ERR(data->class_dev); | ||
760 | goto exit_remove; | ||
761 | } | ||
680 | 762 | ||
681 | return 0; | 763 | return 0; |
682 | 764 | ||
765 | exit_remove: | ||
766 | sysfs_remove_group(&new_client->dev.kobj, &lm87_group); | ||
767 | sysfs_remove_group(&new_client->dev.kobj, &lm87_group_opt); | ||
683 | exit_detach: | 768 | exit_detach: |
684 | i2c_detach_client(new_client); | 769 | i2c_detach_client(new_client); |
685 | exit_free: | 770 | exit_free: |
@@ -732,6 +817,8 @@ static int lm87_detach_client(struct i2c_client *client) | |||
732 | int err; | 817 | int err; |
733 | 818 | ||
734 | hwmon_device_unregister(data->class_dev); | 819 | hwmon_device_unregister(data->class_dev); |
820 | sysfs_remove_group(&client->dev.kobj, &lm87_group); | ||
821 | sysfs_remove_group(&client->dev.kobj, &lm87_group_opt); | ||
735 | 822 | ||
736 | if ((err = i2c_detach_client(client))) | 823 | if ((err = i2c_detach_client(client))) |
737 | return err; | 824 | return err; |
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index d9eeaf7585bd..6882ce75feee 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * lm90.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | * lm90.c - Part of lm_sensors, Linux kernel modules for hardware |
3 | * monitoring | 3 | * monitoring |
4 | * Copyright (C) 2003-2005 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2003-2006 Jean Delvare <khali@linux-fr.org> |
5 | * | 5 | * |
6 | * Based on the lm83 driver. The LM90 is a sensor chip made by National | 6 | * Based on the lm83 driver. The LM90 is a sensor chip made by National |
7 | * Semiconductor. It reports up to two temperatures (its own plus up to | 7 | * Semiconductor. It reports up to two temperatures (its own plus up to |
@@ -79,6 +79,7 @@ | |||
79 | #include <linux/hwmon.h> | 79 | #include <linux/hwmon.h> |
80 | #include <linux/err.h> | 80 | #include <linux/err.h> |
81 | #include <linux/mutex.h> | 81 | #include <linux/mutex.h> |
82 | #include <linux/sysfs.h> | ||
82 | 83 | ||
83 | /* | 84 | /* |
84 | * Addresses to scan | 85 | * Addresses to scan |
@@ -327,6 +328,16 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, | |||
327 | return sprintf(buf, "%d\n", data->alarms); | 328 | return sprintf(buf, "%d\n", data->alarms); |
328 | } | 329 | } |
329 | 330 | ||
331 | static ssize_t show_alarm(struct device *dev, struct device_attribute | ||
332 | *devattr, char *buf) | ||
333 | { | ||
334 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
335 | struct lm90_data *data = lm90_update_device(dev); | ||
336 | int bitnr = attr->index; | ||
337 | |||
338 | return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); | ||
339 | } | ||
340 | |||
330 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0); | 341 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0); |
331 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); | 342 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); |
332 | static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8, | 343 | static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8, |
@@ -344,8 +355,45 @@ static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8, | |||
344 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst, | 355 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst, |
345 | set_temphyst, 3); | 356 | set_temphyst, 3); |
346 | static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4); | 357 | static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4); |
358 | |||
359 | /* Individual alarm files */ | ||
360 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); | ||
361 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); | ||
362 | static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2); | ||
363 | static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); | ||
364 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); | ||
365 | static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 5); | ||
366 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); | ||
367 | /* Raw alarm file for compatibility */ | ||
347 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 368 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
348 | 369 | ||
370 | static struct attribute *lm90_attributes[] = { | ||
371 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
372 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
373 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
374 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
375 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
376 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
377 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
378 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | ||
379 | &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, | ||
380 | &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, | ||
381 | |||
382 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | ||
383 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | ||
384 | &sensor_dev_attr_temp2_input_fault.dev_attr.attr, | ||
385 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | ||
386 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | ||
387 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | ||
388 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
389 | &dev_attr_alarms.attr, | ||
390 | NULL | ||
391 | }; | ||
392 | |||
393 | static const struct attribute_group lm90_group = { | ||
394 | .attrs = lm90_attributes, | ||
395 | }; | ||
396 | |||
349 | /* pec used for ADM1032 only */ | 397 | /* pec used for ADM1032 only */ |
350 | static ssize_t show_pec(struct device *dev, struct device_attribute *dummy, | 398 | static ssize_t show_pec(struct device *dev, struct device_attribute *dummy, |
351 | char *buf) | 399 | char *buf) |
@@ -569,39 +617,25 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) | |||
569 | lm90_init_client(new_client); | 617 | lm90_init_client(new_client); |
570 | 618 | ||
571 | /* Register sysfs hooks */ | 619 | /* Register sysfs hooks */ |
620 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm90_group))) | ||
621 | goto exit_detach; | ||
622 | if (new_client->flags & I2C_CLIENT_PEC) { | ||
623 | if ((err = device_create_file(&new_client->dev, | ||
624 | &dev_attr_pec))) | ||
625 | goto exit_remove_files; | ||
626 | } | ||
627 | |||
572 | data->class_dev = hwmon_device_register(&new_client->dev); | 628 | data->class_dev = hwmon_device_register(&new_client->dev); |
573 | if (IS_ERR(data->class_dev)) { | 629 | if (IS_ERR(data->class_dev)) { |
574 | err = PTR_ERR(data->class_dev); | 630 | err = PTR_ERR(data->class_dev); |
575 | goto exit_detach; | 631 | goto exit_remove_files; |
576 | } | 632 | } |
577 | 633 | ||
578 | device_create_file(&new_client->dev, | ||
579 | &sensor_dev_attr_temp1_input.dev_attr); | ||
580 | device_create_file(&new_client->dev, | ||
581 | &sensor_dev_attr_temp2_input.dev_attr); | ||
582 | device_create_file(&new_client->dev, | ||
583 | &sensor_dev_attr_temp1_min.dev_attr); | ||
584 | device_create_file(&new_client->dev, | ||
585 | &sensor_dev_attr_temp2_min.dev_attr); | ||
586 | device_create_file(&new_client->dev, | ||
587 | &sensor_dev_attr_temp1_max.dev_attr); | ||
588 | device_create_file(&new_client->dev, | ||
589 | &sensor_dev_attr_temp2_max.dev_attr); | ||
590 | device_create_file(&new_client->dev, | ||
591 | &sensor_dev_attr_temp1_crit.dev_attr); | ||
592 | device_create_file(&new_client->dev, | ||
593 | &sensor_dev_attr_temp2_crit.dev_attr); | ||
594 | device_create_file(&new_client->dev, | ||
595 | &sensor_dev_attr_temp1_crit_hyst.dev_attr); | ||
596 | device_create_file(&new_client->dev, | ||
597 | &sensor_dev_attr_temp2_crit_hyst.dev_attr); | ||
598 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
599 | |||
600 | if (new_client->flags & I2C_CLIENT_PEC) | ||
601 | device_create_file(&new_client->dev, &dev_attr_pec); | ||
602 | |||
603 | return 0; | 634 | return 0; |
604 | 635 | ||
636 | exit_remove_files: | ||
637 | sysfs_remove_group(&new_client->dev.kobj, &lm90_group); | ||
638 | device_remove_file(&new_client->dev, &dev_attr_pec); | ||
605 | exit_detach: | 639 | exit_detach: |
606 | i2c_detach_client(new_client); | 640 | i2c_detach_client(new_client); |
607 | exit_free: | 641 | exit_free: |
@@ -634,6 +668,8 @@ static int lm90_detach_client(struct i2c_client *client) | |||
634 | int err; | 668 | int err; |
635 | 669 | ||
636 | hwmon_device_unregister(data->class_dev); | 670 | hwmon_device_unregister(data->class_dev); |
671 | sysfs_remove_group(&client->dev.kobj, &lm90_group); | ||
672 | device_remove_file(&client->dev, &dev_attr_pec); | ||
637 | 673 | ||
638 | if ((err = i2c_detach_client(client))) | 674 | if ((err = i2c_detach_client(client))) |
639 | return err; | 675 | return err; |
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index 197f77226dc4..30b536333f14 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c | |||
@@ -288,6 +288,23 @@ static int max6635_check(struct i2c_client *client) | |||
288 | return 1; | 288 | return 1; |
289 | } | 289 | } |
290 | 290 | ||
291 | static struct attribute *lm92_attributes[] = { | ||
292 | &dev_attr_temp1_input.attr, | ||
293 | &dev_attr_temp1_crit.attr, | ||
294 | &dev_attr_temp1_crit_hyst.attr, | ||
295 | &dev_attr_temp1_min.attr, | ||
296 | &dev_attr_temp1_min_hyst.attr, | ||
297 | &dev_attr_temp1_max.attr, | ||
298 | &dev_attr_temp1_max_hyst.attr, | ||
299 | &dev_attr_alarms.attr, | ||
300 | |||
301 | NULL | ||
302 | }; | ||
303 | |||
304 | static const struct attribute_group lm92_group = { | ||
305 | .attrs = lm92_attributes, | ||
306 | }; | ||
307 | |||
291 | /* The following function does more than just detection. If detection | 308 | /* The following function does more than just detection. If detection |
292 | succeeds, it also registers the new chip. */ | 309 | succeeds, it also registers the new chip. */ |
293 | static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) | 310 | static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) |
@@ -359,23 +376,19 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) | |||
359 | lm92_init_client(new_client); | 376 | lm92_init_client(new_client); |
360 | 377 | ||
361 | /* Register sysfs hooks */ | 378 | /* Register sysfs hooks */ |
379 | if ((err = sysfs_create_group(&new_client->dev.kobj, &lm92_group))) | ||
380 | goto exit_detach; | ||
381 | |||
362 | data->class_dev = hwmon_device_register(&new_client->dev); | 382 | data->class_dev = hwmon_device_register(&new_client->dev); |
363 | if (IS_ERR(data->class_dev)) { | 383 | if (IS_ERR(data->class_dev)) { |
364 | err = PTR_ERR(data->class_dev); | 384 | err = PTR_ERR(data->class_dev); |
365 | goto exit_detach; | 385 | goto exit_remove; |
366 | } | 386 | } |
367 | 387 | ||
368 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
369 | device_create_file(&new_client->dev, &dev_attr_temp1_crit); | ||
370 | device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst); | ||
371 | device_create_file(&new_client->dev, &dev_attr_temp1_min); | ||
372 | device_create_file(&new_client->dev, &dev_attr_temp1_min_hyst); | ||
373 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
374 | device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst); | ||
375 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
376 | |||
377 | return 0; | 388 | return 0; |
378 | 389 | ||
390 | exit_remove: | ||
391 | sysfs_remove_group(&new_client->dev.kobj, &lm92_group); | ||
379 | exit_detach: | 392 | exit_detach: |
380 | i2c_detach_client(new_client); | 393 | i2c_detach_client(new_client); |
381 | exit_free: | 394 | exit_free: |
@@ -397,6 +410,7 @@ static int lm92_detach_client(struct i2c_client *client) | |||
397 | int err; | 410 | int err; |
398 | 411 | ||
399 | hwmon_device_unregister(data->class_dev); | 412 | hwmon_device_unregister(data->class_dev); |
413 | sysfs_remove_group(&client->dev.kobj, &lm92_group); | ||
400 | 414 | ||
401 | if ((err = i2c_detach_client(client))) | 415 | if ((err = i2c_detach_client(client))) |
402 | return err; | 416 | return err; |
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index b4135b5971f4..2f58f651f03a 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/hwmon.h> | 34 | #include <linux/hwmon.h> |
35 | #include <linux/err.h> | 35 | #include <linux/err.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/sysfs.h> | ||
37 | 38 | ||
38 | static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, | 39 | static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, |
39 | 0x29, 0x2a, 0x2b, | 40 | 0x29, 0x2a, 0x2b, |
@@ -172,6 +173,22 @@ static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst2, | |||
172 | set_temp_hyst2); | 173 | set_temp_hyst2); |
173 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 174 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
174 | 175 | ||
176 | static struct attribute *max1619_attributes[] = { | ||
177 | &dev_attr_temp1_input.attr, | ||
178 | &dev_attr_temp2_input.attr, | ||
179 | &dev_attr_temp2_min.attr, | ||
180 | &dev_attr_temp2_max.attr, | ||
181 | &dev_attr_temp2_crit.attr, | ||
182 | &dev_attr_temp2_crit_hyst.attr, | ||
183 | |||
184 | &dev_attr_alarms.attr, | ||
185 | NULL | ||
186 | }; | ||
187 | |||
188 | static const struct attribute_group max1619_group = { | ||
189 | .attrs = max1619_attributes, | ||
190 | }; | ||
191 | |||
175 | /* | 192 | /* |
176 | * Real code | 193 | * Real code |
177 | */ | 194 | */ |
@@ -273,22 +290,19 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) | |||
273 | max1619_init_client(new_client); | 290 | max1619_init_client(new_client); |
274 | 291 | ||
275 | /* Register sysfs hooks */ | 292 | /* Register sysfs hooks */ |
293 | if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group))) | ||
294 | goto exit_detach; | ||
295 | |||
276 | data->class_dev = hwmon_device_register(&new_client->dev); | 296 | data->class_dev = hwmon_device_register(&new_client->dev); |
277 | if (IS_ERR(data->class_dev)) { | 297 | if (IS_ERR(data->class_dev)) { |
278 | err = PTR_ERR(data->class_dev); | 298 | err = PTR_ERR(data->class_dev); |
279 | goto exit_detach; | 299 | goto exit_remove_files; |
280 | } | 300 | } |
281 | 301 | ||
282 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
283 | device_create_file(&new_client->dev, &dev_attr_temp2_input); | ||
284 | device_create_file(&new_client->dev, &dev_attr_temp2_min); | ||
285 | device_create_file(&new_client->dev, &dev_attr_temp2_max); | ||
286 | device_create_file(&new_client->dev, &dev_attr_temp2_crit); | ||
287 | device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst); | ||
288 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
289 | |||
290 | return 0; | 302 | return 0; |
291 | 303 | ||
304 | exit_remove_files: | ||
305 | sysfs_remove_group(&new_client->dev.kobj, &max1619_group); | ||
292 | exit_detach: | 306 | exit_detach: |
293 | i2c_detach_client(new_client); | 307 | i2c_detach_client(new_client); |
294 | exit_free: | 308 | exit_free: |
@@ -318,6 +332,7 @@ static int max1619_detach_client(struct i2c_client *client) | |||
318 | int err; | 332 | int err; |
319 | 333 | ||
320 | hwmon_device_unregister(data->class_dev); | 334 | hwmon_device_unregister(data->class_dev); |
335 | sysfs_remove_group(&client->dev.kobj, &max1619_group); | ||
321 | 336 | ||
322 | if ((err = i2c_detach_client(client))) | 337 | if ((err = i2c_detach_client(client))) |
323 | return err; | 338 | return err; |
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 236f9f29c624..3b8b81984ad4 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c | |||
@@ -328,6 +328,12 @@ static struct sensor_device_attribute fan_min[] = { | |||
328 | SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2), | 328 | SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2), |
329 | }; | 329 | }; |
330 | 330 | ||
331 | #define FAN_UNIT_ATTRS(X) \ | ||
332 | &fan_input[X].dev_attr.attr, \ | ||
333 | &fan_status[X].dev_attr.attr, \ | ||
334 | &fan_div[X].dev_attr.attr, \ | ||
335 | &fan_min[X].dev_attr.attr | ||
336 | |||
331 | static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf) | 337 | static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf) |
332 | { | 338 | { |
333 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 339 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
@@ -360,6 +366,19 @@ static struct sensor_device_attribute pwm[] = { | |||
360 | SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2), | 366 | SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2), |
361 | }; | 367 | }; |
362 | 368 | ||
369 | static struct attribute * pc8736x_fan_attr_array[] = { | ||
370 | FAN_UNIT_ATTRS(0), | ||
371 | FAN_UNIT_ATTRS(1), | ||
372 | FAN_UNIT_ATTRS(2), | ||
373 | &pwm[0].dev_attr.attr, | ||
374 | &pwm[1].dev_attr.attr, | ||
375 | &pwm[2].dev_attr.attr, | ||
376 | NULL | ||
377 | }; | ||
378 | static const struct attribute_group pc8736x_fan_group = { | ||
379 | .attrs = pc8736x_fan_attr_array, | ||
380 | }; | ||
381 | |||
363 | static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf) | 382 | static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf) |
364 | { | 383 | { |
365 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 384 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
@@ -472,6 +491,61 @@ static struct sensor_device_attribute in_max[] = { | |||
472 | SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10), | 491 | SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10), |
473 | }; | 492 | }; |
474 | 493 | ||
494 | #define VIN_UNIT_ATTRS(X) \ | ||
495 | &in_input[X].dev_attr.attr, \ | ||
496 | &in_status[X].dev_attr.attr, \ | ||
497 | &in_min[X].dev_attr.attr, \ | ||
498 | &in_max[X].dev_attr.attr | ||
499 | |||
500 | static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) | ||
501 | { | ||
502 | struct pc87360_data *data = pc87360_update_device(dev); | ||
503 | return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm)); | ||
504 | } | ||
505 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); | ||
506 | |||
507 | static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) | ||
508 | { | ||
509 | struct pc87360_data *data = pc87360_update_device(dev); | ||
510 | return sprintf(buf, "%u\n", data->vrm); | ||
511 | } | ||
512 | static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | ||
513 | { | ||
514 | struct i2c_client *client = to_i2c_client(dev); | ||
515 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
516 | data->vrm = simple_strtoul(buf, NULL, 10); | ||
517 | return count; | ||
518 | } | ||
519 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); | ||
520 | |||
521 | static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf) | ||
522 | { | ||
523 | struct pc87360_data *data = pc87360_update_device(dev); | ||
524 | return sprintf(buf, "%u\n", data->in_alarms); | ||
525 | } | ||
526 | static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL); | ||
527 | |||
528 | static struct attribute *pc8736x_vin_attr_array[] = { | ||
529 | VIN_UNIT_ATTRS(0), | ||
530 | VIN_UNIT_ATTRS(1), | ||
531 | VIN_UNIT_ATTRS(2), | ||
532 | VIN_UNIT_ATTRS(3), | ||
533 | VIN_UNIT_ATTRS(4), | ||
534 | VIN_UNIT_ATTRS(5), | ||
535 | VIN_UNIT_ATTRS(6), | ||
536 | VIN_UNIT_ATTRS(7), | ||
537 | VIN_UNIT_ATTRS(8), | ||
538 | VIN_UNIT_ATTRS(9), | ||
539 | VIN_UNIT_ATTRS(10), | ||
540 | &dev_attr_cpu0_vid.attr, | ||
541 | &dev_attr_vrm.attr, | ||
542 | &dev_attr_alarms_in.attr, | ||
543 | NULL | ||
544 | }; | ||
545 | static const struct attribute_group pc8736x_vin_group = { | ||
546 | .attrs = pc8736x_vin_attr_array, | ||
547 | }; | ||
548 | |||
475 | static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf) | 549 | static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf) |
476 | { | 550 | { |
477 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 551 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
@@ -590,33 +664,22 @@ static struct sensor_device_attribute therm_crit[] = { | |||
590 | show_therm_crit, set_therm_crit, 2+11), | 664 | show_therm_crit, set_therm_crit, 2+11), |
591 | }; | 665 | }; |
592 | 666 | ||
593 | static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf) | 667 | #define THERM_UNIT_ATTRS(X) \ |
594 | { | 668 | &therm_input[X].dev_attr.attr, \ |
595 | struct pc87360_data *data = pc87360_update_device(dev); | 669 | &therm_status[X].dev_attr.attr, \ |
596 | return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm)); | 670 | &therm_min[X].dev_attr.attr, \ |
597 | } | 671 | &therm_max[X].dev_attr.attr, \ |
598 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); | 672 | &therm_crit[X].dev_attr.attr |
599 | 673 | ||
600 | static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) | 674 | static struct attribute * pc8736x_therm_attr_array[] = { |
601 | { | 675 | THERM_UNIT_ATTRS(0), |
602 | struct pc87360_data *data = pc87360_update_device(dev); | 676 | THERM_UNIT_ATTRS(1), |
603 | return sprintf(buf, "%u\n", data->vrm); | 677 | THERM_UNIT_ATTRS(2), |
604 | } | 678 | NULL |
605 | static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 679 | }; |
606 | { | 680 | static const struct attribute_group pc8736x_therm_group = { |
607 | struct i2c_client *client = to_i2c_client(dev); | 681 | .attrs = pc8736x_therm_attr_array, |
608 | struct pc87360_data *data = i2c_get_clientdata(client); | 682 | }; |
609 | data->vrm = simple_strtoul(buf, NULL, 10); | ||
610 | return count; | ||
611 | } | ||
612 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); | ||
613 | |||
614 | static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf) | ||
615 | { | ||
616 | struct pc87360_data *data = pc87360_update_device(dev); | ||
617 | return sprintf(buf, "%u\n", data->in_alarms); | ||
618 | } | ||
619 | static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL); | ||
620 | 683 | ||
621 | static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf) | 684 | static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf) |
622 | { | 685 | { |
@@ -736,6 +799,25 @@ static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *att | |||
736 | } | 799 | } |
737 | static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL); | 800 | static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL); |
738 | 801 | ||
802 | #define TEMP_UNIT_ATTRS(X) \ | ||
803 | &temp_input[X].dev_attr.attr, \ | ||
804 | &temp_status[X].dev_attr.attr, \ | ||
805 | &temp_min[X].dev_attr.attr, \ | ||
806 | &temp_max[X].dev_attr.attr, \ | ||
807 | &temp_crit[X].dev_attr.attr | ||
808 | |||
809 | static struct attribute * pc8736x_temp_attr_array[] = { | ||
810 | TEMP_UNIT_ATTRS(0), | ||
811 | TEMP_UNIT_ATTRS(1), | ||
812 | TEMP_UNIT_ATTRS(2), | ||
813 | /* include the few miscellaneous atts here */ | ||
814 | &dev_attr_alarms_temp.attr, | ||
815 | NULL | ||
816 | }; | ||
817 | static const struct attribute_group pc8736x_temp_group = { | ||
818 | .attrs = pc8736x_temp_attr_array, | ||
819 | }; | ||
820 | |||
739 | /* | 821 | /* |
740 | * Device detection, registration and update | 822 | * Device detection, registration and update |
741 | */ | 823 | */ |
@@ -936,60 +1018,69 @@ static int pc87360_detect(struct i2c_adapter *adapter) | |||
936 | pc87360_init_client(client, use_thermistors); | 1018 | pc87360_init_client(client, use_thermistors); |
937 | } | 1019 | } |
938 | 1020 | ||
939 | /* Register sysfs hooks */ | 1021 | /* Register all-or-nothing sysfs groups */ |
940 | data->class_dev = hwmon_device_register(&client->dev); | 1022 | |
941 | if (IS_ERR(data->class_dev)) { | 1023 | if (data->innr && |
942 | err = PTR_ERR(data->class_dev); | 1024 | (err = sysfs_create_group(&client->dev.kobj, |
1025 | &pc8736x_vin_group))) | ||
943 | goto ERROR3; | 1026 | goto ERROR3; |
944 | } | ||
945 | 1027 | ||
946 | if (data->innr) { | 1028 | if (data->innr == 14 && |
947 | for (i = 0; i < 11; i++) { | 1029 | (err = sysfs_create_group(&client->dev.kobj, |
948 | device_create_file(dev, &in_input[i].dev_attr); | 1030 | &pc8736x_therm_group))) |
949 | device_create_file(dev, &in_min[i].dev_attr); | 1031 | goto ERROR3; |
950 | device_create_file(dev, &in_max[i].dev_attr); | 1032 | |
951 | device_create_file(dev, &in_status[i].dev_attr); | 1033 | /* create device attr-files for varying sysfs groups */ |
952 | } | ||
953 | device_create_file(dev, &dev_attr_cpu0_vid); | ||
954 | device_create_file(dev, &dev_attr_vrm); | ||
955 | device_create_file(dev, &dev_attr_alarms_in); | ||
956 | } | ||
957 | 1034 | ||
958 | if (data->tempnr) { | 1035 | if (data->tempnr) { |
959 | for (i = 0; i < data->tempnr; i++) { | 1036 | for (i = 0; i < data->tempnr; i++) { |
960 | device_create_file(dev, &temp_input[i].dev_attr); | 1037 | if ((err = device_create_file(dev, |
961 | device_create_file(dev, &temp_min[i].dev_attr); | 1038 | &temp_input[i].dev_attr)) |
962 | device_create_file(dev, &temp_max[i].dev_attr); | 1039 | || (err = device_create_file(dev, |
963 | device_create_file(dev, &temp_crit[i].dev_attr); | 1040 | &temp_min[i].dev_attr)) |
964 | device_create_file(dev, &temp_status[i].dev_attr); | 1041 | || (err = device_create_file(dev, |
965 | } | 1042 | &temp_max[i].dev_attr)) |
966 | device_create_file(dev, &dev_attr_alarms_temp); | 1043 | || (err = device_create_file(dev, |
967 | } | 1044 | &temp_crit[i].dev_attr)) |
968 | 1045 | || (err = device_create_file(dev, | |
969 | if (data->innr == 14) { | 1046 | &temp_status[i].dev_attr))) |
970 | for (i = 0; i < 3; i++) { | 1047 | goto ERROR3; |
971 | device_create_file(dev, &therm_input[i].dev_attr); | ||
972 | device_create_file(dev, &therm_min[i].dev_attr); | ||
973 | device_create_file(dev, &therm_max[i].dev_attr); | ||
974 | device_create_file(dev, &therm_crit[i].dev_attr); | ||
975 | device_create_file(dev, &therm_status[i].dev_attr); | ||
976 | } | 1048 | } |
1049 | if ((err = device_create_file(dev, &dev_attr_alarms_temp))) | ||
1050 | goto ERROR3; | ||
977 | } | 1051 | } |
978 | 1052 | ||
979 | for (i = 0; i < data->fannr; i++) { | 1053 | for (i = 0; i < data->fannr; i++) { |
980 | if (FAN_CONFIG_MONITOR(data->fan_conf, i)) { | 1054 | if (FAN_CONFIG_MONITOR(data->fan_conf, i) |
981 | device_create_file(dev, &fan_input[i].dev_attr); | 1055 | && ((err = device_create_file(dev, |
982 | device_create_file(dev, &fan_min[i].dev_attr); | 1056 | &fan_input[i].dev_attr)) |
983 | device_create_file(dev, &fan_div[i].dev_attr); | 1057 | || (err = device_create_file(dev, |
984 | device_create_file(dev, &fan_status[i].dev_attr); | 1058 | &fan_min[i].dev_attr)) |
985 | } | 1059 | || (err = device_create_file(dev, |
986 | if (FAN_CONFIG_CONTROL(data->fan_conf, i)) | 1060 | &fan_div[i].dev_attr)) |
987 | device_create_file(dev, &pwm[i].dev_attr); | 1061 | || (err = device_create_file(dev, |
1062 | &fan_status[i].dev_attr)))) | ||
1063 | goto ERROR3; | ||
1064 | |||
1065 | if (FAN_CONFIG_CONTROL(data->fan_conf, i) | ||
1066 | && (err = device_create_file(dev, &pwm[i].dev_attr))) | ||
1067 | goto ERROR3; | ||
988 | } | 1068 | } |
989 | 1069 | ||
1070 | data->class_dev = hwmon_device_register(&client->dev); | ||
1071 | if (IS_ERR(data->class_dev)) { | ||
1072 | err = PTR_ERR(data->class_dev); | ||
1073 | goto ERROR3; | ||
1074 | } | ||
990 | return 0; | 1075 | return 0; |
991 | 1076 | ||
992 | ERROR3: | 1077 | ERROR3: |
1078 | /* can still remove groups whose members were added individually */ | ||
1079 | sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group); | ||
1080 | sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group); | ||
1081 | sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group); | ||
1082 | sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group); | ||
1083 | |||
993 | i2c_detach_client(client); | 1084 | i2c_detach_client(client); |
994 | ERROR2: | 1085 | ERROR2: |
995 | for (i = 0; i < 3; i++) { | 1086 | for (i = 0; i < 3; i++) { |
@@ -1009,6 +1100,11 @@ static int pc87360_detach_client(struct i2c_client *client) | |||
1009 | 1100 | ||
1010 | hwmon_device_unregister(data->class_dev); | 1101 | hwmon_device_unregister(data->class_dev); |
1011 | 1102 | ||
1103 | sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group); | ||
1104 | sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group); | ||
1105 | sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group); | ||
1106 | sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group); | ||
1107 | |||
1012 | if ((i = i2c_detach_client(client))) | 1108 | if ((i = i2c_detach_client(client))) |
1013 | return i; | 1109 | return i; |
1014 | 1110 | ||
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 3783af4195bd..95a4b5d9eaf2 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include <linux/init.h> | 61 | #include <linux/init.h> |
62 | #include <linux/jiffies.h> | 62 | #include <linux/jiffies.h> |
63 | #include <linux/mutex.h> | 63 | #include <linux/mutex.h> |
64 | #include <linux/sysfs.h> | ||
64 | #include <asm/io.h> | 65 | #include <asm/io.h> |
65 | 66 | ||
66 | 67 | ||
@@ -473,6 +474,50 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch | |||
473 | return sprintf(buf, "%d\n", data->alarms); | 474 | return sprintf(buf, "%d\n", data->alarms); |
474 | } | 475 | } |
475 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 476 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
477 | |||
478 | static struct attribute *sis5595_attributes[] = { | ||
479 | &dev_attr_in0_input.attr, | ||
480 | &dev_attr_in0_min.attr, | ||
481 | &dev_attr_in0_max.attr, | ||
482 | &dev_attr_in1_input.attr, | ||
483 | &dev_attr_in1_min.attr, | ||
484 | &dev_attr_in1_max.attr, | ||
485 | &dev_attr_in2_input.attr, | ||
486 | &dev_attr_in2_min.attr, | ||
487 | &dev_attr_in2_max.attr, | ||
488 | &dev_attr_in3_input.attr, | ||
489 | &dev_attr_in3_min.attr, | ||
490 | &dev_attr_in3_max.attr, | ||
491 | |||
492 | &dev_attr_fan1_input.attr, | ||
493 | &dev_attr_fan1_min.attr, | ||
494 | &dev_attr_fan1_div.attr, | ||
495 | &dev_attr_fan2_input.attr, | ||
496 | &dev_attr_fan2_min.attr, | ||
497 | &dev_attr_fan2_div.attr, | ||
498 | |||
499 | &dev_attr_alarms.attr, | ||
500 | NULL | ||
501 | }; | ||
502 | |||
503 | static const struct attribute_group sis5595_group = { | ||
504 | .attrs = sis5595_attributes, | ||
505 | }; | ||
506 | |||
507 | static struct attribute *sis5595_attributes_opt[] = { | ||
508 | &dev_attr_in4_input.attr, | ||
509 | &dev_attr_in4_min.attr, | ||
510 | &dev_attr_in4_max.attr, | ||
511 | |||
512 | &dev_attr_temp1_input.attr, | ||
513 | &dev_attr_temp1_max.attr, | ||
514 | &dev_attr_temp1_max_hyst.attr, | ||
515 | NULL | ||
516 | }; | ||
517 | |||
518 | static const struct attribute_group sis5595_group_opt = { | ||
519 | .attrs = sis5595_attributes_opt, | ||
520 | }; | ||
476 | 521 | ||
477 | /* This is called when the module is loaded */ | 522 | /* This is called when the module is loaded */ |
478 | static int sis5595_detect(struct i2c_adapter *adapter) | 523 | static int sis5595_detect(struct i2c_adapter *adapter) |
@@ -566,43 +611,37 @@ static int sis5595_detect(struct i2c_adapter *adapter) | |||
566 | } | 611 | } |
567 | 612 | ||
568 | /* Register sysfs hooks */ | 613 | /* Register sysfs hooks */ |
614 | if ((err = sysfs_create_group(&new_client->dev.kobj, &sis5595_group))) | ||
615 | goto exit_detach; | ||
616 | if (data->maxins == 4) { | ||
617 | if ((err = device_create_file(&new_client->dev, | ||
618 | &dev_attr_in4_input)) | ||
619 | || (err = device_create_file(&new_client->dev, | ||
620 | &dev_attr_in4_min)) | ||
621 | || (err = device_create_file(&new_client->dev, | ||
622 | &dev_attr_in4_max))) | ||
623 | goto exit_remove_files; | ||
624 | } else { | ||
625 | if ((err = device_create_file(&new_client->dev, | ||
626 | &dev_attr_temp1_input)) | ||
627 | || (err = device_create_file(&new_client->dev, | ||
628 | &dev_attr_temp1_max)) | ||
629 | || (err = device_create_file(&new_client->dev, | ||
630 | &dev_attr_temp1_max_hyst))) | ||
631 | goto exit_remove_files; | ||
632 | } | ||
633 | |||
569 | data->class_dev = hwmon_device_register(&new_client->dev); | 634 | data->class_dev = hwmon_device_register(&new_client->dev); |
570 | if (IS_ERR(data->class_dev)) { | 635 | if (IS_ERR(data->class_dev)) { |
571 | err = PTR_ERR(data->class_dev); | 636 | err = PTR_ERR(data->class_dev); |
572 | goto exit_detach; | 637 | goto exit_remove_files; |
573 | } | 638 | } |
574 | 639 | ||
575 | device_create_file(&new_client->dev, &dev_attr_in0_input); | ||
576 | device_create_file(&new_client->dev, &dev_attr_in0_min); | ||
577 | device_create_file(&new_client->dev, &dev_attr_in0_max); | ||
578 | device_create_file(&new_client->dev, &dev_attr_in1_input); | ||
579 | device_create_file(&new_client->dev, &dev_attr_in1_min); | ||
580 | device_create_file(&new_client->dev, &dev_attr_in1_max); | ||
581 | device_create_file(&new_client->dev, &dev_attr_in2_input); | ||
582 | device_create_file(&new_client->dev, &dev_attr_in2_min); | ||
583 | device_create_file(&new_client->dev, &dev_attr_in2_max); | ||
584 | device_create_file(&new_client->dev, &dev_attr_in3_input); | ||
585 | device_create_file(&new_client->dev, &dev_attr_in3_min); | ||
586 | device_create_file(&new_client->dev, &dev_attr_in3_max); | ||
587 | if (data->maxins == 4) { | ||
588 | device_create_file(&new_client->dev, &dev_attr_in4_input); | ||
589 | device_create_file(&new_client->dev, &dev_attr_in4_min); | ||
590 | device_create_file(&new_client->dev, &dev_attr_in4_max); | ||
591 | } | ||
592 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | ||
593 | device_create_file(&new_client->dev, &dev_attr_fan1_min); | ||
594 | device_create_file(&new_client->dev, &dev_attr_fan1_div); | ||
595 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | ||
596 | device_create_file(&new_client->dev, &dev_attr_fan2_min); | ||
597 | device_create_file(&new_client->dev, &dev_attr_fan2_div); | ||
598 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
599 | if (data->maxins == 3) { | ||
600 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
601 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
602 | device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst); | ||
603 | } | ||
604 | return 0; | 640 | return 0; |
605 | 641 | ||
642 | exit_remove_files: | ||
643 | sysfs_remove_group(&new_client->dev.kobj, &sis5595_group); | ||
644 | sysfs_remove_group(&new_client->dev.kobj, &sis5595_group_opt); | ||
606 | exit_detach: | 645 | exit_detach: |
607 | i2c_detach_client(new_client); | 646 | i2c_detach_client(new_client); |
608 | exit_free: | 647 | exit_free: |
@@ -619,6 +658,8 @@ static int sis5595_detach_client(struct i2c_client *client) | |||
619 | int err; | 658 | int err; |
620 | 659 | ||
621 | hwmon_device_unregister(data->class_dev); | 660 | hwmon_device_unregister(data->class_dev); |
661 | sysfs_remove_group(&client->dev.kobj, &sis5595_group); | ||
662 | sysfs_remove_group(&client->dev.kobj, &sis5595_group_opt); | ||
622 | 663 | ||
623 | if ((err = i2c_detach_client(client))) | 664 | if ((err = i2c_detach_client(client))) |
624 | return err; | 665 | return err; |
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index a85869393bab..72b0e2d8650c 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c | |||
@@ -176,9 +176,6 @@ sysfs_temp(2); | |||
176 | sysfs_temp(3); | 176 | sysfs_temp(3); |
177 | sysfs_temp(4); | 177 | sysfs_temp(4); |
178 | 178 | ||
179 | #define device_create_file_temp(client, num) \ | ||
180 | device_create_file(&client->dev, &dev_attr_temp##num##_input) | ||
181 | |||
182 | /* FAN: 1 RPM/bit | 179 | /* FAN: 1 RPM/bit |
183 | REG: count of 90kHz pulses / revolution */ | 180 | REG: count of 90kHz pulses / revolution */ |
184 | static int fan_from_reg(u16 reg) | 181 | static int fan_from_reg(u16 reg) |
@@ -205,8 +202,22 @@ sysfs_fan(2); | |||
205 | sysfs_fan(3); | 202 | sysfs_fan(3); |
206 | sysfs_fan(4); | 203 | sysfs_fan(4); |
207 | 204 | ||
208 | #define device_create_file_fan(client, num) \ | 205 | static struct attribute *smsc47b397_attributes[] = { |
209 | device_create_file(&client->dev, &dev_attr_fan##num##_input) | 206 | &dev_attr_temp1_input.attr, |
207 | &dev_attr_temp2_input.attr, | ||
208 | &dev_attr_temp3_input.attr, | ||
209 | &dev_attr_temp4_input.attr, | ||
210 | &dev_attr_fan1_input.attr, | ||
211 | &dev_attr_fan2_input.attr, | ||
212 | &dev_attr_fan3_input.attr, | ||
213 | &dev_attr_fan4_input.attr, | ||
214 | |||
215 | NULL | ||
216 | }; | ||
217 | |||
218 | static const struct attribute_group smsc47b397_group = { | ||
219 | .attrs = smsc47b397_attributes, | ||
220 | }; | ||
210 | 221 | ||
211 | static int smsc47b397_detach_client(struct i2c_client *client) | 222 | static int smsc47b397_detach_client(struct i2c_client *client) |
212 | { | 223 | { |
@@ -214,6 +225,7 @@ static int smsc47b397_detach_client(struct i2c_client *client) | |||
214 | int err; | 225 | int err; |
215 | 226 | ||
216 | hwmon_device_unregister(data->class_dev); | 227 | hwmon_device_unregister(data->class_dev); |
228 | sysfs_remove_group(&client->dev.kobj, &smsc47b397_group); | ||
217 | 229 | ||
218 | if ((err = i2c_detach_client(client))) | 230 | if ((err = i2c_detach_client(client))) |
219 | return err; | 231 | return err; |
@@ -268,24 +280,19 @@ static int smsc47b397_detect(struct i2c_adapter *adapter) | |||
268 | if ((err = i2c_attach_client(new_client))) | 280 | if ((err = i2c_attach_client(new_client))) |
269 | goto error_free; | 281 | goto error_free; |
270 | 282 | ||
283 | if ((err = sysfs_create_group(&new_client->dev.kobj, &smsc47b397_group))) | ||
284 | goto error_detach; | ||
285 | |||
271 | data->class_dev = hwmon_device_register(&new_client->dev); | 286 | data->class_dev = hwmon_device_register(&new_client->dev); |
272 | if (IS_ERR(data->class_dev)) { | 287 | if (IS_ERR(data->class_dev)) { |
273 | err = PTR_ERR(data->class_dev); | 288 | err = PTR_ERR(data->class_dev); |
274 | goto error_detach; | 289 | goto error_remove; |
275 | } | 290 | } |
276 | 291 | ||
277 | device_create_file_temp(new_client, 1); | ||
278 | device_create_file_temp(new_client, 2); | ||
279 | device_create_file_temp(new_client, 3); | ||
280 | device_create_file_temp(new_client, 4); | ||
281 | |||
282 | device_create_file_fan(new_client, 1); | ||
283 | device_create_file_fan(new_client, 2); | ||
284 | device_create_file_fan(new_client, 3); | ||
285 | device_create_file_fan(new_client, 4); | ||
286 | |||
287 | return 0; | 292 | return 0; |
288 | 293 | ||
294 | error_remove: | ||
295 | sysfs_remove_group(&new_client->dev.kobj, &smsc47b397_group); | ||
289 | error_detach: | 296 | error_detach: |
290 | i2c_detach_client(new_client); | 297 | i2c_detach_client(new_client); |
291 | error_free: | 298 | error_free: |
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 6c81b843d831..47132fd26b1b 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/err.h> | 35 | #include <linux/err.h> |
36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
37 | #include <linux/mutex.h> | 37 | #include <linux/mutex.h> |
38 | #include <linux/sysfs.h> | ||
38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
39 | 40 | ||
40 | /* Address is autodetected, there is no default value */ | 41 | /* Address is autodetected, there is no default value */ |
@@ -347,6 +348,30 @@ fan_present(2); | |||
347 | 348 | ||
348 | static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); | 349 | static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); |
349 | 350 | ||
351 | /* Almost all sysfs files may or may not be created depending on the chip | ||
352 | setup so we create them individually. It is still convenient to define a | ||
353 | group to remove them all at once. */ | ||
354 | static struct attribute *smsc47m1_attributes[] = { | ||
355 | &dev_attr_fan1_input.attr, | ||
356 | &dev_attr_fan1_min.attr, | ||
357 | &dev_attr_fan1_div.attr, | ||
358 | &dev_attr_fan2_input.attr, | ||
359 | &dev_attr_fan2_min.attr, | ||
360 | &dev_attr_fan2_div.attr, | ||
361 | |||
362 | &dev_attr_pwm1.attr, | ||
363 | &dev_attr_pwm1_enable.attr, | ||
364 | &dev_attr_pwm2.attr, | ||
365 | &dev_attr_pwm2_enable.attr, | ||
366 | |||
367 | &dev_attr_alarms.attr, | ||
368 | NULL | ||
369 | }; | ||
370 | |||
371 | static const struct attribute_group smsc47m1_group = { | ||
372 | .attrs = smsc47m1_attributes, | ||
373 | }; | ||
374 | |||
350 | static int __init smsc47m1_find(unsigned short *addr) | 375 | static int __init smsc47m1_find(unsigned short *addr) |
351 | { | 376 | { |
352 | u8 val; | 377 | u8 val; |
@@ -429,7 +454,8 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) | |||
429 | pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05) | 454 | pwm2 = (smsc47m1_read_value(new_client, SMSC47M1_REG_PPIN(1)) & 0x05) |
430 | == 0x04; | 455 | == 0x04; |
431 | if (!(fan1 || fan2 || pwm1 || pwm2)) { | 456 | if (!(fan1 || fan2 || pwm1 || pwm2)) { |
432 | dev_warn(&new_client->dev, "Device is not configured, will not use\n"); | 457 | dev_warn(&adapter->dev, "Device at 0x%x is not configured, " |
458 | "will not use\n", new_client->addr); | ||
433 | err = -ENODEV; | 459 | err = -ENODEV; |
434 | goto error_free; | 460 | goto error_free; |
435 | } | 461 | } |
@@ -446,46 +472,62 @@ static int smsc47m1_detect(struct i2c_adapter *adapter) | |||
446 | smsc47m1_update_device(&new_client->dev, 1); | 472 | smsc47m1_update_device(&new_client->dev, 1); |
447 | 473 | ||
448 | /* Register sysfs hooks */ | 474 | /* Register sysfs hooks */ |
449 | data->class_dev = hwmon_device_register(&new_client->dev); | ||
450 | if (IS_ERR(data->class_dev)) { | ||
451 | err = PTR_ERR(data->class_dev); | ||
452 | goto error_detach; | ||
453 | } | ||
454 | |||
455 | if (fan1) { | 475 | if (fan1) { |
456 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | 476 | if ((err = device_create_file(&new_client->dev, |
457 | device_create_file(&new_client->dev, &dev_attr_fan1_min); | 477 | &dev_attr_fan1_input)) |
458 | device_create_file(&new_client->dev, &dev_attr_fan1_div); | 478 | || (err = device_create_file(&new_client->dev, |
479 | &dev_attr_fan1_min)) | ||
480 | || (err = device_create_file(&new_client->dev, | ||
481 | &dev_attr_fan1_div))) | ||
482 | goto error_remove_files; | ||
459 | } else | 483 | } else |
460 | dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, " | 484 | dev_dbg(&new_client->dev, "Fan 1 not enabled by hardware, " |
461 | "skipping\n"); | 485 | "skipping\n"); |
462 | 486 | ||
463 | if (fan2) { | 487 | if (fan2) { |
464 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | 488 | if ((err = device_create_file(&new_client->dev, |
465 | device_create_file(&new_client->dev, &dev_attr_fan2_min); | 489 | &dev_attr_fan2_input)) |
466 | device_create_file(&new_client->dev, &dev_attr_fan2_div); | 490 | || (err = device_create_file(&new_client->dev, |
491 | &dev_attr_fan2_min)) | ||
492 | || (err = device_create_file(&new_client->dev, | ||
493 | &dev_attr_fan2_div))) | ||
494 | goto error_remove_files; | ||
467 | } else | 495 | } else |
468 | dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, " | 496 | dev_dbg(&new_client->dev, "Fan 2 not enabled by hardware, " |
469 | "skipping\n"); | 497 | "skipping\n"); |
470 | 498 | ||
471 | if (pwm1) { | 499 | if (pwm1) { |
472 | device_create_file(&new_client->dev, &dev_attr_pwm1); | 500 | if ((err = device_create_file(&new_client->dev, |
473 | device_create_file(&new_client->dev, &dev_attr_pwm1_enable); | 501 | &dev_attr_pwm1)) |
502 | || (err = device_create_file(&new_client->dev, | ||
503 | &dev_attr_pwm1_enable))) | ||
504 | goto error_remove_files; | ||
474 | } else | 505 | } else |
475 | dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, " | 506 | dev_dbg(&new_client->dev, "PWM 1 not enabled by hardware, " |
476 | "skipping\n"); | 507 | "skipping\n"); |
477 | if (pwm2) { | 508 | if (pwm2) { |
478 | device_create_file(&new_client->dev, &dev_attr_pwm2); | 509 | if ((err = device_create_file(&new_client->dev, |
479 | device_create_file(&new_client->dev, &dev_attr_pwm2_enable); | 510 | &dev_attr_pwm2)) |
511 | || (err = device_create_file(&new_client->dev, | ||
512 | &dev_attr_pwm2_enable))) | ||
513 | goto error_remove_files; | ||
480 | } else | 514 | } else |
481 | dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, " | 515 | dev_dbg(&new_client->dev, "PWM 2 not enabled by hardware, " |
482 | "skipping\n"); | 516 | "skipping\n"); |
483 | 517 | ||
484 | device_create_file(&new_client->dev, &dev_attr_alarms); | 518 | if ((err = device_create_file(&new_client->dev, &dev_attr_alarms))) |
519 | goto error_remove_files; | ||
520 | |||
521 | data->class_dev = hwmon_device_register(&new_client->dev); | ||
522 | if (IS_ERR(data->class_dev)) { | ||
523 | err = PTR_ERR(data->class_dev); | ||
524 | goto error_remove_files; | ||
525 | } | ||
485 | 526 | ||
486 | return 0; | 527 | return 0; |
487 | 528 | ||
488 | error_detach: | 529 | error_remove_files: |
530 | sysfs_remove_group(&new_client->dev.kobj, &smsc47m1_group); | ||
489 | i2c_detach_client(new_client); | 531 | i2c_detach_client(new_client); |
490 | error_free: | 532 | error_free: |
491 | kfree(data); | 533 | kfree(data); |
@@ -500,6 +542,7 @@ static int smsc47m1_detach_client(struct i2c_client *client) | |||
500 | int err; | 542 | int err; |
501 | 543 | ||
502 | hwmon_device_unregister(data->class_dev); | 544 | hwmon_device_unregister(data->class_dev); |
545 | sysfs_remove_group(&client->dev.kobj, &smsc47m1_group); | ||
503 | 546 | ||
504 | if ((err = i2c_detach_client(client))) | 547 | if ((err = i2c_detach_client(client))) |
505 | return err; | 548 | return err; |
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index bdc4570acf9a..a6833f437395 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/hwmon-sysfs.h> | 30 | #include <linux/hwmon-sysfs.h> |
31 | #include <linux/hwmon-vid.h> | 31 | #include <linux/hwmon-vid.h> |
32 | #include <linux/err.h> | 32 | #include <linux/err.h> |
33 | #include <linux/sysfs.h> | ||
33 | 34 | ||
34 | /* Addresses to scan */ | 35 | /* Addresses to scan */ |
35 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; | 36 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; |
@@ -370,6 +371,75 @@ static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200); | |||
370 | static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400); | 371 | static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400); |
371 | static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800); | 372 | static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800); |
372 | 373 | ||
374 | static struct attribute *smsc47m192_attributes[] = { | ||
375 | &sensor_dev_attr_in0_input.dev_attr.attr, | ||
376 | &sensor_dev_attr_in0_min.dev_attr.attr, | ||
377 | &sensor_dev_attr_in0_max.dev_attr.attr, | ||
378 | &sensor_dev_attr_in0_alarm.dev_attr.attr, | ||
379 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
380 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
381 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
382 | &sensor_dev_attr_in1_alarm.dev_attr.attr, | ||
383 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
384 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
385 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
386 | &sensor_dev_attr_in2_alarm.dev_attr.attr, | ||
387 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
388 | &sensor_dev_attr_in3_min.dev_attr.attr, | ||
389 | &sensor_dev_attr_in3_max.dev_attr.attr, | ||
390 | &sensor_dev_attr_in3_alarm.dev_attr.attr, | ||
391 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
392 | &sensor_dev_attr_in5_min.dev_attr.attr, | ||
393 | &sensor_dev_attr_in5_max.dev_attr.attr, | ||
394 | &sensor_dev_attr_in5_alarm.dev_attr.attr, | ||
395 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
396 | &sensor_dev_attr_in6_min.dev_attr.attr, | ||
397 | &sensor_dev_attr_in6_max.dev_attr.attr, | ||
398 | &sensor_dev_attr_in6_alarm.dev_attr.attr, | ||
399 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
400 | &sensor_dev_attr_in7_min.dev_attr.attr, | ||
401 | &sensor_dev_attr_in7_max.dev_attr.attr, | ||
402 | &sensor_dev_attr_in7_alarm.dev_attr.attr, | ||
403 | |||
404 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
405 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
406 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
407 | &sensor_dev_attr_temp1_offset.dev_attr.attr, | ||
408 | &sensor_dev_attr_temp1_alarm.dev_attr.attr, | ||
409 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
410 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
411 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
412 | &sensor_dev_attr_temp2_offset.dev_attr.attr, | ||
413 | &sensor_dev_attr_temp2_alarm.dev_attr.attr, | ||
414 | &sensor_dev_attr_temp2_input_fault.dev_attr.attr, | ||
415 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
416 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
417 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
418 | &sensor_dev_attr_temp3_offset.dev_attr.attr, | ||
419 | &sensor_dev_attr_temp3_alarm.dev_attr.attr, | ||
420 | &sensor_dev_attr_temp3_input_fault.dev_attr.attr, | ||
421 | |||
422 | &dev_attr_cpu0_vid.attr, | ||
423 | &dev_attr_vrm.attr, | ||
424 | NULL | ||
425 | }; | ||
426 | |||
427 | static const struct attribute_group smsc47m192_group = { | ||
428 | .attrs = smsc47m192_attributes, | ||
429 | }; | ||
430 | |||
431 | static struct attribute *smsc47m192_attributes_in4[] = { | ||
432 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
433 | &sensor_dev_attr_in4_min.dev_attr.attr, | ||
434 | &sensor_dev_attr_in4_max.dev_attr.attr, | ||
435 | &sensor_dev_attr_in4_alarm.dev_attr.attr, | ||
436 | NULL | ||
437 | }; | ||
438 | |||
439 | static const struct attribute_group smsc47m192_group_in4 = { | ||
440 | .attrs = smsc47m192_attributes_in4, | ||
441 | }; | ||
442 | |||
373 | /* This function is called when: | 443 | /* This function is called when: |
374 | * smsc47m192_driver is inserted (when this module is loaded), for each | 444 | * smsc47m192_driver is inserted (when this module is loaded), for each |
375 | available adapter | 445 | available adapter |
@@ -471,80 +541,28 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address, | |||
471 | smsc47m192_init_client(client); | 541 | smsc47m192_init_client(client); |
472 | 542 | ||
473 | /* Register sysfs hooks */ | 543 | /* Register sysfs hooks */ |
474 | data->class_dev = hwmon_device_register(&client->dev); | 544 | if ((err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group))) |
475 | if (IS_ERR(data->class_dev)) { | ||
476 | err = PTR_ERR(data->class_dev); | ||
477 | goto exit_detach; | 545 | goto exit_detach; |
478 | } | ||
479 | |||
480 | device_create_file(&client->dev, &sensor_dev_attr_in0_input.dev_attr); | ||
481 | device_create_file(&client->dev, &sensor_dev_attr_in0_min.dev_attr); | ||
482 | device_create_file(&client->dev, &sensor_dev_attr_in0_max.dev_attr); | ||
483 | device_create_file(&client->dev, &sensor_dev_attr_in0_alarm.dev_attr); | ||
484 | device_create_file(&client->dev, &sensor_dev_attr_in1_input.dev_attr); | ||
485 | device_create_file(&client->dev, &sensor_dev_attr_in1_min.dev_attr); | ||
486 | device_create_file(&client->dev, &sensor_dev_attr_in1_max.dev_attr); | ||
487 | device_create_file(&client->dev, &sensor_dev_attr_in1_alarm.dev_attr); | ||
488 | device_create_file(&client->dev, &sensor_dev_attr_in2_input.dev_attr); | ||
489 | device_create_file(&client->dev, &sensor_dev_attr_in2_min.dev_attr); | ||
490 | device_create_file(&client->dev, &sensor_dev_attr_in2_max.dev_attr); | ||
491 | device_create_file(&client->dev, &sensor_dev_attr_in2_alarm.dev_attr); | ||
492 | device_create_file(&client->dev, &sensor_dev_attr_in3_input.dev_attr); | ||
493 | device_create_file(&client->dev, &sensor_dev_attr_in3_min.dev_attr); | ||
494 | device_create_file(&client->dev, &sensor_dev_attr_in3_max.dev_attr); | ||
495 | device_create_file(&client->dev, &sensor_dev_attr_in3_alarm.dev_attr); | ||
496 | 546 | ||
497 | /* Pin 110 is either in4 (+12V) or VID4 */ | 547 | /* Pin 110 is either in4 (+12V) or VID4 */ |
498 | config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); | 548 | config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); |
499 | if (!(config & 0x20)) { | 549 | if (!(config & 0x20)) { |
500 | device_create_file(&client->dev, | 550 | if ((err = sysfs_create_group(&client->dev.kobj, |
501 | &sensor_dev_attr_in4_input.dev_attr); | 551 | &smsc47m192_group_in4))) |
502 | device_create_file(&client->dev, | 552 | goto exit_remove_files; |
503 | &sensor_dev_attr_in4_min.dev_attr); | 553 | } |
504 | device_create_file(&client->dev, | 554 | |
505 | &sensor_dev_attr_in4_max.dev_attr); | 555 | data->class_dev = hwmon_device_register(&client->dev); |
506 | device_create_file(&client->dev, | 556 | if (IS_ERR(data->class_dev)) { |
507 | &sensor_dev_attr_in4_alarm.dev_attr); | 557 | err = PTR_ERR(data->class_dev); |
558 | goto exit_remove_files; | ||
508 | } | 559 | } |
509 | device_create_file(&client->dev, &sensor_dev_attr_in5_input.dev_attr); | ||
510 | device_create_file(&client->dev, &sensor_dev_attr_in5_min.dev_attr); | ||
511 | device_create_file(&client->dev, &sensor_dev_attr_in5_max.dev_attr); | ||
512 | device_create_file(&client->dev, &sensor_dev_attr_in5_alarm.dev_attr); | ||
513 | device_create_file(&client->dev, &sensor_dev_attr_in6_input.dev_attr); | ||
514 | device_create_file(&client->dev, &sensor_dev_attr_in6_min.dev_attr); | ||
515 | device_create_file(&client->dev, &sensor_dev_attr_in6_max.dev_attr); | ||
516 | device_create_file(&client->dev, &sensor_dev_attr_in6_alarm.dev_attr); | ||
517 | device_create_file(&client->dev, &sensor_dev_attr_in7_input.dev_attr); | ||
518 | device_create_file(&client->dev, &sensor_dev_attr_in7_min.dev_attr); | ||
519 | device_create_file(&client->dev, &sensor_dev_attr_in7_max.dev_attr); | ||
520 | device_create_file(&client->dev, &sensor_dev_attr_in7_alarm.dev_attr); | ||
521 | device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); | ||
522 | device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); | ||
523 | device_create_file(&client->dev, &sensor_dev_attr_temp1_min.dev_attr); | ||
524 | device_create_file(&client->dev, | ||
525 | &sensor_dev_attr_temp1_offset.dev_attr); | ||
526 | device_create_file(&client->dev, &sensor_dev_attr_temp1_alarm.dev_attr); | ||
527 | device_create_file(&client->dev, &sensor_dev_attr_temp2_input.dev_attr); | ||
528 | device_create_file(&client->dev, &sensor_dev_attr_temp2_max.dev_attr); | ||
529 | device_create_file(&client->dev, &sensor_dev_attr_temp2_min.dev_attr); | ||
530 | device_create_file(&client->dev, | ||
531 | &sensor_dev_attr_temp2_offset.dev_attr); | ||
532 | device_create_file(&client->dev, &sensor_dev_attr_temp2_alarm.dev_attr); | ||
533 | device_create_file(&client->dev, | ||
534 | &sensor_dev_attr_temp2_input_fault.dev_attr); | ||
535 | device_create_file(&client->dev, &sensor_dev_attr_temp3_input.dev_attr); | ||
536 | device_create_file(&client->dev, &sensor_dev_attr_temp3_max.dev_attr); | ||
537 | device_create_file(&client->dev, &sensor_dev_attr_temp3_min.dev_attr); | ||
538 | device_create_file(&client->dev, | ||
539 | &sensor_dev_attr_temp3_offset.dev_attr); | ||
540 | device_create_file(&client->dev, &sensor_dev_attr_temp3_alarm.dev_attr); | ||
541 | device_create_file(&client->dev, | ||
542 | &sensor_dev_attr_temp3_input_fault.dev_attr); | ||
543 | device_create_file(&client->dev, &dev_attr_cpu0_vid); | ||
544 | device_create_file(&client->dev, &dev_attr_vrm); | ||
545 | 560 | ||
546 | return 0; | 561 | return 0; |
547 | 562 | ||
563 | exit_remove_files: | ||
564 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); | ||
565 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); | ||
548 | exit_detach: | 566 | exit_detach: |
549 | i2c_detach_client(client); | 567 | i2c_detach_client(client); |
550 | exit_free: | 568 | exit_free: |
@@ -559,6 +577,8 @@ static int smsc47m192_detach_client(struct i2c_client *client) | |||
559 | int err; | 577 | int err; |
560 | 578 | ||
561 | hwmon_device_unregister(data->class_dev); | 579 | hwmon_device_unregister(data->class_dev); |
580 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); | ||
581 | sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); | ||
562 | 582 | ||
563 | if ((err = i2c_detach_client(client))) | 583 | if ((err = i2c_detach_client(client))) |
564 | return err; | 584 | return err; |
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index 95ae056e5a94..f8acada0537a 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/err.h> | 40 | #include <linux/err.h> |
41 | #include <linux/init.h> | 41 | #include <linux/init.h> |
42 | #include <linux/mutex.h> | 42 | #include <linux/mutex.h> |
43 | #include <linux/sysfs.h> | ||
43 | #include <asm/io.h> | 44 | #include <asm/io.h> |
44 | 45 | ||
45 | 46 | ||
@@ -570,6 +571,48 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch | |||
570 | } | 571 | } |
571 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 572 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
572 | 573 | ||
574 | static struct attribute *via686a_attributes[] = { | ||
575 | &dev_attr_in0_input.attr, | ||
576 | &dev_attr_in1_input.attr, | ||
577 | &dev_attr_in2_input.attr, | ||
578 | &dev_attr_in3_input.attr, | ||
579 | &dev_attr_in4_input.attr, | ||
580 | &dev_attr_in0_min.attr, | ||
581 | &dev_attr_in1_min.attr, | ||
582 | &dev_attr_in2_min.attr, | ||
583 | &dev_attr_in3_min.attr, | ||
584 | &dev_attr_in4_min.attr, | ||
585 | &dev_attr_in0_max.attr, | ||
586 | &dev_attr_in1_max.attr, | ||
587 | &dev_attr_in2_max.attr, | ||
588 | &dev_attr_in3_max.attr, | ||
589 | &dev_attr_in4_max.attr, | ||
590 | |||
591 | &dev_attr_temp1_input.attr, | ||
592 | &dev_attr_temp2_input.attr, | ||
593 | &dev_attr_temp3_input.attr, | ||
594 | &dev_attr_temp1_max.attr, | ||
595 | &dev_attr_temp2_max.attr, | ||
596 | &dev_attr_temp3_max.attr, | ||
597 | &dev_attr_temp1_max_hyst.attr, | ||
598 | &dev_attr_temp2_max_hyst.attr, | ||
599 | &dev_attr_temp3_max_hyst.attr, | ||
600 | |||
601 | &dev_attr_fan1_input.attr, | ||
602 | &dev_attr_fan2_input.attr, | ||
603 | &dev_attr_fan1_min.attr, | ||
604 | &dev_attr_fan2_min.attr, | ||
605 | &dev_attr_fan1_div.attr, | ||
606 | &dev_attr_fan2_div.attr, | ||
607 | |||
608 | &dev_attr_alarms.attr, | ||
609 | NULL | ||
610 | }; | ||
611 | |||
612 | static const struct attribute_group via686a_group = { | ||
613 | .attrs = via686a_attributes, | ||
614 | }; | ||
615 | |||
573 | /* The driver. I choose to use type i2c_driver, as at is identical to both | 616 | /* The driver. I choose to use type i2c_driver, as at is identical to both |
574 | smbus_driver and isa_driver, and clients could be of either kind */ | 617 | smbus_driver and isa_driver, and clients could be of either kind */ |
575 | static struct i2c_driver via686a_driver = { | 618 | static struct i2c_driver via686a_driver = { |
@@ -650,46 +693,19 @@ static int via686a_detect(struct i2c_adapter *adapter) | |||
650 | via686a_init_client(new_client); | 693 | via686a_init_client(new_client); |
651 | 694 | ||
652 | /* Register sysfs hooks */ | 695 | /* Register sysfs hooks */ |
696 | if ((err = sysfs_create_group(&new_client->dev.kobj, &via686a_group))) | ||
697 | goto exit_detach; | ||
698 | |||
653 | data->class_dev = hwmon_device_register(&new_client->dev); | 699 | data->class_dev = hwmon_device_register(&new_client->dev); |
654 | if (IS_ERR(data->class_dev)) { | 700 | if (IS_ERR(data->class_dev)) { |
655 | err = PTR_ERR(data->class_dev); | 701 | err = PTR_ERR(data->class_dev); |
656 | goto exit_detach; | 702 | goto exit_remove_files; |
657 | } | 703 | } |
658 | 704 | ||
659 | device_create_file(&new_client->dev, &dev_attr_in0_input); | ||
660 | device_create_file(&new_client->dev, &dev_attr_in1_input); | ||
661 | device_create_file(&new_client->dev, &dev_attr_in2_input); | ||
662 | device_create_file(&new_client->dev, &dev_attr_in3_input); | ||
663 | device_create_file(&new_client->dev, &dev_attr_in4_input); | ||
664 | device_create_file(&new_client->dev, &dev_attr_in0_min); | ||
665 | device_create_file(&new_client->dev, &dev_attr_in1_min); | ||
666 | device_create_file(&new_client->dev, &dev_attr_in2_min); | ||
667 | device_create_file(&new_client->dev, &dev_attr_in3_min); | ||
668 | device_create_file(&new_client->dev, &dev_attr_in4_min); | ||
669 | device_create_file(&new_client->dev, &dev_attr_in0_max); | ||
670 | device_create_file(&new_client->dev, &dev_attr_in1_max); | ||
671 | device_create_file(&new_client->dev, &dev_attr_in2_max); | ||
672 | device_create_file(&new_client->dev, &dev_attr_in3_max); | ||
673 | device_create_file(&new_client->dev, &dev_attr_in4_max); | ||
674 | device_create_file(&new_client->dev, &dev_attr_temp1_input); | ||
675 | device_create_file(&new_client->dev, &dev_attr_temp2_input); | ||
676 | device_create_file(&new_client->dev, &dev_attr_temp3_input); | ||
677 | device_create_file(&new_client->dev, &dev_attr_temp1_max); | ||
678 | device_create_file(&new_client->dev, &dev_attr_temp2_max); | ||
679 | device_create_file(&new_client->dev, &dev_attr_temp3_max); | ||
680 | device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst); | ||
681 | device_create_file(&new_client->dev, &dev_attr_temp2_max_hyst); | ||
682 | device_create_file(&new_client->dev, &dev_attr_temp3_max_hyst); | ||
683 | device_create_file(&new_client->dev, &dev_attr_fan1_input); | ||
684 | device_create_file(&new_client->dev, &dev_attr_fan2_input); | ||
685 | device_create_file(&new_client->dev, &dev_attr_fan1_min); | ||
686 | device_create_file(&new_client->dev, &dev_attr_fan2_min); | ||
687 | device_create_file(&new_client->dev, &dev_attr_fan1_div); | ||
688 | device_create_file(&new_client->dev, &dev_attr_fan2_div); | ||
689 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
690 | |||
691 | return 0; | 705 | return 0; |
692 | 706 | ||
707 | exit_remove_files: | ||
708 | sysfs_remove_group(&new_client->dev.kobj, &via686a_group); | ||
693 | exit_detach: | 709 | exit_detach: |
694 | i2c_detach_client(new_client); | 710 | i2c_detach_client(new_client); |
695 | exit_free: | 711 | exit_free: |
@@ -705,6 +721,7 @@ static int via686a_detach_client(struct i2c_client *client) | |||
705 | int err; | 721 | int err; |
706 | 722 | ||
707 | hwmon_device_unregister(data->class_dev); | 723 | hwmon_device_unregister(data->class_dev); |
724 | sysfs_remove_group(&client->dev.kobj, &via686a_group); | ||
708 | 725 | ||
709 | if ((err = i2c_detach_client(client))) | 726 | if ((err = i2c_detach_client(client))) |
710 | return err; | 727 | return err; |
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c new file mode 100644 index 000000000000..25cc56003d7a --- /dev/null +++ b/drivers/hwmon/vt1211.c | |||
@@ -0,0 +1,1355 @@ | |||
1 | /* | ||
2 | * vt1211.c - driver for the VIA VT1211 Super-I/O chip integrated hardware | ||
3 | * monitoring features | ||
4 | * Copyright (C) 2006 Juerg Haefliger <juergh@gmail.com> | ||
5 | * | ||
6 | * This driver is based on the driver for kernel 2.4 by Mark D. Studebaker | ||
7 | * and its port to kernel 2.6 by Lars Ekman. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/jiffies.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/hwmon.h> | ||
30 | #include <linux/hwmon-sysfs.h> | ||
31 | #include <linux/hwmon-vid.h> | ||
32 | #include <linux/err.h> | ||
33 | #include <linux/mutex.h> | ||
34 | #include <asm/io.h> | ||
35 | |||
36 | static int uch_config = -1; | ||
37 | module_param(uch_config, int, 0); | ||
38 | MODULE_PARM_DESC(uch_config, "Initialize the universal channel configuration"); | ||
39 | |||
40 | static int int_mode = -1; | ||
41 | module_param(int_mode, int, 0); | ||
42 | MODULE_PARM_DESC(int_mode, "Force the temperature interrupt mode"); | ||
43 | |||
44 | static struct platform_device *pdev; | ||
45 | |||
46 | #define DRVNAME "vt1211" | ||
47 | |||
48 | /* --------------------------------------------------------------------- | ||
49 | * Registers | ||
50 | * | ||
51 | * The sensors are defined as follows. | ||
52 | * | ||
53 | * Sensor Voltage Mode Temp Mode Notes (from the datasheet) | ||
54 | * -------- ------------ --------- -------------------------- | ||
55 | * Reading 1 temp1 Intel thermal diode | ||
56 | * Reading 3 temp2 Internal thermal diode | ||
57 | * UCH1/Reading2 in0 temp3 NTC type thermistor | ||
58 | * UCH2 in1 temp4 +2.5V | ||
59 | * UCH3 in2 temp5 VccP | ||
60 | * UCH4 in3 temp6 +5V | ||
61 | * UCH5 in4 temp7 +12V | ||
62 | * 3.3V in5 Internal VDD (+3.3V) | ||
63 | * | ||
64 | * --------------------------------------------------------------------- */ | ||
65 | |||
66 | /* Voltages (in) numbered 0-5 (ix) */ | ||
67 | #define VT1211_REG_IN(ix) (0x21 + (ix)) | ||
68 | #define VT1211_REG_IN_MIN(ix) ((ix) == 0 ? 0x3e : 0x2a + 2 * (ix)) | ||
69 | #define VT1211_REG_IN_MAX(ix) ((ix) == 0 ? 0x3d : 0x29 + 2 * (ix)) | ||
70 | |||
71 | /* Temperatures (temp) numbered 0-6 (ix) */ | ||
72 | static u8 regtemp[] = {0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25}; | ||
73 | static u8 regtempmax[] = {0x39, 0x1d, 0x3d, 0x2b, 0x2d, 0x2f, 0x31}; | ||
74 | static u8 regtemphyst[] = {0x3a, 0x1e, 0x3e, 0x2c, 0x2e, 0x30, 0x32}; | ||
75 | |||
76 | /* Fans numbered 0-1 (ix) */ | ||
77 | #define VT1211_REG_FAN(ix) (0x29 + (ix)) | ||
78 | #define VT1211_REG_FAN_MIN(ix) (0x3b + (ix)) | ||
79 | #define VT1211_REG_FAN_DIV 0x47 | ||
80 | |||
81 | /* PWMs numbered 0-1 (ix) */ | ||
82 | /* Auto points numbered 0-3 (ap) */ | ||
83 | #define VT1211_REG_PWM(ix) (0x60 + (ix)) | ||
84 | #define VT1211_REG_PWM_CLK 0x50 | ||
85 | #define VT1211_REG_PWM_CTL 0x51 | ||
86 | #define VT1211_REG_PWM_AUTO_TEMP(ap) (0x55 - (ap)) | ||
87 | #define VT1211_REG_PWM_AUTO_PWM(ix, ap) (0x58 + 2 * (ix) - (ap)) | ||
88 | |||
89 | /* Miscellaneous registers */ | ||
90 | #define VT1211_REG_CONFIG 0x40 | ||
91 | #define VT1211_REG_ALARM1 0x41 | ||
92 | #define VT1211_REG_ALARM2 0x42 | ||
93 | #define VT1211_REG_VID 0x45 | ||
94 | #define VT1211_REG_UCH_CONFIG 0x4a | ||
95 | #define VT1211_REG_TEMP1_CONFIG 0x4b | ||
96 | #define VT1211_REG_TEMP2_CONFIG 0x4c | ||
97 | |||
98 | /* In, temp & fan alarm bits */ | ||
99 | static const u8 bitalarmin[] = {11, 0, 1, 3, 8, 2, 9}; | ||
100 | static const u8 bitalarmtemp[] = {4, 15, 11, 0, 1, 3, 8}; | ||
101 | static const u8 bitalarmfan[] = {6, 7}; | ||
102 | |||
103 | /* --------------------------------------------------------------------- | ||
104 | * Data structures and manipulation thereof | ||
105 | * --------------------------------------------------------------------- */ | ||
106 | |||
107 | struct vt1211_data { | ||
108 | unsigned short addr; | ||
109 | const char *name; | ||
110 | struct class_device *class_dev; | ||
111 | |||
112 | struct mutex update_lock; | ||
113 | char valid; /* !=0 if following fields are valid */ | ||
114 | unsigned long last_updated; /* In jiffies */ | ||
115 | |||
116 | /* Register values */ | ||
117 | u8 in[6]; | ||
118 | u8 in_max[6]; | ||
119 | u8 in_min[6]; | ||
120 | u8 temp[7]; | ||
121 | u8 temp_max[7]; | ||
122 | u8 temp_hyst[7]; | ||
123 | u8 fan[2]; | ||
124 | u8 fan_min[2]; | ||
125 | u8 fan_div[2]; | ||
126 | u8 fan_ctl; | ||
127 | u8 pwm[2]; | ||
128 | u8 pwm_ctl[2]; | ||
129 | u8 pwm_clk; | ||
130 | u8 pwm_auto_temp[4]; | ||
131 | u8 pwm_auto_pwm[2][4]; | ||
132 | u8 vid; /* Read once at init time */ | ||
133 | u8 vrm; | ||
134 | u8 uch_config; /* Read once at init time */ | ||
135 | u16 alarms; | ||
136 | }; | ||
137 | |||
138 | /* ix = [0-5] */ | ||
139 | #define ISVOLT(ix, uch_config) ((ix) > 4 ? 1 : \ | ||
140 | !(((uch_config) >> ((ix) + 2)) & 1)) | ||
141 | |||
142 | /* ix = [0-6] */ | ||
143 | #define ISTEMP(ix, uch_config) ((ix) < 2 ? 1 : \ | ||
144 | ((uch_config) >> (ix)) & 1) | ||
145 | |||
146 | /* in5 (ix = 5) is special. It's the internal 3.3V so it's scaled in the | ||
147 | driver according to the VT1211 BIOS porting guide */ | ||
148 | #define IN_FROM_REG(ix, reg) ((reg) < 3 ? 0 : (ix) == 5 ? \ | ||
149 | (((reg) - 3) * 15882 + 479) / 958 : \ | ||
150 | (((reg) - 3) * 10000 + 479) / 958) | ||
151 | #define IN_TO_REG(ix, val) (SENSORS_LIMIT((ix) == 5 ? \ | ||
152 | ((val) * 958 + 7941) / 15882 + 3 : \ | ||
153 | ((val) * 958 + 5000) / 10000 + 3, 0, 255)) | ||
154 | |||
155 | /* temp1 (ix = 0) is an intel thermal diode which is scaled in user space. | ||
156 | temp2 (ix = 1) is the internal temp diode so it's scaled in the driver | ||
157 | according to some measurements that I took on an EPIA M10000. | ||
158 | temp3-7 are thermistor based so the driver returns the voltage measured at | ||
159 | the pin (range 0V - 2.2V). */ | ||
160 | #define TEMP_FROM_REG(ix, reg) ((ix) == 0 ? (reg) * 1000 : \ | ||
161 | (ix) == 1 ? (reg) < 51 ? 0 : \ | ||
162 | ((reg) - 51) * 1000 : \ | ||
163 | ((253 - (reg)) * 2200 + 105) / 210) | ||
164 | #define TEMP_TO_REG(ix, val) SENSORS_LIMIT( \ | ||
165 | ((ix) == 0 ? ((val) + 500) / 1000 : \ | ||
166 | (ix) == 1 ? ((val) + 500) / 1000 + 51 : \ | ||
167 | 253 - ((val) * 210 + 1100) / 2200), 0, 255) | ||
168 | |||
169 | #define DIV_FROM_REG(reg) (1 << (reg)) | ||
170 | |||
171 | #define RPM_FROM_REG(reg, div) (((reg) == 0) || ((reg) == 255) ? 0 : \ | ||
172 | 1310720 / (reg) / DIV_FROM_REG(div)) | ||
173 | #define RPM_TO_REG(val, div) ((val) == 0 ? 255 : \ | ||
174 | SENSORS_LIMIT((1310720 / (val) / \ | ||
175 | DIV_FROM_REG(div)), 1, 254)) | ||
176 | |||
177 | /* --------------------------------------------------------------------- | ||
178 | * Super-I/O constants and functions | ||
179 | * --------------------------------------------------------------------- */ | ||
180 | |||
181 | /* Configuration & data index port registers */ | ||
182 | #define SIO_REG_CIP 0x2e | ||
183 | #define SIO_REG_DIP 0x2f | ||
184 | |||
185 | /* Configuration registers */ | ||
186 | #define SIO_VT1211_LDN 0x07 /* logical device number */ | ||
187 | #define SIO_VT1211_DEVID 0x20 /* device ID */ | ||
188 | #define SIO_VT1211_DEVREV 0x21 /* device revision */ | ||
189 | #define SIO_VT1211_ACTIVE 0x30 /* HW monitor active */ | ||
190 | #define SIO_VT1211_BADDR 0x60 /* base I/O address */ | ||
191 | #define SIO_VT1211_ID 0x3c /* VT1211 device ID */ | ||
192 | |||
193 | /* VT1211 logical device numbers */ | ||
194 | #define SIO_VT1211_LDN_HWMON 0x0b /* HW monitor */ | ||
195 | |||
196 | static inline void superio_outb(int reg, int val) | ||
197 | { | ||
198 | outb(reg, SIO_REG_CIP); | ||
199 | outb(val, SIO_REG_DIP); | ||
200 | } | ||
201 | |||
202 | static inline int superio_inb(int reg) | ||
203 | { | ||
204 | outb(reg, SIO_REG_CIP); | ||
205 | return inb(SIO_REG_DIP); | ||
206 | } | ||
207 | |||
208 | static inline void superio_select(int ldn) | ||
209 | { | ||
210 | outb(SIO_VT1211_LDN, SIO_REG_CIP); | ||
211 | outb(ldn, SIO_REG_DIP); | ||
212 | } | ||
213 | |||
214 | static inline void superio_enter(void) | ||
215 | { | ||
216 | outb(0x87, SIO_REG_CIP); | ||
217 | outb(0x87, SIO_REG_CIP); | ||
218 | } | ||
219 | |||
220 | static inline void superio_exit(void) | ||
221 | { | ||
222 | outb(0xaa, SIO_REG_CIP); | ||
223 | } | ||
224 | |||
225 | /* --------------------------------------------------------------------- | ||
226 | * Device I/O access | ||
227 | * --------------------------------------------------------------------- */ | ||
228 | |||
229 | static inline u8 vt1211_read8(struct vt1211_data *data, u8 reg) | ||
230 | { | ||
231 | return inb(data->addr + reg); | ||
232 | } | ||
233 | |||
234 | static inline void vt1211_write8(struct vt1211_data *data, u8 reg, u8 val) | ||
235 | { | ||
236 | outb(val, data->addr + reg); | ||
237 | } | ||
238 | |||
239 | static struct vt1211_data *vt1211_update_device(struct device *dev) | ||
240 | { | ||
241 | struct vt1211_data *data = dev_get_drvdata(dev); | ||
242 | int ix, val; | ||
243 | |||
244 | mutex_lock(&data->update_lock); | ||
245 | |||
246 | /* registers cache is refreshed after 1 second */ | ||
247 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { | ||
248 | /* read VID */ | ||
249 | data->vid = vt1211_read8(data, VT1211_REG_VID) & 0x1f; | ||
250 | |||
251 | /* voltage (in) registers */ | ||
252 | for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { | ||
253 | if (ISVOLT(ix, data->uch_config)) { | ||
254 | data->in[ix] = vt1211_read8(data, | ||
255 | VT1211_REG_IN(ix)); | ||
256 | data->in_min[ix] = vt1211_read8(data, | ||
257 | VT1211_REG_IN_MIN(ix)); | ||
258 | data->in_max[ix] = vt1211_read8(data, | ||
259 | VT1211_REG_IN_MAX(ix)); | ||
260 | } | ||
261 | } | ||
262 | |||
263 | /* temp registers */ | ||
264 | for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) { | ||
265 | if (ISTEMP(ix, data->uch_config)) { | ||
266 | data->temp[ix] = vt1211_read8(data, | ||
267 | regtemp[ix]); | ||
268 | data->temp_max[ix] = vt1211_read8(data, | ||
269 | regtempmax[ix]); | ||
270 | data->temp_hyst[ix] = vt1211_read8(data, | ||
271 | regtemphyst[ix]); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | /* fan & pwm registers */ | ||
276 | for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) { | ||
277 | data->fan[ix] = vt1211_read8(data, | ||
278 | VT1211_REG_FAN(ix)); | ||
279 | data->fan_min[ix] = vt1211_read8(data, | ||
280 | VT1211_REG_FAN_MIN(ix)); | ||
281 | data->pwm[ix] = vt1211_read8(data, | ||
282 | VT1211_REG_PWM(ix)); | ||
283 | } | ||
284 | val = vt1211_read8(data, VT1211_REG_FAN_DIV); | ||
285 | data->fan_div[0] = (val >> 4) & 3; | ||
286 | data->fan_div[1] = (val >> 6) & 3; | ||
287 | data->fan_ctl = val & 0xf; | ||
288 | |||
289 | val = vt1211_read8(data, VT1211_REG_PWM_CTL); | ||
290 | data->pwm_ctl[0] = val & 0xf; | ||
291 | data->pwm_ctl[1] = (val >> 4) & 0xf; | ||
292 | |||
293 | data->pwm_clk = vt1211_read8(data, VT1211_REG_PWM_CLK); | ||
294 | |||
295 | /* pwm & temp auto point registers */ | ||
296 | data->pwm_auto_pwm[0][1] = vt1211_read8(data, | ||
297 | VT1211_REG_PWM_AUTO_PWM(0, 1)); | ||
298 | data->pwm_auto_pwm[0][2] = vt1211_read8(data, | ||
299 | VT1211_REG_PWM_AUTO_PWM(0, 2)); | ||
300 | data->pwm_auto_pwm[1][1] = vt1211_read8(data, | ||
301 | VT1211_REG_PWM_AUTO_PWM(1, 1)); | ||
302 | data->pwm_auto_pwm[1][2] = vt1211_read8(data, | ||
303 | VT1211_REG_PWM_AUTO_PWM(1, 2)); | ||
304 | for (ix = 0; ix < ARRAY_SIZE(data->pwm_auto_temp); ix++) { | ||
305 | data->pwm_auto_temp[ix] = vt1211_read8(data, | ||
306 | VT1211_REG_PWM_AUTO_TEMP(ix)); | ||
307 | } | ||
308 | |||
309 | /* alarm registers */ | ||
310 | data->alarms = (vt1211_read8(data, VT1211_REG_ALARM2) << 8) | | ||
311 | vt1211_read8(data, VT1211_REG_ALARM1); | ||
312 | |||
313 | data->last_updated = jiffies; | ||
314 | data->valid = 1; | ||
315 | } | ||
316 | |||
317 | mutex_unlock(&data->update_lock); | ||
318 | |||
319 | return data; | ||
320 | } | ||
321 | |||
322 | /* --------------------------------------------------------------------- | ||
323 | * Voltage sysfs interfaces | ||
324 | * ix = [0-5] | ||
325 | * --------------------------------------------------------------------- */ | ||
326 | |||
327 | #define SHOW_IN_INPUT 0 | ||
328 | #define SHOW_SET_IN_MIN 1 | ||
329 | #define SHOW_SET_IN_MAX 2 | ||
330 | #define SHOW_IN_ALARM 3 | ||
331 | |||
332 | static ssize_t show_in(struct device *dev, struct device_attribute *attr, | ||
333 | char *buf) | ||
334 | { | ||
335 | struct vt1211_data *data = vt1211_update_device(dev); | ||
336 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
337 | to_sensor_dev_attr_2(attr); | ||
338 | int ix = sensor_attr_2->index; | ||
339 | int fn = sensor_attr_2->nr; | ||
340 | int res; | ||
341 | |||
342 | switch (fn) { | ||
343 | case SHOW_IN_INPUT: | ||
344 | res = IN_FROM_REG(ix, data->in[ix]); | ||
345 | break; | ||
346 | case SHOW_SET_IN_MIN: | ||
347 | res = IN_FROM_REG(ix, data->in_min[ix]); | ||
348 | break; | ||
349 | case SHOW_SET_IN_MAX: | ||
350 | res = IN_FROM_REG(ix, data->in_max[ix]); | ||
351 | break; | ||
352 | case SHOW_IN_ALARM: | ||
353 | res = (data->alarms >> bitalarmin[ix]) & 1; | ||
354 | break; | ||
355 | default: | ||
356 | res = 0; | ||
357 | dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); | ||
358 | } | ||
359 | |||
360 | return sprintf(buf, "%d\n", res); | ||
361 | } | ||
362 | |||
363 | static ssize_t set_in(struct device *dev, struct device_attribute *attr, | ||
364 | const char *buf, size_t count) | ||
365 | { | ||
366 | struct vt1211_data *data = dev_get_drvdata(dev); | ||
367 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
368 | to_sensor_dev_attr_2(attr); | ||
369 | int ix = sensor_attr_2->index; | ||
370 | int fn = sensor_attr_2->nr; | ||
371 | long val = simple_strtol(buf, NULL, 10); | ||
372 | |||
373 | mutex_lock(&data->update_lock); | ||
374 | switch (fn) { | ||
375 | case SHOW_SET_IN_MIN: | ||
376 | data->in_min[ix] = IN_TO_REG(ix, val); | ||
377 | vt1211_write8(data, VT1211_REG_IN_MIN(ix), data->in_min[ix]); | ||
378 | break; | ||
379 | case SHOW_SET_IN_MAX: | ||
380 | data->in_max[ix] = IN_TO_REG(ix, val); | ||
381 | vt1211_write8(data, VT1211_REG_IN_MAX(ix), data->in_max[ix]); | ||
382 | break; | ||
383 | default: | ||
384 | dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); | ||
385 | } | ||
386 | mutex_unlock(&data->update_lock); | ||
387 | |||
388 | return count; | ||
389 | } | ||
390 | |||
391 | /* --------------------------------------------------------------------- | ||
392 | * Temperature sysfs interfaces | ||
393 | * ix = [0-6] | ||
394 | * --------------------------------------------------------------------- */ | ||
395 | |||
396 | #define SHOW_TEMP_INPUT 0 | ||
397 | #define SHOW_SET_TEMP_MAX 1 | ||
398 | #define SHOW_SET_TEMP_MAX_HYST 2 | ||
399 | #define SHOW_TEMP_ALARM 3 | ||
400 | |||
401 | static ssize_t show_temp(struct device *dev, struct device_attribute *attr, | ||
402 | char *buf) | ||
403 | { | ||
404 | struct vt1211_data *data = vt1211_update_device(dev); | ||
405 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
406 | to_sensor_dev_attr_2(attr); | ||
407 | int ix = sensor_attr_2->index; | ||
408 | int fn = sensor_attr_2->nr; | ||
409 | int res; | ||
410 | |||
411 | switch (fn) { | ||
412 | case SHOW_TEMP_INPUT: | ||
413 | res = TEMP_FROM_REG(ix, data->temp[ix]); | ||
414 | break; | ||
415 | case SHOW_SET_TEMP_MAX: | ||
416 | res = TEMP_FROM_REG(ix, data->temp_max[ix]); | ||
417 | break; | ||
418 | case SHOW_SET_TEMP_MAX_HYST: | ||
419 | res = TEMP_FROM_REG(ix, data->temp_hyst[ix]); | ||
420 | break; | ||
421 | case SHOW_TEMP_ALARM: | ||
422 | res = (data->alarms >> bitalarmtemp[ix]) & 1; | ||
423 | break; | ||
424 | default: | ||
425 | res = 0; | ||
426 | dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); | ||
427 | } | ||
428 | |||
429 | return sprintf(buf, "%d\n", res); | ||
430 | } | ||
431 | |||
432 | static ssize_t set_temp(struct device *dev, struct device_attribute *attr, | ||
433 | const char *buf, size_t count) | ||
434 | { | ||
435 | struct vt1211_data *data = dev_get_drvdata(dev); | ||
436 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
437 | to_sensor_dev_attr_2(attr); | ||
438 | int ix = sensor_attr_2->index; | ||
439 | int fn = sensor_attr_2->nr; | ||
440 | long val = simple_strtol(buf, NULL, 10); | ||
441 | |||
442 | mutex_lock(&data->update_lock); | ||
443 | switch (fn) { | ||
444 | case SHOW_SET_TEMP_MAX: | ||
445 | data->temp_max[ix] = TEMP_TO_REG(ix, val); | ||
446 | vt1211_write8(data, regtempmax[ix], | ||
447 | data->temp_max[ix]); | ||
448 | break; | ||
449 | case SHOW_SET_TEMP_MAX_HYST: | ||
450 | data->temp_hyst[ix] = TEMP_TO_REG(ix, val); | ||
451 | vt1211_write8(data, regtemphyst[ix], | ||
452 | data->temp_hyst[ix]); | ||
453 | break; | ||
454 | default: | ||
455 | dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); | ||
456 | } | ||
457 | mutex_unlock(&data->update_lock); | ||
458 | |||
459 | return count; | ||
460 | } | ||
461 | |||
462 | /* --------------------------------------------------------------------- | ||
463 | * Fan sysfs interfaces | ||
464 | * ix = [0-1] | ||
465 | * --------------------------------------------------------------------- */ | ||
466 | |||
467 | #define SHOW_FAN_INPUT 0 | ||
468 | #define SHOW_SET_FAN_MIN 1 | ||
469 | #define SHOW_SET_FAN_DIV 2 | ||
470 | #define SHOW_FAN_ALARM 3 | ||
471 | |||
472 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, | ||
473 | char *buf) | ||
474 | { | ||
475 | struct vt1211_data *data = vt1211_update_device(dev); | ||
476 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
477 | to_sensor_dev_attr_2(attr); | ||
478 | int ix = sensor_attr_2->index; | ||
479 | int fn = sensor_attr_2->nr; | ||
480 | int res; | ||
481 | |||
482 | switch (fn) { | ||
483 | case SHOW_FAN_INPUT: | ||
484 | res = RPM_FROM_REG(data->fan[ix], data->fan_div[ix]); | ||
485 | break; | ||
486 | case SHOW_SET_FAN_MIN: | ||
487 | res = RPM_FROM_REG(data->fan_min[ix], data->fan_div[ix]); | ||
488 | break; | ||
489 | case SHOW_SET_FAN_DIV: | ||
490 | res = DIV_FROM_REG(data->fan_div[ix]); | ||
491 | break; | ||
492 | case SHOW_FAN_ALARM: | ||
493 | res = (data->alarms >> bitalarmfan[ix]) & 1; | ||
494 | break; | ||
495 | default: | ||
496 | res = 0; | ||
497 | dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); | ||
498 | } | ||
499 | |||
500 | return sprintf(buf, "%d\n", res); | ||
501 | } | ||
502 | |||
503 | static ssize_t set_fan(struct device *dev, struct device_attribute *attr, | ||
504 | const char *buf, size_t count) | ||
505 | { | ||
506 | struct vt1211_data *data = dev_get_drvdata(dev); | ||
507 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
508 | to_sensor_dev_attr_2(attr); | ||
509 | int ix = sensor_attr_2->index; | ||
510 | int fn = sensor_attr_2->nr; | ||
511 | long val = simple_strtol(buf, NULL, 10); | ||
512 | int reg; | ||
513 | |||
514 | mutex_lock(&data->update_lock); | ||
515 | |||
516 | /* sync the data cache */ | ||
517 | reg = vt1211_read8(data, VT1211_REG_FAN_DIV); | ||
518 | data->fan_div[0] = (reg >> 4) & 3; | ||
519 | data->fan_div[1] = (reg >> 6) & 3; | ||
520 | data->fan_ctl = reg & 0xf; | ||
521 | |||
522 | switch (fn) { | ||
523 | case SHOW_SET_FAN_MIN: | ||
524 | data->fan_min[ix] = RPM_TO_REG(val, data->fan_div[ix]); | ||
525 | vt1211_write8(data, VT1211_REG_FAN_MIN(ix), | ||
526 | data->fan_min[ix]); | ||
527 | break; | ||
528 | case SHOW_SET_FAN_DIV: | ||
529 | switch (val) { | ||
530 | case 1: data->fan_div[ix] = 0; break; | ||
531 | case 2: data->fan_div[ix] = 1; break; | ||
532 | case 4: data->fan_div[ix] = 2; break; | ||
533 | case 8: data->fan_div[ix] = 3; break; | ||
534 | default: | ||
535 | count = -EINVAL; | ||
536 | dev_warn(dev, "fan div value %ld not " | ||
537 | "supported. Choose one of 1, 2, " | ||
538 | "4, or 8.\n", val); | ||
539 | goto EXIT; | ||
540 | } | ||
541 | vt1211_write8(data, VT1211_REG_FAN_DIV, | ||
542 | ((data->fan_div[1] << 6) | | ||
543 | (data->fan_div[0] << 4) | | ||
544 | data->fan_ctl)); | ||
545 | break; | ||
546 | default: | ||
547 | dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); | ||
548 | } | ||
549 | |||
550 | EXIT: | ||
551 | mutex_unlock(&data->update_lock); | ||
552 | return count; | ||
553 | } | ||
554 | |||
555 | /* --------------------------------------------------------------------- | ||
556 | * PWM sysfs interfaces | ||
557 | * ix = [0-1] | ||
558 | * --------------------------------------------------------------------- */ | ||
559 | |||
560 | #define SHOW_PWM 0 | ||
561 | #define SHOW_SET_PWM_ENABLE 1 | ||
562 | #define SHOW_SET_PWM_FREQ 2 | ||
563 | #define SHOW_SET_PWM_AUTO_CHANNELS_TEMP 3 | ||
564 | |||
565 | static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | ||
566 | char *buf) | ||
567 | { | ||
568 | struct vt1211_data *data = vt1211_update_device(dev); | ||
569 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
570 | to_sensor_dev_attr_2(attr); | ||
571 | int ix = sensor_attr_2->index; | ||
572 | int fn = sensor_attr_2->nr; | ||
573 | int res; | ||
574 | |||
575 | switch (fn) { | ||
576 | case SHOW_PWM: | ||
577 | res = data->pwm[ix]; | ||
578 | break; | ||
579 | case SHOW_SET_PWM_ENABLE: | ||
580 | res = ((data->pwm_ctl[ix] >> 3) & 1) ? 2 : 0; | ||
581 | break; | ||
582 | case SHOW_SET_PWM_FREQ: | ||
583 | res = 90000 >> (data->pwm_clk & 7); | ||
584 | break; | ||
585 | case SHOW_SET_PWM_AUTO_CHANNELS_TEMP: | ||
586 | res = (data->pwm_ctl[ix] & 7) + 1; | ||
587 | break; | ||
588 | default: | ||
589 | res = 0; | ||
590 | dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); | ||
591 | } | ||
592 | |||
593 | return sprintf(buf, "%d\n", res); | ||
594 | } | ||
595 | |||
596 | static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | ||
597 | const char *buf, size_t count) | ||
598 | { | ||
599 | struct vt1211_data *data = dev_get_drvdata(dev); | ||
600 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
601 | to_sensor_dev_attr_2(attr); | ||
602 | int ix = sensor_attr_2->index; | ||
603 | int fn = sensor_attr_2->nr; | ||
604 | long val = simple_strtol(buf, NULL, 10); | ||
605 | int tmp, reg; | ||
606 | |||
607 | mutex_lock(&data->update_lock); | ||
608 | |||
609 | switch (fn) { | ||
610 | case SHOW_SET_PWM_ENABLE: | ||
611 | /* sync the data cache */ | ||
612 | reg = vt1211_read8(data, VT1211_REG_FAN_DIV); | ||
613 | data->fan_div[0] = (reg >> 4) & 3; | ||
614 | data->fan_div[1] = (reg >> 6) & 3; | ||
615 | data->fan_ctl = reg & 0xf; | ||
616 | reg = vt1211_read8(data, VT1211_REG_PWM_CTL); | ||
617 | data->pwm_ctl[0] = reg & 0xf; | ||
618 | data->pwm_ctl[1] = (reg >> 4) & 0xf; | ||
619 | switch (val) { | ||
620 | case 0: | ||
621 | data->pwm_ctl[ix] &= 7; | ||
622 | /* disable SmartGuardian if both PWM outputs are | ||
623 | * disabled */ | ||
624 | if ((data->pwm_ctl[ix ^ 1] & 1) == 0) { | ||
625 | data->fan_ctl &= 0xe; | ||
626 | } | ||
627 | break; | ||
628 | case 2: | ||
629 | data->pwm_ctl[ix] |= 8; | ||
630 | data->fan_ctl |= 1; | ||
631 | break; | ||
632 | default: | ||
633 | count = -EINVAL; | ||
634 | dev_warn(dev, "pwm mode %ld not supported. " | ||
635 | "Choose one of 0 or 2.\n", val); | ||
636 | goto EXIT; | ||
637 | } | ||
638 | vt1211_write8(data, VT1211_REG_PWM_CTL, | ||
639 | ((data->pwm_ctl[1] << 4) | | ||
640 | data->pwm_ctl[0])); | ||
641 | vt1211_write8(data, VT1211_REG_FAN_DIV, | ||
642 | ((data->fan_div[1] << 6) | | ||
643 | (data->fan_div[0] << 4) | | ||
644 | data->fan_ctl)); | ||
645 | break; | ||
646 | case SHOW_SET_PWM_FREQ: | ||
647 | val = 135000 / SENSORS_LIMIT(val, 135000 >> 7, 135000); | ||
648 | /* calculate tmp = log2(val) */ | ||
649 | tmp = 0; | ||
650 | for (val >>= 1; val > 0; val >>= 1) { | ||
651 | tmp++; | ||
652 | } | ||
653 | /* sync the data cache */ | ||
654 | reg = vt1211_read8(data, VT1211_REG_PWM_CLK); | ||
655 | data->pwm_clk = (reg & 0xf8) | tmp; | ||
656 | vt1211_write8(data, VT1211_REG_PWM_CLK, data->pwm_clk); | ||
657 | break; | ||
658 | case SHOW_SET_PWM_AUTO_CHANNELS_TEMP: | ||
659 | if ((val < 1) || (val > 7)) { | ||
660 | count = -EINVAL; | ||
661 | dev_warn(dev, "temp channel %ld not supported. " | ||
662 | "Choose a value between 1 and 7.\n", val); | ||
663 | goto EXIT; | ||
664 | } | ||
665 | if (!ISTEMP(val - 1, data->uch_config)) { | ||
666 | count = -EINVAL; | ||
667 | dev_warn(dev, "temp channel %ld is not available.\n", | ||
668 | val); | ||
669 | goto EXIT; | ||
670 | } | ||
671 | /* sync the data cache */ | ||
672 | reg = vt1211_read8(data, VT1211_REG_PWM_CTL); | ||
673 | data->pwm_ctl[0] = reg & 0xf; | ||
674 | data->pwm_ctl[1] = (reg >> 4) & 0xf; | ||
675 | data->pwm_ctl[ix] = (data->pwm_ctl[ix] & 8) | (val - 1); | ||
676 | vt1211_write8(data, VT1211_REG_PWM_CTL, | ||
677 | ((data->pwm_ctl[1] << 4) | data->pwm_ctl[0])); | ||
678 | break; | ||
679 | default: | ||
680 | dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); | ||
681 | } | ||
682 | |||
683 | EXIT: | ||
684 | mutex_unlock(&data->update_lock); | ||
685 | return count; | ||
686 | } | ||
687 | |||
688 | /* --------------------------------------------------------------------- | ||
689 | * PWM auto point definitions | ||
690 | * ix = [0-1] | ||
691 | * ap = [0-3] | ||
692 | * --------------------------------------------------------------------- */ | ||
693 | |||
694 | /* | ||
695 | * pwm[ix+1]_auto_point[ap+1]_temp mapping table: | ||
696 | * Note that there is only a single set of temp auto points that controls both | ||
697 | * PWM controllers. We still create 2 sets of sysfs files to make it look | ||
698 | * more consistent even though they map to the same registers. | ||
699 | * | ||
700 | * ix ap : description | ||
701 | * ------------------- | ||
702 | * 0 0 : pwm1/2 off temperature (pwm_auto_temp[0]) | ||
703 | * 0 1 : pwm1/2 low speed temperature (pwm_auto_temp[1]) | ||
704 | * 0 2 : pwm1/2 high speed temperature (pwm_auto_temp[2]) | ||
705 | * 0 3 : pwm1/2 full speed temperature (pwm_auto_temp[3]) | ||
706 | * 1 0 : pwm1/2 off temperature (pwm_auto_temp[0]) | ||
707 | * 1 1 : pwm1/2 low speed temperature (pwm_auto_temp[1]) | ||
708 | * 1 2 : pwm1/2 high speed temperature (pwm_auto_temp[2]) | ||
709 | * 1 3 : pwm1/2 full speed temperature (pwm_auto_temp[3]) | ||
710 | */ | ||
711 | |||
712 | static ssize_t show_pwm_auto_point_temp(struct device *dev, | ||
713 | struct device_attribute *attr, | ||
714 | char *buf) | ||
715 | { | ||
716 | struct vt1211_data *data = vt1211_update_device(dev); | ||
717 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
718 | to_sensor_dev_attr_2(attr); | ||
719 | int ix = sensor_attr_2->index; | ||
720 | int ap = sensor_attr_2->nr; | ||
721 | |||
722 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->pwm_ctl[ix] & 7, | ||
723 | data->pwm_auto_temp[ap])); | ||
724 | } | ||
725 | |||
726 | static ssize_t set_pwm_auto_point_temp(struct device *dev, | ||
727 | struct device_attribute *attr, | ||
728 | const char *buf, size_t count) | ||
729 | { | ||
730 | struct vt1211_data *data = dev_get_drvdata(dev); | ||
731 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
732 | to_sensor_dev_attr_2(attr); | ||
733 | int ix = sensor_attr_2->index; | ||
734 | int ap = sensor_attr_2->nr; | ||
735 | long val = simple_strtol(buf, NULL, 10); | ||
736 | int reg; | ||
737 | |||
738 | mutex_lock(&data->update_lock); | ||
739 | |||
740 | /* sync the data cache */ | ||
741 | reg = vt1211_read8(data, VT1211_REG_PWM_CTL); | ||
742 | data->pwm_ctl[0] = reg & 0xf; | ||
743 | data->pwm_ctl[1] = (reg >> 4) & 0xf; | ||
744 | |||
745 | data->pwm_auto_temp[ap] = TEMP_TO_REG(data->pwm_ctl[ix] & 7, val); | ||
746 | vt1211_write8(data, VT1211_REG_PWM_AUTO_TEMP(ap), | ||
747 | data->pwm_auto_temp[ap]); | ||
748 | mutex_unlock(&data->update_lock); | ||
749 | |||
750 | return count; | ||
751 | } | ||
752 | |||
753 | /* | ||
754 | * pwm[ix+1]_auto_point[ap+1]_pwm mapping table: | ||
755 | * Note that the PWM auto points 0 & 3 are hard-wired in the VT1211 and can't | ||
756 | * be changed. | ||
757 | * | ||
758 | * ix ap : description | ||
759 | * ------------------- | ||
760 | * 0 0 : pwm1 off (pwm_auto_pwm[0][0], hard-wired to 0) | ||
761 | * 0 1 : pwm1 low speed duty cycle (pwm_auto_pwm[0][1]) | ||
762 | * 0 2 : pwm1 high speed duty cycle (pwm_auto_pwm[0][2]) | ||
763 | * 0 3 : pwm1 full speed (pwm_auto_pwm[0][3], hard-wired to 255) | ||
764 | * 1 0 : pwm2 off (pwm_auto_pwm[1][0], hard-wired to 0) | ||
765 | * 1 1 : pwm2 low speed duty cycle (pwm_auto_pwm[1][1]) | ||
766 | * 1 2 : pwm2 high speed duty cycle (pwm_auto_pwm[1][2]) | ||
767 | * 1 3 : pwm2 full speed (pwm_auto_pwm[1][3], hard-wired to 255) | ||
768 | */ | ||
769 | |||
770 | static ssize_t show_pwm_auto_point_pwm(struct device *dev, | ||
771 | struct device_attribute *attr, | ||
772 | char *buf) | ||
773 | { | ||
774 | struct vt1211_data *data = vt1211_update_device(dev); | ||
775 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
776 | to_sensor_dev_attr_2(attr); | ||
777 | int ix = sensor_attr_2->index; | ||
778 | int ap = sensor_attr_2->nr; | ||
779 | |||
780 | return sprintf(buf, "%d\n", data->pwm_auto_pwm[ix][ap]); | ||
781 | } | ||
782 | |||
783 | static ssize_t set_pwm_auto_point_pwm(struct device *dev, | ||
784 | struct device_attribute *attr, | ||
785 | const char *buf, size_t count) | ||
786 | { | ||
787 | struct vt1211_data *data = dev_get_drvdata(dev); | ||
788 | struct sensor_device_attribute_2 *sensor_attr_2 = | ||
789 | to_sensor_dev_attr_2(attr); | ||
790 | int ix = sensor_attr_2->index; | ||
791 | int ap = sensor_attr_2->nr; | ||
792 | long val = simple_strtol(buf, NULL, 10); | ||
793 | |||
794 | if ((val < 0) || (val > 255)) { | ||
795 | dev_err(dev, "pwm value %ld is out of range. " | ||
796 | "Choose a value between 0 and 255." , val); | ||
797 | return -EINVAL; | ||
798 | } | ||
799 | |||
800 | mutex_lock(&data->update_lock); | ||
801 | data->pwm_auto_pwm[ix][ap] = val; | ||
802 | vt1211_write8(data, VT1211_REG_PWM_AUTO_PWM(ix, ap), | ||
803 | data->pwm_auto_pwm[ix][ap]); | ||
804 | mutex_unlock(&data->update_lock); | ||
805 | |||
806 | return count; | ||
807 | } | ||
808 | |||
809 | /* --------------------------------------------------------------------- | ||
810 | * Miscellaneous sysfs interfaces (VRM, VID, name, and (legacy) alarms) | ||
811 | * --------------------------------------------------------------------- */ | ||
812 | |||
813 | static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, | ||
814 | char *buf) | ||
815 | { | ||
816 | struct vt1211_data *data = dev_get_drvdata(dev); | ||
817 | |||
818 | return sprintf(buf, "%d\n", data->vrm); | ||
819 | } | ||
820 | |||
821 | static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, | ||
822 | const char *buf, size_t count) | ||
823 | { | ||
824 | struct vt1211_data *data = dev_get_drvdata(dev); | ||
825 | long val = simple_strtol(buf, NULL, 10); | ||
826 | |||
827 | data->vrm = val; | ||
828 | |||
829 | return count; | ||
830 | } | ||
831 | |||
832 | static ssize_t show_vid(struct device *dev, struct device_attribute *attr, | ||
833 | char *buf) | ||
834 | { | ||
835 | struct vt1211_data *data = dev_get_drvdata(dev); | ||
836 | |||
837 | return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); | ||
838 | } | ||
839 | |||
840 | static ssize_t show_name(struct device *dev, | ||
841 | struct device_attribute *attr, char *buf) | ||
842 | { | ||
843 | struct vt1211_data *data = dev_get_drvdata(dev); | ||
844 | |||
845 | return sprintf(buf, "%s\n", data->name); | ||
846 | } | ||
847 | |||
848 | static ssize_t show_alarms(struct device *dev, | ||
849 | struct device_attribute *attr, char *buf) | ||
850 | { | ||
851 | struct vt1211_data *data = vt1211_update_device(dev); | ||
852 | |||
853 | return sprintf(buf, "%d\n", data->alarms); | ||
854 | } | ||
855 | |||
856 | /* --------------------------------------------------------------------- | ||
857 | * Device attribute structs | ||
858 | * --------------------------------------------------------------------- */ | ||
859 | |||
860 | #define SENSOR_ATTR_IN_INPUT(ix) \ | ||
861 | SENSOR_ATTR_2(in##ix##_input, S_IRUGO, \ | ||
862 | show_in, NULL, SHOW_IN_INPUT, ix) | ||
863 | |||
864 | static struct sensor_device_attribute_2 vt1211_sysfs_in_input[] = { | ||
865 | SENSOR_ATTR_IN_INPUT(0), | ||
866 | SENSOR_ATTR_IN_INPUT(1), | ||
867 | SENSOR_ATTR_IN_INPUT(2), | ||
868 | SENSOR_ATTR_IN_INPUT(3), | ||
869 | SENSOR_ATTR_IN_INPUT(4), | ||
870 | SENSOR_ATTR_IN_INPUT(5), | ||
871 | }; | ||
872 | |||
873 | #define SENSOR_ATTR_IN_MIN(ix) \ | ||
874 | SENSOR_ATTR_2(in##ix##_min, S_IRUGO | S_IWUSR, \ | ||
875 | show_in, set_in, SHOW_SET_IN_MIN, ix) | ||
876 | |||
877 | static struct sensor_device_attribute_2 vt1211_sysfs_in_min[] = { | ||
878 | SENSOR_ATTR_IN_MIN(0), | ||
879 | SENSOR_ATTR_IN_MIN(1), | ||
880 | SENSOR_ATTR_IN_MIN(2), | ||
881 | SENSOR_ATTR_IN_MIN(3), | ||
882 | SENSOR_ATTR_IN_MIN(4), | ||
883 | SENSOR_ATTR_IN_MIN(5), | ||
884 | }; | ||
885 | |||
886 | #define SENSOR_ATTR_IN_MAX(ix) \ | ||
887 | SENSOR_ATTR_2(in##ix##_max, S_IRUGO | S_IWUSR, \ | ||
888 | show_in, set_in, SHOW_SET_IN_MAX, ix) | ||
889 | |||
890 | static struct sensor_device_attribute_2 vt1211_sysfs_in_max[] = { | ||
891 | SENSOR_ATTR_IN_MAX(0), | ||
892 | SENSOR_ATTR_IN_MAX(1), | ||
893 | SENSOR_ATTR_IN_MAX(2), | ||
894 | SENSOR_ATTR_IN_MAX(3), | ||
895 | SENSOR_ATTR_IN_MAX(4), | ||
896 | SENSOR_ATTR_IN_MAX(5), | ||
897 | }; | ||
898 | |||
899 | #define SENSOR_ATTR_IN_ALARM(ix) \ | ||
900 | SENSOR_ATTR_2(in##ix##_alarm, S_IRUGO, \ | ||
901 | show_in, NULL, SHOW_IN_ALARM, ix) | ||
902 | |||
903 | static struct sensor_device_attribute_2 vt1211_sysfs_in_alarm[] = { | ||
904 | SENSOR_ATTR_IN_ALARM(0), | ||
905 | SENSOR_ATTR_IN_ALARM(1), | ||
906 | SENSOR_ATTR_IN_ALARM(2), | ||
907 | SENSOR_ATTR_IN_ALARM(3), | ||
908 | SENSOR_ATTR_IN_ALARM(4), | ||
909 | SENSOR_ATTR_IN_ALARM(5), | ||
910 | }; | ||
911 | |||
912 | #define SENSOR_ATTR_TEMP_INPUT(ix) \ | ||
913 | SENSOR_ATTR_2(temp##ix##_input, S_IRUGO, \ | ||
914 | show_temp, NULL, SHOW_TEMP_INPUT, ix-1) | ||
915 | |||
916 | static struct sensor_device_attribute_2 vt1211_sysfs_temp_input[] = { | ||
917 | SENSOR_ATTR_TEMP_INPUT(1), | ||
918 | SENSOR_ATTR_TEMP_INPUT(2), | ||
919 | SENSOR_ATTR_TEMP_INPUT(3), | ||
920 | SENSOR_ATTR_TEMP_INPUT(4), | ||
921 | SENSOR_ATTR_TEMP_INPUT(5), | ||
922 | SENSOR_ATTR_TEMP_INPUT(6), | ||
923 | SENSOR_ATTR_TEMP_INPUT(7), | ||
924 | }; | ||
925 | |||
926 | #define SENSOR_ATTR_TEMP_MAX(ix) \ | ||
927 | SENSOR_ATTR_2(temp##ix##_max, S_IRUGO | S_IWUSR, \ | ||
928 | show_temp, set_temp, SHOW_SET_TEMP_MAX, ix-1) | ||
929 | |||
930 | static struct sensor_device_attribute_2 vt1211_sysfs_temp_max[] = { | ||
931 | SENSOR_ATTR_TEMP_MAX(1), | ||
932 | SENSOR_ATTR_TEMP_MAX(2), | ||
933 | SENSOR_ATTR_TEMP_MAX(3), | ||
934 | SENSOR_ATTR_TEMP_MAX(4), | ||
935 | SENSOR_ATTR_TEMP_MAX(5), | ||
936 | SENSOR_ATTR_TEMP_MAX(6), | ||
937 | SENSOR_ATTR_TEMP_MAX(7), | ||
938 | }; | ||
939 | |||
940 | #define SENSOR_ATTR_TEMP_MAX_HYST(ix) \ | ||
941 | SENSOR_ATTR_2(temp##ix##_max_hyst, S_IRUGO | S_IWUSR, \ | ||
942 | show_temp, set_temp, SHOW_SET_TEMP_MAX_HYST, ix-1) | ||
943 | |||
944 | static struct sensor_device_attribute_2 vt1211_sysfs_temp_max_hyst[] = { | ||
945 | SENSOR_ATTR_TEMP_MAX_HYST(1), | ||
946 | SENSOR_ATTR_TEMP_MAX_HYST(2), | ||
947 | SENSOR_ATTR_TEMP_MAX_HYST(3), | ||
948 | SENSOR_ATTR_TEMP_MAX_HYST(4), | ||
949 | SENSOR_ATTR_TEMP_MAX_HYST(5), | ||
950 | SENSOR_ATTR_TEMP_MAX_HYST(6), | ||
951 | SENSOR_ATTR_TEMP_MAX_HYST(7), | ||
952 | }; | ||
953 | |||
954 | #define SENSOR_ATTR_TEMP_ALARM(ix) \ | ||
955 | SENSOR_ATTR_2(temp##ix##_alarm, S_IRUGO, \ | ||
956 | show_temp, NULL, SHOW_TEMP_ALARM, ix-1) | ||
957 | |||
958 | static struct sensor_device_attribute_2 vt1211_sysfs_temp_alarm[] = { | ||
959 | SENSOR_ATTR_TEMP_ALARM(1), | ||
960 | SENSOR_ATTR_TEMP_ALARM(2), | ||
961 | SENSOR_ATTR_TEMP_ALARM(3), | ||
962 | SENSOR_ATTR_TEMP_ALARM(4), | ||
963 | SENSOR_ATTR_TEMP_ALARM(5), | ||
964 | SENSOR_ATTR_TEMP_ALARM(6), | ||
965 | SENSOR_ATTR_TEMP_ALARM(7), | ||
966 | }; | ||
967 | |||
968 | #define SENSOR_ATTR_FAN(ix) \ | ||
969 | SENSOR_ATTR_2(fan##ix##_input, S_IRUGO, \ | ||
970 | show_fan, NULL, SHOW_FAN_INPUT, ix-1), \ | ||
971 | SENSOR_ATTR_2(fan##ix##_min, S_IRUGO | S_IWUSR, \ | ||
972 | show_fan, set_fan, SHOW_SET_FAN_MIN, ix-1), \ | ||
973 | SENSOR_ATTR_2(fan##ix##_div, S_IRUGO | S_IWUSR, \ | ||
974 | show_fan, set_fan, SHOW_SET_FAN_DIV, ix-1), \ | ||
975 | SENSOR_ATTR_2(fan##ix##_alarm, S_IRUGO, \ | ||
976 | show_fan, NULL, SHOW_FAN_ALARM, ix-1) | ||
977 | |||
978 | #define SENSOR_ATTR_PWM(ix) \ | ||
979 | SENSOR_ATTR_2(pwm##ix, S_IRUGO, \ | ||
980 | show_pwm, NULL, SHOW_PWM, ix-1), \ | ||
981 | SENSOR_ATTR_2(pwm##ix##_enable, S_IRUGO | S_IWUSR, \ | ||
982 | show_pwm, set_pwm, SHOW_SET_PWM_ENABLE, ix-1), \ | ||
983 | SENSOR_ATTR_2(pwm##ix##_auto_channels_temp, S_IRUGO | S_IWUSR, \ | ||
984 | show_pwm, set_pwm, SHOW_SET_PWM_AUTO_CHANNELS_TEMP, ix-1) | ||
985 | |||
986 | #define SENSOR_ATTR_PWM_FREQ(ix) \ | ||
987 | SENSOR_ATTR_2(pwm##ix##_freq, S_IRUGO | S_IWUSR, \ | ||
988 | show_pwm, set_pwm, SHOW_SET_PWM_FREQ, ix-1) | ||
989 | |||
990 | #define SENSOR_ATTR_PWM_FREQ_RO(ix) \ | ||
991 | SENSOR_ATTR_2(pwm##ix##_freq, S_IRUGO, \ | ||
992 | show_pwm, NULL, SHOW_SET_PWM_FREQ, ix-1) | ||
993 | |||
994 | #define SENSOR_ATTR_PWM_AUTO_POINT_TEMP(ix, ap) \ | ||
995 | SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_temp, S_IRUGO | S_IWUSR, \ | ||
996 | show_pwm_auto_point_temp, set_pwm_auto_point_temp, \ | ||
997 | ap-1, ix-1) | ||
998 | |||
999 | #define SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(ix, ap) \ | ||
1000 | SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_temp, S_IRUGO, \ | ||
1001 | show_pwm_auto_point_temp, NULL, \ | ||
1002 | ap-1, ix-1) | ||
1003 | |||
1004 | #define SENSOR_ATTR_PWM_AUTO_POINT_PWM(ix, ap) \ | ||
1005 | SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_pwm, S_IRUGO | S_IWUSR, \ | ||
1006 | show_pwm_auto_point_pwm, set_pwm_auto_point_pwm, \ | ||
1007 | ap-1, ix-1) | ||
1008 | |||
1009 | #define SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(ix, ap) \ | ||
1010 | SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_pwm, S_IRUGO, \ | ||
1011 | show_pwm_auto_point_pwm, NULL, \ | ||
1012 | ap-1, ix-1) | ||
1013 | |||
1014 | static struct sensor_device_attribute_2 vt1211_sysfs_fan_pwm[] = { | ||
1015 | SENSOR_ATTR_FAN(1), | ||
1016 | SENSOR_ATTR_FAN(2), | ||
1017 | SENSOR_ATTR_PWM(1), | ||
1018 | SENSOR_ATTR_PWM(2), | ||
1019 | SENSOR_ATTR_PWM_FREQ(1), | ||
1020 | SENSOR_ATTR_PWM_FREQ_RO(2), | ||
1021 | SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 1), | ||
1022 | SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 2), | ||
1023 | SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 3), | ||
1024 | SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 4), | ||
1025 | SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 1), | ||
1026 | SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 2), | ||
1027 | SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 3), | ||
1028 | SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 4), | ||
1029 | SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(1, 1), | ||
1030 | SENSOR_ATTR_PWM_AUTO_POINT_PWM(1, 2), | ||
1031 | SENSOR_ATTR_PWM_AUTO_POINT_PWM(1, 3), | ||
1032 | SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(1, 4), | ||
1033 | SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(2, 1), | ||
1034 | SENSOR_ATTR_PWM_AUTO_POINT_PWM(2, 2), | ||
1035 | SENSOR_ATTR_PWM_AUTO_POINT_PWM(2, 3), | ||
1036 | SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(2, 4), | ||
1037 | }; | ||
1038 | |||
1039 | static struct device_attribute vt1211_sysfs_misc[] = { | ||
1040 | __ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm), | ||
1041 | __ATTR(cpu0_vid, S_IRUGO, show_vid, NULL), | ||
1042 | __ATTR(name, S_IRUGO, show_name, NULL), | ||
1043 | __ATTR(alarms, S_IRUGO, show_alarms, NULL), | ||
1044 | }; | ||
1045 | |||
1046 | /* --------------------------------------------------------------------- | ||
1047 | * Device registration and initialization | ||
1048 | * --------------------------------------------------------------------- */ | ||
1049 | |||
1050 | static void __devinit vt1211_init_device(struct vt1211_data *data) | ||
1051 | { | ||
1052 | /* set VRM */ | ||
1053 | data->vrm = vid_which_vrm(); | ||
1054 | |||
1055 | /* Read (and initialize) UCH config */ | ||
1056 | data->uch_config = vt1211_read8(data, VT1211_REG_UCH_CONFIG); | ||
1057 | if (uch_config > -1) { | ||
1058 | data->uch_config = (data->uch_config & 0x83) | | ||
1059 | (uch_config << 2); | ||
1060 | vt1211_write8(data, VT1211_REG_UCH_CONFIG, data->uch_config); | ||
1061 | } | ||
1062 | |||
1063 | /* Initialize the interrupt mode (if request at module load time). | ||
1064 | * The VT1211 implements 3 different modes for clearing interrupts: | ||
1065 | * 0: Clear INT when status register is read. Regenerate INT as long | ||
1066 | * as temp stays above hysteresis limit. | ||
1067 | * 1: Clear INT when status register is read. DON'T regenerate INT | ||
1068 | * until temp falls below hysteresis limit and exceeds hot limit | ||
1069 | * again. | ||
1070 | * 2: Clear INT when temp falls below max limit. | ||
1071 | * | ||
1072 | * The driver only allows to force mode 0 since that's the only one | ||
1073 | * that makes sense for 'sensors' */ | ||
1074 | if (int_mode == 0) { | ||
1075 | vt1211_write8(data, VT1211_REG_TEMP1_CONFIG, 0); | ||
1076 | vt1211_write8(data, VT1211_REG_TEMP2_CONFIG, 0); | ||
1077 | } | ||
1078 | |||
1079 | /* Fill in some hard wired values into our data struct */ | ||
1080 | data->pwm_auto_pwm[0][3] = 255; | ||
1081 | data->pwm_auto_pwm[1][3] = 255; | ||
1082 | } | ||
1083 | |||
1084 | static void vt1211_remove_sysfs(struct platform_device *pdev) | ||
1085 | { | ||
1086 | struct device *dev = &pdev->dev; | ||
1087 | int i; | ||
1088 | |||
1089 | for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_in_input); i++) { | ||
1090 | device_remove_file(dev, | ||
1091 | &vt1211_sysfs_in_input[i].dev_attr); | ||
1092 | device_remove_file(dev, | ||
1093 | &vt1211_sysfs_in_min[i].dev_attr); | ||
1094 | device_remove_file(dev, | ||
1095 | &vt1211_sysfs_in_max[i].dev_attr); | ||
1096 | device_remove_file(dev, | ||
1097 | &vt1211_sysfs_in_alarm[i].dev_attr); | ||
1098 | } | ||
1099 | for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_temp_input); i++) { | ||
1100 | device_remove_file(dev, | ||
1101 | &vt1211_sysfs_temp_input[i].dev_attr); | ||
1102 | device_remove_file(dev, | ||
1103 | &vt1211_sysfs_temp_max[i].dev_attr); | ||
1104 | device_remove_file(dev, | ||
1105 | &vt1211_sysfs_temp_max_hyst[i].dev_attr); | ||
1106 | device_remove_file(dev, | ||
1107 | &vt1211_sysfs_temp_alarm[i].dev_attr); | ||
1108 | } | ||
1109 | for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_fan_pwm); i++) { | ||
1110 | device_remove_file(dev, | ||
1111 | &vt1211_sysfs_fan_pwm[i].dev_attr); | ||
1112 | } | ||
1113 | for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) { | ||
1114 | device_remove_file(dev, &vt1211_sysfs_misc[i]); | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1118 | static int __devinit vt1211_probe(struct platform_device *pdev) | ||
1119 | { | ||
1120 | struct device *dev = &pdev->dev; | ||
1121 | struct vt1211_data *data; | ||
1122 | struct resource *res; | ||
1123 | int i, err; | ||
1124 | |||
1125 | if (!(data = kzalloc(sizeof(struct vt1211_data), GFP_KERNEL))) { | ||
1126 | err = -ENOMEM; | ||
1127 | dev_err(dev, "Out of memory\n"); | ||
1128 | goto EXIT; | ||
1129 | } | ||
1130 | |||
1131 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
1132 | data->addr = res->start; | ||
1133 | data->name = DRVNAME; | ||
1134 | mutex_init(&data->update_lock); | ||
1135 | |||
1136 | platform_set_drvdata(pdev, data); | ||
1137 | |||
1138 | /* Initialize the VT1211 chip */ | ||
1139 | vt1211_init_device(data); | ||
1140 | |||
1141 | /* Create sysfs interface files */ | ||
1142 | for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_in_input); i++) { | ||
1143 | if (ISVOLT(i, data->uch_config)) { | ||
1144 | if ((err = device_create_file(dev, | ||
1145 | &vt1211_sysfs_in_input[i].dev_attr)) || | ||
1146 | (err = device_create_file(dev, | ||
1147 | &vt1211_sysfs_in_min[i].dev_attr)) || | ||
1148 | (err = device_create_file(dev, | ||
1149 | &vt1211_sysfs_in_max[i].dev_attr)) || | ||
1150 | (err = device_create_file(dev, | ||
1151 | &vt1211_sysfs_in_alarm[i].dev_attr))) { | ||
1152 | goto EXIT_DEV_REMOVE; | ||
1153 | } | ||
1154 | } | ||
1155 | } | ||
1156 | for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_temp_input); i++) { | ||
1157 | if (ISTEMP(i, data->uch_config)) { | ||
1158 | if ((err = device_create_file(dev, | ||
1159 | &vt1211_sysfs_temp_input[i].dev_attr)) || | ||
1160 | (err = device_create_file(dev, | ||
1161 | &vt1211_sysfs_temp_max[i].dev_attr)) || | ||
1162 | (err = device_create_file(dev, | ||
1163 | &vt1211_sysfs_temp_max_hyst[i].dev_attr)) || | ||
1164 | (err = device_create_file(dev, | ||
1165 | &vt1211_sysfs_temp_alarm[i].dev_attr))) { | ||
1166 | goto EXIT_DEV_REMOVE; | ||
1167 | } | ||
1168 | } | ||
1169 | } | ||
1170 | for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_fan_pwm); i++) { | ||
1171 | err = device_create_file(dev, | ||
1172 | &vt1211_sysfs_fan_pwm[i].dev_attr); | ||
1173 | if (err) { | ||
1174 | goto EXIT_DEV_REMOVE; | ||
1175 | } | ||
1176 | } | ||
1177 | for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) { | ||
1178 | err = device_create_file(dev, | ||
1179 | &vt1211_sysfs_misc[i]); | ||
1180 | if (err) { | ||
1181 | goto EXIT_DEV_REMOVE; | ||
1182 | } | ||
1183 | } | ||
1184 | |||
1185 | /* Register device */ | ||
1186 | data->class_dev = hwmon_device_register(dev); | ||
1187 | if (IS_ERR(data->class_dev)) { | ||
1188 | err = PTR_ERR(data->class_dev); | ||
1189 | dev_err(dev, "Class registration failed (%d)\n", err); | ||
1190 | goto EXIT_DEV_REMOVE_SILENT; | ||
1191 | } | ||
1192 | |||
1193 | return 0; | ||
1194 | |||
1195 | EXIT_DEV_REMOVE: | ||
1196 | dev_err(dev, "Sysfs interface creation failed (%d)\n", err); | ||
1197 | EXIT_DEV_REMOVE_SILENT: | ||
1198 | vt1211_remove_sysfs(pdev); | ||
1199 | platform_set_drvdata(pdev, NULL); | ||
1200 | kfree(data); | ||
1201 | EXIT: | ||
1202 | return err; | ||
1203 | } | ||
1204 | |||
1205 | static int __devexit vt1211_remove(struct platform_device *pdev) | ||
1206 | { | ||
1207 | struct vt1211_data *data = platform_get_drvdata(pdev); | ||
1208 | |||
1209 | hwmon_device_unregister(data->class_dev); | ||
1210 | vt1211_remove_sysfs(pdev); | ||
1211 | platform_set_drvdata(pdev, NULL); | ||
1212 | kfree(data); | ||
1213 | |||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | static struct platform_driver vt1211_driver = { | ||
1218 | .driver = { | ||
1219 | .owner = THIS_MODULE, | ||
1220 | .name = DRVNAME, | ||
1221 | }, | ||
1222 | .probe = vt1211_probe, | ||
1223 | .remove = __devexit_p(vt1211_remove), | ||
1224 | }; | ||
1225 | |||
1226 | static int __init vt1211_device_add(unsigned short address) | ||
1227 | { | ||
1228 | struct resource res = { | ||
1229 | .start = address, | ||
1230 | .end = address + 0x7f, | ||
1231 | .flags = IORESOURCE_IO, | ||
1232 | }; | ||
1233 | int err; | ||
1234 | |||
1235 | pdev = platform_device_alloc(DRVNAME, address); | ||
1236 | if (!pdev) { | ||
1237 | err = -ENOMEM; | ||
1238 | printk(KERN_ERR DRVNAME ": Device allocation failed (%d)\n", | ||
1239 | err); | ||
1240 | goto EXIT; | ||
1241 | } | ||
1242 | |||
1243 | res.name = pdev->name; | ||
1244 | err = platform_device_add_resources(pdev, &res, 1); | ||
1245 | if (err) { | ||
1246 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | ||
1247 | "(%d)\n", err); | ||
1248 | goto EXIT_DEV_PUT; | ||
1249 | } | ||
1250 | |||
1251 | err = platform_device_add(pdev); | ||
1252 | if (err) { | ||
1253 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | ||
1254 | err); | ||
1255 | goto EXIT_DEV_PUT; | ||
1256 | } | ||
1257 | |||
1258 | return 0; | ||
1259 | |||
1260 | EXIT_DEV_PUT: | ||
1261 | platform_device_put(pdev); | ||
1262 | EXIT: | ||
1263 | return err; | ||
1264 | } | ||
1265 | |||
1266 | static int __init vt1211_find(unsigned short *address) | ||
1267 | { | ||
1268 | int err = -ENODEV; | ||
1269 | |||
1270 | superio_enter(); | ||
1271 | |||
1272 | if (superio_inb(SIO_VT1211_DEVID) != SIO_VT1211_ID) { | ||
1273 | goto EXIT; | ||
1274 | } | ||
1275 | |||
1276 | superio_select(SIO_VT1211_LDN_HWMON); | ||
1277 | |||
1278 | if ((superio_inb(SIO_VT1211_ACTIVE) & 1) == 0) { | ||
1279 | printk(KERN_WARNING DRVNAME ": HW monitor is disabled, " | ||
1280 | "skipping\n"); | ||
1281 | goto EXIT; | ||
1282 | } | ||
1283 | |||
1284 | *address = ((superio_inb(SIO_VT1211_BADDR) << 8) | | ||
1285 | (superio_inb(SIO_VT1211_BADDR + 1))) & 0xff00; | ||
1286 | if (*address == 0) { | ||
1287 | printk(KERN_WARNING DRVNAME ": Base address is not set, " | ||
1288 | "skipping\n"); | ||
1289 | goto EXIT; | ||
1290 | } | ||
1291 | |||
1292 | err = 0; | ||
1293 | printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, " | ||
1294 | "revision %u\n", *address, superio_inb(SIO_VT1211_DEVREV)); | ||
1295 | |||
1296 | EXIT: | ||
1297 | superio_exit(); | ||
1298 | return err; | ||
1299 | } | ||
1300 | |||
1301 | static int __init vt1211_init(void) | ||
1302 | { | ||
1303 | int err; | ||
1304 | unsigned short address = 0; | ||
1305 | |||
1306 | err = vt1211_find(&address); | ||
1307 | if (err) { | ||
1308 | goto EXIT; | ||
1309 | } | ||
1310 | |||
1311 | if ((uch_config < -1) || (uch_config > 31)) { | ||
1312 | err = -EINVAL; | ||
1313 | printk(KERN_WARNING DRVNAME ": Invalid UCH configuration %d. " | ||
1314 | "Choose a value between 0 and 31.\n", uch_config); | ||
1315 | goto EXIT; | ||
1316 | } | ||
1317 | |||
1318 | if ((int_mode < -1) || (int_mode > 0)) { | ||
1319 | err = -EINVAL; | ||
1320 | printk(KERN_WARNING DRVNAME ": Invalid interrupt mode %d. " | ||
1321 | "Only mode 0 is supported.\n", int_mode); | ||
1322 | goto EXIT; | ||
1323 | } | ||
1324 | |||
1325 | err = platform_driver_register(&vt1211_driver); | ||
1326 | if (err) { | ||
1327 | goto EXIT; | ||
1328 | } | ||
1329 | |||
1330 | /* Sets global pdev as a side effect */ | ||
1331 | err = vt1211_device_add(address); | ||
1332 | if (err) { | ||
1333 | goto EXIT_DRV_UNREGISTER; | ||
1334 | } | ||
1335 | |||
1336 | return 0; | ||
1337 | |||
1338 | EXIT_DRV_UNREGISTER: | ||
1339 | platform_driver_unregister(&vt1211_driver); | ||
1340 | EXIT: | ||
1341 | return err; | ||
1342 | } | ||
1343 | |||
1344 | static void __exit vt1211_exit(void) | ||
1345 | { | ||
1346 | platform_device_unregister(pdev); | ||
1347 | platform_driver_unregister(&vt1211_driver); | ||
1348 | } | ||
1349 | |||
1350 | MODULE_AUTHOR("Juerg Haefliger <juergh@gmail.com>"); | ||
1351 | MODULE_DESCRIPTION("VT1211 sensors"); | ||
1352 | MODULE_LICENSE("GPL"); | ||
1353 | |||
1354 | module_init(vt1211_init); | ||
1355 | module_exit(vt1211_exit); | ||
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 236ccf0e915d..93f93d4fb8ae 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c | |||
@@ -451,37 +451,6 @@ define_temperature_sysfs(4); | |||
451 | define_temperature_sysfs(5); | 451 | define_temperature_sysfs(5); |
452 | define_temperature_sysfs(6); | 452 | define_temperature_sysfs(6); |
453 | 453 | ||
454 | #define CFG_INFO_TEMP(id) { &sensor_dev_attr_temp##id##_input.dev_attr, \ | ||
455 | &sensor_dev_attr_temp##id##_max_hyst.dev_attr, \ | ||
456 | &sensor_dev_attr_temp##id##_max.dev_attr } | ||
457 | #define CFG_INFO_VOLT(id) { &sensor_dev_attr_in##id##_input.dev_attr, \ | ||
458 | &sensor_dev_attr_in##id##_min.dev_attr, \ | ||
459 | &sensor_dev_attr_in##id##_max.dev_attr } | ||
460 | |||
461 | struct str_device_attr_table { | ||
462 | struct device_attribute *input; | ||
463 | struct device_attribute *min; | ||
464 | struct device_attribute *max; | ||
465 | }; | ||
466 | |||
467 | static struct str_device_attr_table cfg_info_temp[] = { | ||
468 | { &dev_attr_temp1_input, &dev_attr_temp1_max_hyst, &dev_attr_temp1_max }, | ||
469 | CFG_INFO_TEMP(2), | ||
470 | CFG_INFO_TEMP(3), | ||
471 | CFG_INFO_TEMP(4), | ||
472 | CFG_INFO_TEMP(5), | ||
473 | CFG_INFO_TEMP(6) | ||
474 | }; | ||
475 | |||
476 | static struct str_device_attr_table cfg_info_volt[] = { | ||
477 | CFG_INFO_VOLT(0), | ||
478 | CFG_INFO_VOLT(1), | ||
479 | CFG_INFO_VOLT(2), | ||
480 | CFG_INFO_VOLT(3), | ||
481 | CFG_INFO_VOLT(4), | ||
482 | { &dev_attr_in5_input, &dev_attr_in5_min, &dev_attr_in5_max } | ||
483 | }; | ||
484 | |||
485 | /* Fans */ | 454 | /* Fans */ |
486 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, | 455 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, |
487 | char *buf) | 456 | char *buf) |
@@ -585,6 +554,107 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, | |||
585 | 554 | ||
586 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 555 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
587 | 556 | ||
557 | static struct attribute *vt8231_attributes_temps[6][4] = { | ||
558 | { | ||
559 | &dev_attr_temp1_input.attr, | ||
560 | &dev_attr_temp1_max_hyst.attr, | ||
561 | &dev_attr_temp1_max.attr, | ||
562 | NULL | ||
563 | }, { | ||
564 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
565 | &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, | ||
566 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
567 | NULL | ||
568 | }, { | ||
569 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
570 | &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, | ||
571 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
572 | NULL | ||
573 | }, { | ||
574 | &sensor_dev_attr_temp4_input.dev_attr.attr, | ||
575 | &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, | ||
576 | &sensor_dev_attr_temp4_max.dev_attr.attr, | ||
577 | NULL | ||
578 | }, { | ||
579 | &sensor_dev_attr_temp5_input.dev_attr.attr, | ||
580 | &sensor_dev_attr_temp5_max_hyst.dev_attr.attr, | ||
581 | &sensor_dev_attr_temp5_max.dev_attr.attr, | ||
582 | NULL | ||
583 | }, { | ||
584 | &sensor_dev_attr_temp6_input.dev_attr.attr, | ||
585 | &sensor_dev_attr_temp6_max_hyst.dev_attr.attr, | ||
586 | &sensor_dev_attr_temp6_max.dev_attr.attr, | ||
587 | NULL | ||
588 | } | ||
589 | }; | ||
590 | |||
591 | static const struct attribute_group vt8231_group_temps[6] = { | ||
592 | { .attrs = vt8231_attributes_temps[0] }, | ||
593 | { .attrs = vt8231_attributes_temps[1] }, | ||
594 | { .attrs = vt8231_attributes_temps[2] }, | ||
595 | { .attrs = vt8231_attributes_temps[3] }, | ||
596 | { .attrs = vt8231_attributes_temps[4] }, | ||
597 | { .attrs = vt8231_attributes_temps[5] }, | ||
598 | }; | ||
599 | |||
600 | static struct attribute *vt8231_attributes_volts[6][4] = { | ||
601 | { | ||
602 | &sensor_dev_attr_in0_input.dev_attr.attr, | ||
603 | &sensor_dev_attr_in0_min.dev_attr.attr, | ||
604 | &sensor_dev_attr_in0_max.dev_attr.attr, | ||
605 | NULL | ||
606 | }, { | ||
607 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
608 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
609 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
610 | NULL | ||
611 | }, { | ||
612 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
613 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
614 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
615 | NULL | ||
616 | }, { | ||
617 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
618 | &sensor_dev_attr_in3_min.dev_attr.attr, | ||
619 | &sensor_dev_attr_in3_max.dev_attr.attr, | ||
620 | NULL | ||
621 | }, { | ||
622 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
623 | &sensor_dev_attr_in4_min.dev_attr.attr, | ||
624 | &sensor_dev_attr_in4_max.dev_attr.attr, | ||
625 | NULL | ||
626 | }, { | ||
627 | &dev_attr_in5_input.attr, | ||
628 | &dev_attr_in5_min.attr, | ||
629 | &dev_attr_in5_max.attr, | ||
630 | NULL | ||
631 | } | ||
632 | }; | ||
633 | |||
634 | static const struct attribute_group vt8231_group_volts[6] = { | ||
635 | { .attrs = vt8231_attributes_volts[0] }, | ||
636 | { .attrs = vt8231_attributes_volts[1] }, | ||
637 | { .attrs = vt8231_attributes_volts[2] }, | ||
638 | { .attrs = vt8231_attributes_volts[3] }, | ||
639 | { .attrs = vt8231_attributes_volts[4] }, | ||
640 | { .attrs = vt8231_attributes_volts[5] }, | ||
641 | }; | ||
642 | |||
643 | static struct attribute *vt8231_attributes[] = { | ||
644 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
645 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
646 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
647 | &sensor_dev_attr_fan2_min.dev_attr.attr, | ||
648 | &sensor_dev_attr_fan1_div.dev_attr.attr, | ||
649 | &sensor_dev_attr_fan2_div.dev_attr.attr, | ||
650 | &dev_attr_alarms.attr, | ||
651 | NULL | ||
652 | }; | ||
653 | |||
654 | static const struct attribute_group vt8231_group = { | ||
655 | .attrs = vt8231_attributes, | ||
656 | }; | ||
657 | |||
588 | static struct i2c_driver vt8231_driver = { | 658 | static struct i2c_driver vt8231_driver = { |
589 | .driver = { | 659 | .driver = { |
590 | .owner = THIS_MODULE, | 660 | .owner = THIS_MODULE, |
@@ -671,43 +741,43 @@ int vt8231_detect(struct i2c_adapter *adapter) | |||
671 | vt8231_init_client(client); | 741 | vt8231_init_client(client); |
672 | 742 | ||
673 | /* Register sysfs hooks */ | 743 | /* Register sysfs hooks */ |
674 | data->class_dev = hwmon_device_register(&client->dev); | 744 | if ((err = sysfs_create_group(&client->dev.kobj, &vt8231_group))) |
675 | if (IS_ERR(data->class_dev)) { | ||
676 | err = PTR_ERR(data->class_dev); | ||
677 | goto exit_detach; | 745 | goto exit_detach; |
678 | } | ||
679 | 746 | ||
680 | /* Must update device information to find out the config field */ | 747 | /* Must update device information to find out the config field */ |
681 | data->uch_config = vt8231_read_value(client, VT8231_REG_UCH_CONFIG); | 748 | data->uch_config = vt8231_read_value(client, VT8231_REG_UCH_CONFIG); |
682 | 749 | ||
683 | for (i = 0; i < ARRAY_SIZE(cfg_info_temp); i++) { | 750 | for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) { |
684 | if (ISTEMP(i, data->uch_config)) { | 751 | if (ISTEMP(i, data->uch_config)) { |
685 | device_create_file(&client->dev, | 752 | if ((err = sysfs_create_group(&client->dev.kobj, |
686 | cfg_info_temp[i].input); | 753 | &vt8231_group_temps[i]))) |
687 | device_create_file(&client->dev, cfg_info_temp[i].max); | 754 | goto exit_remove_files; |
688 | device_create_file(&client->dev, cfg_info_temp[i].min); | ||
689 | } | 755 | } |
690 | } | 756 | } |
691 | 757 | ||
692 | for (i = 0; i < ARRAY_SIZE(cfg_info_volt); i++) { | 758 | for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) { |
693 | if (ISVOLT(i, data->uch_config)) { | 759 | if (ISVOLT(i, data->uch_config)) { |
694 | device_create_file(&client->dev, | 760 | if ((err = sysfs_create_group(&client->dev.kobj, |
695 | cfg_info_volt[i].input); | 761 | &vt8231_group_volts[i]))) |
696 | device_create_file(&client->dev, cfg_info_volt[i].max); | 762 | goto exit_remove_files; |
697 | device_create_file(&client->dev, cfg_info_volt[i].min); | ||
698 | } | 763 | } |
699 | } | 764 | } |
700 | 765 | ||
701 | device_create_file(&client->dev, &sensor_dev_attr_fan1_input.dev_attr); | 766 | data->class_dev = hwmon_device_register(&client->dev); |
702 | device_create_file(&client->dev, &sensor_dev_attr_fan2_input.dev_attr); | 767 | if (IS_ERR(data->class_dev)) { |
703 | device_create_file(&client->dev, &sensor_dev_attr_fan1_min.dev_attr); | 768 | err = PTR_ERR(data->class_dev); |
704 | device_create_file(&client->dev, &sensor_dev_attr_fan2_min.dev_attr); | 769 | goto exit_remove_files; |
705 | device_create_file(&client->dev, &sensor_dev_attr_fan1_div.dev_attr); | 770 | } |
706 | device_create_file(&client->dev, &sensor_dev_attr_fan2_div.dev_attr); | ||
707 | |||
708 | device_create_file(&client->dev, &dev_attr_alarms); | ||
709 | return 0; | 771 | return 0; |
710 | 772 | ||
773 | exit_remove_files: | ||
774 | for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) | ||
775 | sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]); | ||
776 | |||
777 | for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) | ||
778 | sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]); | ||
779 | |||
780 | sysfs_remove_group(&client->dev.kobj, &vt8231_group); | ||
711 | exit_detach: | 781 | exit_detach: |
712 | i2c_detach_client(client); | 782 | i2c_detach_client(client); |
713 | exit_free: | 783 | exit_free: |
@@ -720,10 +790,18 @@ exit_release: | |||
720 | static int vt8231_detach_client(struct i2c_client *client) | 790 | static int vt8231_detach_client(struct i2c_client *client) |
721 | { | 791 | { |
722 | struct vt8231_data *data = i2c_get_clientdata(client); | 792 | struct vt8231_data *data = i2c_get_clientdata(client); |
723 | int err; | 793 | int err, i; |
724 | 794 | ||
725 | hwmon_device_unregister(data->class_dev); | 795 | hwmon_device_unregister(data->class_dev); |
726 | 796 | ||
797 | for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) | ||
798 | sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]); | ||
799 | |||
800 | for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) | ||
801 | sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]); | ||
802 | |||
803 | sysfs_remove_group(&client->dev.kobj, &vt8231_group); | ||
804 | |||
727 | if ((err = i2c_detach_client(client))) { | 805 | if ((err = i2c_detach_client(client))) { |
728 | return err; | 806 | return err; |
729 | } | 807 | } |
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index b21d6b9d7eac..833faa275ffa 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c | |||
@@ -2,6 +2,9 @@ | |||
2 | w83627ehf - Driver for the hardware monitoring functionality of | 2 | w83627ehf - Driver for the hardware monitoring functionality of |
3 | the Winbond W83627EHF Super-I/O chip | 3 | the Winbond W83627EHF Super-I/O chip |
4 | Copyright (C) 2005 Jean Delvare <khali@linux-fr.org> | 4 | Copyright (C) 2005 Jean Delvare <khali@linux-fr.org> |
5 | Copyright (C) 2006 Yuan Mu (Winbond), | ||
6 | Rudolf Marek <r.marek@sh.cvut.cz> | ||
7 | David Hubbard <david.c.hubbard@gmail.com> | ||
5 | 8 | ||
6 | Shamelessly ripped from the w83627hf driver | 9 | Shamelessly ripped from the w83627hf driver |
7 | Copyright (C) 2003 Mark Studebaker | 10 | Copyright (C) 2003 Mark Studebaker |
@@ -29,8 +32,8 @@ | |||
29 | 32 | ||
30 | Supports the following chips: | 33 | Supports the following chips: |
31 | 34 | ||
32 | Chip #vin #fan #pwm #temp chip_id man_id | 35 | Chip #vin #fan #pwm #temp chip_id man_id |
33 | w83627ehf 10 5 - 3 0x88 0x5ca3 | 36 | w83627ehf 10 5 4 3 0x88,0xa1 0x5ca3 |
34 | */ | 37 | */ |
35 | 38 | ||
36 | #include <linux/module.h> | 39 | #include <linux/module.h> |
@@ -145,10 +148,44 @@ static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 }; | |||
145 | #define W83627EHF_REG_ALARM2 0x45A | 148 | #define W83627EHF_REG_ALARM2 0x45A |
146 | #define W83627EHF_REG_ALARM3 0x45B | 149 | #define W83627EHF_REG_ALARM3 0x45B |
147 | 150 | ||
151 | /* SmartFan registers */ | ||
152 | /* DC or PWM output fan configuration */ | ||
153 | static const u8 W83627EHF_REG_PWM_ENABLE[] = { | ||
154 | 0x04, /* SYS FAN0 output mode and PWM mode */ | ||
155 | 0x04, /* CPU FAN0 output mode and PWM mode */ | ||
156 | 0x12, /* AUX FAN mode */ | ||
157 | 0x62, /* CPU fan1 mode */ | ||
158 | }; | ||
159 | |||
160 | static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 }; | ||
161 | static const u8 W83627EHF_PWM_ENABLE_SHIFT[] = { 2, 4, 1, 4 }; | ||
162 | |||
163 | /* FAN Duty Cycle, be used to control */ | ||
164 | static const u8 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 }; | ||
165 | static const u8 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 }; | ||
166 | static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 }; | ||
167 | |||
168 | |||
169 | /* Advanced Fan control, some values are common for all fans */ | ||
170 | static const u8 W83627EHF_REG_FAN_MIN_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 }; | ||
171 | static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0C, 0x0D, 0x17, 0x66 }; | ||
172 | |||
148 | /* | 173 | /* |
149 | * Conversions | 174 | * Conversions |
150 | */ | 175 | */ |
151 | 176 | ||
177 | /* 1 is PWM mode, output in ms */ | ||
178 | static inline unsigned int step_time_from_reg(u8 reg, u8 mode) | ||
179 | { | ||
180 | return mode ? 100 * reg : 400 * reg; | ||
181 | } | ||
182 | |||
183 | static inline u8 step_time_to_reg(unsigned int msec, u8 mode) | ||
184 | { | ||
185 | return SENSORS_LIMIT((mode ? (msec + 50) / 100 : | ||
186 | (msec + 200) / 400), 1, 255); | ||
187 | } | ||
188 | |||
152 | static inline unsigned int | 189 | static inline unsigned int |
153 | fan_from_reg(u8 reg, unsigned int div) | 190 | fan_from_reg(u8 reg, unsigned int div) |
154 | { | 191 | { |
@@ -170,12 +207,12 @@ temp1_from_reg(s8 reg) | |||
170 | } | 207 | } |
171 | 208 | ||
172 | static inline s8 | 209 | static inline s8 |
173 | temp1_to_reg(int temp) | 210 | temp1_to_reg(int temp, int min, int max) |
174 | { | 211 | { |
175 | if (temp <= -128000) | 212 | if (temp <= min) |
176 | return -128; | 213 | return min / 1000; |
177 | if (temp >= 127000) | 214 | if (temp >= max) |
178 | return 127; | 215 | return max / 1000; |
179 | if (temp < 0) | 216 | if (temp < 0) |
180 | return (temp - 500) / 1000; | 217 | return (temp - 500) / 1000; |
181 | return (temp + 500) / 1000; | 218 | return (temp + 500) / 1000; |
@@ -223,6 +260,16 @@ struct w83627ehf_data { | |||
223 | s16 temp_max[2]; | 260 | s16 temp_max[2]; |
224 | s16 temp_max_hyst[2]; | 261 | s16 temp_max_hyst[2]; |
225 | u32 alarms; | 262 | u32 alarms; |
263 | |||
264 | u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */ | ||
265 | u8 pwm_enable[4]; /* 1->manual | ||
266 | 2->thermal cruise (also called SmartFan I) */ | ||
267 | u8 pwm[4]; | ||
268 | u8 target_temp[4]; | ||
269 | u8 tolerance[4]; | ||
270 | |||
271 | u8 fan_min_output[4]; /* minimum fan speed */ | ||
272 | u8 fan_stop_time[4]; | ||
226 | }; | 273 | }; |
227 | 274 | ||
228 | static inline int is_word_sized(u16 reg) | 275 | static inline int is_word_sized(u16 reg) |
@@ -349,6 +396,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | |||
349 | { | 396 | { |
350 | struct i2c_client *client = to_i2c_client(dev); | 397 | struct i2c_client *client = to_i2c_client(dev); |
351 | struct w83627ehf_data *data = i2c_get_clientdata(client); | 398 | struct w83627ehf_data *data = i2c_get_clientdata(client); |
399 | int pwmcfg = 0, tolerance = 0; /* shut up the compiler */ | ||
352 | int i; | 400 | int i; |
353 | 401 | ||
354 | mutex_lock(&data->update_lock); | 402 | mutex_lock(&data->update_lock); |
@@ -416,6 +464,34 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | |||
416 | } | 464 | } |
417 | } | 465 | } |
418 | 466 | ||
467 | for (i = 0; i < 4; i++) { | ||
468 | /* pwmcfg, tolarance mapped for i=0, i=1 to same reg */ | ||
469 | if (i != 1) { | ||
470 | pwmcfg = w83627ehf_read_value(client, | ||
471 | W83627EHF_REG_PWM_ENABLE[i]); | ||
472 | tolerance = w83627ehf_read_value(client, | ||
473 | W83627EHF_REG_TOLERANCE[i]); | ||
474 | } | ||
475 | data->pwm_mode[i] = | ||
476 | ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1) | ||
477 | ? 0 : 1; | ||
478 | data->pwm_enable[i] = | ||
479 | ((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i]) | ||
480 | & 3) + 1; | ||
481 | data->pwm[i] = w83627ehf_read_value(client, | ||
482 | W83627EHF_REG_PWM[i]); | ||
483 | data->fan_min_output[i] = w83627ehf_read_value(client, | ||
484 | W83627EHF_REG_FAN_MIN_OUTPUT[i]); | ||
485 | data->fan_stop_time[i] = w83627ehf_read_value(client, | ||
486 | W83627EHF_REG_FAN_STOP_TIME[i]); | ||
487 | data->target_temp[i] = | ||
488 | w83627ehf_read_value(client, | ||
489 | W83627EHF_REG_TARGET[i]) & | ||
490 | (data->pwm_mode[i] == 1 ? 0x7f : 0xff); | ||
491 | data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0)) | ||
492 | & 0x0f; | ||
493 | } | ||
494 | |||
419 | /* Measured temperatures and limits */ | 495 | /* Measured temperatures and limits */ |
420 | data->temp1 = w83627ehf_read_value(client, | 496 | data->temp1 = w83627ehf_read_value(client, |
421 | W83627EHF_REG_TEMP1); | 497 | W83627EHF_REG_TEMP1); |
@@ -546,14 +622,6 @@ static struct sensor_device_attribute sda_in_max[] = { | |||
546 | SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), | 622 | SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), |
547 | }; | 623 | }; |
548 | 624 | ||
549 | static void device_create_file_in(struct device *dev, int i) | ||
550 | { | ||
551 | device_create_file(dev, &sda_in_input[i].dev_attr); | ||
552 | device_create_file(dev, &sda_in_alarm[i].dev_attr); | ||
553 | device_create_file(dev, &sda_in_min[i].dev_attr); | ||
554 | device_create_file(dev, &sda_in_max[i].dev_attr); | ||
555 | } | ||
556 | |||
557 | #define show_fan_reg(reg) \ | 625 | #define show_fan_reg(reg) \ |
558 | static ssize_t \ | 626 | static ssize_t \ |
559 | show_##reg(struct device *dev, struct device_attribute *attr, \ | 627 | show_##reg(struct device *dev, struct device_attribute *attr, \ |
@@ -681,14 +749,6 @@ static struct sensor_device_attribute sda_fan_div[] = { | |||
681 | SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4), | 749 | SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4), |
682 | }; | 750 | }; |
683 | 751 | ||
684 | static void device_create_file_fan(struct device *dev, int i) | ||
685 | { | ||
686 | device_create_file(dev, &sda_fan_input[i].dev_attr); | ||
687 | device_create_file(dev, &sda_fan_alarm[i].dev_attr); | ||
688 | device_create_file(dev, &sda_fan_div[i].dev_attr); | ||
689 | device_create_file(dev, &sda_fan_min[i].dev_attr); | ||
690 | } | ||
691 | |||
692 | #define show_temp1_reg(reg) \ | 752 | #define show_temp1_reg(reg) \ |
693 | static ssize_t \ | 753 | static ssize_t \ |
694 | show_##reg(struct device *dev, struct device_attribute *attr, \ | 754 | show_##reg(struct device *dev, struct device_attribute *attr, \ |
@@ -711,7 +771,7 @@ store_temp1_##reg(struct device *dev, struct device_attribute *attr, \ | |||
711 | u32 val = simple_strtoul(buf, NULL, 10); \ | 771 | u32 val = simple_strtoul(buf, NULL, 10); \ |
712 | \ | 772 | \ |
713 | mutex_lock(&data->update_lock); \ | 773 | mutex_lock(&data->update_lock); \ |
714 | data->temp1_##reg = temp1_to_reg(val); \ | 774 | data->temp1_##reg = temp1_to_reg(val, -128000, 127000); \ |
715 | w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \ | 775 | w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \ |
716 | data->temp1_##reg); \ | 776 | data->temp1_##reg); \ |
717 | mutex_unlock(&data->update_lock); \ | 777 | mutex_unlock(&data->update_lock); \ |
@@ -777,10 +837,309 @@ static struct sensor_device_attribute sda_temp[] = { | |||
777 | SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), | 837 | SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), |
778 | }; | 838 | }; |
779 | 839 | ||
840 | #define show_pwm_reg(reg) \ | ||
841 | static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ | ||
842 | char *buf) \ | ||
843 | { \ | ||
844 | struct w83627ehf_data *data = w83627ehf_update_device(dev); \ | ||
845 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ | ||
846 | int nr = sensor_attr->index; \ | ||
847 | return sprintf(buf, "%d\n", data->reg[nr]); \ | ||
848 | } | ||
849 | |||
850 | show_pwm_reg(pwm_mode) | ||
851 | show_pwm_reg(pwm_enable) | ||
852 | show_pwm_reg(pwm) | ||
853 | |||
854 | static ssize_t | ||
855 | store_pwm_mode(struct device *dev, struct device_attribute *attr, | ||
856 | const char *buf, size_t count) | ||
857 | { | ||
858 | struct i2c_client *client = to_i2c_client(dev); | ||
859 | struct w83627ehf_data *data = i2c_get_clientdata(client); | ||
860 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
861 | int nr = sensor_attr->index; | ||
862 | u32 val = simple_strtoul(buf, NULL, 10); | ||
863 | u16 reg; | ||
864 | |||
865 | if (val > 1) | ||
866 | return -EINVAL; | ||
867 | mutex_lock(&data->update_lock); | ||
868 | reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]); | ||
869 | data->pwm_mode[nr] = val; | ||
870 | reg &= ~(1 << W83627EHF_PWM_MODE_SHIFT[nr]); | ||
871 | if (!val) | ||
872 | reg |= 1 << W83627EHF_PWM_MODE_SHIFT[nr]; | ||
873 | w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg); | ||
874 | mutex_unlock(&data->update_lock); | ||
875 | return count; | ||
876 | } | ||
877 | |||
878 | static ssize_t | ||
879 | store_pwm(struct device *dev, struct device_attribute *attr, | ||
880 | const char *buf, size_t count) | ||
881 | { | ||
882 | struct i2c_client *client = to_i2c_client(dev); | ||
883 | struct w83627ehf_data *data = i2c_get_clientdata(client); | ||
884 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
885 | int nr = sensor_attr->index; | ||
886 | u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255); | ||
887 | |||
888 | mutex_lock(&data->update_lock); | ||
889 | data->pwm[nr] = val; | ||
890 | w83627ehf_write_value(client, W83627EHF_REG_PWM[nr], val); | ||
891 | mutex_unlock(&data->update_lock); | ||
892 | return count; | ||
893 | } | ||
894 | |||
895 | static ssize_t | ||
896 | store_pwm_enable(struct device *dev, struct device_attribute *attr, | ||
897 | const char *buf, size_t count) | ||
898 | { | ||
899 | struct i2c_client *client = to_i2c_client(dev); | ||
900 | struct w83627ehf_data *data = i2c_get_clientdata(client); | ||
901 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
902 | int nr = sensor_attr->index; | ||
903 | u32 val = simple_strtoul(buf, NULL, 10); | ||
904 | u16 reg; | ||
905 | |||
906 | if (!val || (val > 2)) /* only modes 1 and 2 are supported */ | ||
907 | return -EINVAL; | ||
908 | mutex_lock(&data->update_lock); | ||
909 | reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]); | ||
910 | data->pwm_enable[nr] = val; | ||
911 | reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]); | ||
912 | reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr]; | ||
913 | w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg); | ||
914 | mutex_unlock(&data->update_lock); | ||
915 | return count; | ||
916 | } | ||
917 | |||
918 | |||
919 | #define show_tol_temp(reg) \ | ||
920 | static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ | ||
921 | char *buf) \ | ||
922 | { \ | ||
923 | struct w83627ehf_data *data = w83627ehf_update_device(dev); \ | ||
924 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ | ||
925 | int nr = sensor_attr->index; \ | ||
926 | return sprintf(buf, "%d\n", temp1_from_reg(data->reg[nr])); \ | ||
927 | } | ||
928 | |||
929 | show_tol_temp(tolerance) | ||
930 | show_tol_temp(target_temp) | ||
931 | |||
932 | static ssize_t | ||
933 | store_target_temp(struct device *dev, struct device_attribute *attr, | ||
934 | const char *buf, size_t count) | ||
935 | { | ||
936 | struct i2c_client *client = to_i2c_client(dev); | ||
937 | struct w83627ehf_data *data = i2c_get_clientdata(client); | ||
938 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
939 | int nr = sensor_attr->index; | ||
940 | u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 127000); | ||
941 | |||
942 | mutex_lock(&data->update_lock); | ||
943 | data->target_temp[nr] = val; | ||
944 | w83627ehf_write_value(client, W83627EHF_REG_TARGET[nr], val); | ||
945 | mutex_unlock(&data->update_lock); | ||
946 | return count; | ||
947 | } | ||
948 | |||
949 | static ssize_t | ||
950 | store_tolerance(struct device *dev, struct device_attribute *attr, | ||
951 | const char *buf, size_t count) | ||
952 | { | ||
953 | struct i2c_client *client = to_i2c_client(dev); | ||
954 | struct w83627ehf_data *data = i2c_get_clientdata(client); | ||
955 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
956 | int nr = sensor_attr->index; | ||
957 | u16 reg; | ||
958 | /* Limit the temp to 0C - 15C */ | ||
959 | u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 15000); | ||
960 | |||
961 | mutex_lock(&data->update_lock); | ||
962 | reg = w83627ehf_read_value(client, W83627EHF_REG_TOLERANCE[nr]); | ||
963 | data->tolerance[nr] = val; | ||
964 | if (nr == 1) | ||
965 | reg = (reg & 0x0f) | (val << 4); | ||
966 | else | ||
967 | reg = (reg & 0xf0) | val; | ||
968 | w83627ehf_write_value(client, W83627EHF_REG_TOLERANCE[nr], reg); | ||
969 | mutex_unlock(&data->update_lock); | ||
970 | return count; | ||
971 | } | ||
972 | |||
973 | static struct sensor_device_attribute sda_pwm[] = { | ||
974 | SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0), | ||
975 | SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), | ||
976 | SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), | ||
977 | SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3), | ||
978 | }; | ||
979 | |||
980 | static struct sensor_device_attribute sda_pwm_mode[] = { | ||
981 | SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode, | ||
982 | store_pwm_mode, 0), | ||
983 | SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode, | ||
984 | store_pwm_mode, 1), | ||
985 | SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode, | ||
986 | store_pwm_mode, 2), | ||
987 | SENSOR_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode, | ||
988 | store_pwm_mode, 3), | ||
989 | }; | ||
990 | |||
991 | static struct sensor_device_attribute sda_pwm_enable[] = { | ||
992 | SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable, | ||
993 | store_pwm_enable, 0), | ||
994 | SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable, | ||
995 | store_pwm_enable, 1), | ||
996 | SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable, | ||
997 | store_pwm_enable, 2), | ||
998 | SENSOR_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable, | ||
999 | store_pwm_enable, 3), | ||
1000 | }; | ||
1001 | |||
1002 | static struct sensor_device_attribute sda_target_temp[] = { | ||
1003 | SENSOR_ATTR(pwm1_target, S_IWUSR | S_IRUGO, show_target_temp, | ||
1004 | store_target_temp, 0), | ||
1005 | SENSOR_ATTR(pwm2_target, S_IWUSR | S_IRUGO, show_target_temp, | ||
1006 | store_target_temp, 1), | ||
1007 | SENSOR_ATTR(pwm3_target, S_IWUSR | S_IRUGO, show_target_temp, | ||
1008 | store_target_temp, 2), | ||
1009 | SENSOR_ATTR(pwm4_target, S_IWUSR | S_IRUGO, show_target_temp, | ||
1010 | store_target_temp, 3), | ||
1011 | }; | ||
1012 | |||
1013 | static struct sensor_device_attribute sda_tolerance[] = { | ||
1014 | SENSOR_ATTR(pwm1_tolerance, S_IWUSR | S_IRUGO, show_tolerance, | ||
1015 | store_tolerance, 0), | ||
1016 | SENSOR_ATTR(pwm2_tolerance, S_IWUSR | S_IRUGO, show_tolerance, | ||
1017 | store_tolerance, 1), | ||
1018 | SENSOR_ATTR(pwm3_tolerance, S_IWUSR | S_IRUGO, show_tolerance, | ||
1019 | store_tolerance, 2), | ||
1020 | SENSOR_ATTR(pwm4_tolerance, S_IWUSR | S_IRUGO, show_tolerance, | ||
1021 | store_tolerance, 3), | ||
1022 | }; | ||
1023 | |||
1024 | /* Smart Fan registers */ | ||
1025 | |||
1026 | #define fan_functions(reg, REG) \ | ||
1027 | static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ | ||
1028 | char *buf) \ | ||
1029 | { \ | ||
1030 | struct w83627ehf_data *data = w83627ehf_update_device(dev); \ | ||
1031 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ | ||
1032 | int nr = sensor_attr->index; \ | ||
1033 | return sprintf(buf, "%d\n", data->reg[nr]); \ | ||
1034 | }\ | ||
1035 | static ssize_t \ | ||
1036 | store_##reg(struct device *dev, struct device_attribute *attr, \ | ||
1037 | const char *buf, size_t count) \ | ||
1038 | {\ | ||
1039 | struct i2c_client *client = to_i2c_client(dev); \ | ||
1040 | struct w83627ehf_data *data = i2c_get_clientdata(client); \ | ||
1041 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ | ||
1042 | int nr = sensor_attr->index; \ | ||
1043 | u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \ | ||
1044 | mutex_lock(&data->update_lock); \ | ||
1045 | data->reg[nr] = val; \ | ||
1046 | w83627ehf_write_value(client, W83627EHF_REG_##REG[nr], val); \ | ||
1047 | mutex_unlock(&data->update_lock); \ | ||
1048 | return count; \ | ||
1049 | } | ||
1050 | |||
1051 | fan_functions(fan_min_output, FAN_MIN_OUTPUT) | ||
1052 | |||
1053 | #define fan_time_functions(reg, REG) \ | ||
1054 | static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ | ||
1055 | char *buf) \ | ||
1056 | { \ | ||
1057 | struct w83627ehf_data *data = w83627ehf_update_device(dev); \ | ||
1058 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ | ||
1059 | int nr = sensor_attr->index; \ | ||
1060 | return sprintf(buf, "%d\n", \ | ||
1061 | step_time_from_reg(data->reg[nr], data->pwm_mode[nr])); \ | ||
1062 | } \ | ||
1063 | \ | ||
1064 | static ssize_t \ | ||
1065 | store_##reg(struct device *dev, struct device_attribute *attr, \ | ||
1066 | const char *buf, size_t count) \ | ||
1067 | { \ | ||
1068 | struct i2c_client *client = to_i2c_client(dev); \ | ||
1069 | struct w83627ehf_data *data = i2c_get_clientdata(client); \ | ||
1070 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ | ||
1071 | int nr = sensor_attr->index; \ | ||
1072 | u8 val = step_time_to_reg(simple_strtoul(buf, NULL, 10), \ | ||
1073 | data->pwm_mode[nr]); \ | ||
1074 | mutex_lock(&data->update_lock); \ | ||
1075 | data->reg[nr] = val; \ | ||
1076 | w83627ehf_write_value(client, W83627EHF_REG_##REG[nr], val); \ | ||
1077 | mutex_unlock(&data->update_lock); \ | ||
1078 | return count; \ | ||
1079 | } \ | ||
1080 | |||
1081 | fan_time_functions(fan_stop_time, FAN_STOP_TIME) | ||
1082 | |||
1083 | |||
1084 | static struct sensor_device_attribute sda_sf3_arrays_fan4[] = { | ||
1085 | SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, | ||
1086 | store_fan_stop_time, 3), | ||
1087 | SENSOR_ATTR(pwm4_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, | ||
1088 | store_fan_min_output, 3), | ||
1089 | }; | ||
1090 | |||
1091 | static struct sensor_device_attribute sda_sf3_arrays[] = { | ||
1092 | SENSOR_ATTR(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, | ||
1093 | store_fan_stop_time, 0), | ||
1094 | SENSOR_ATTR(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, | ||
1095 | store_fan_stop_time, 1), | ||
1096 | SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, | ||
1097 | store_fan_stop_time, 2), | ||
1098 | SENSOR_ATTR(pwm1_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, | ||
1099 | store_fan_min_output, 0), | ||
1100 | SENSOR_ATTR(pwm2_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, | ||
1101 | store_fan_min_output, 1), | ||
1102 | SENSOR_ATTR(pwm3_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, | ||
1103 | store_fan_min_output, 2), | ||
1104 | }; | ||
1105 | |||
780 | /* | 1106 | /* |
781 | * Driver and client management | 1107 | * Driver and client management |
782 | */ | 1108 | */ |
783 | 1109 | ||
1110 | static void w83627ehf_device_remove_files(struct device *dev) | ||
1111 | { | ||
1112 | /* some entries in the following arrays may not have been used in | ||
1113 | * device_create_file(), but device_remove_file() will ignore them */ | ||
1114 | int i; | ||
1115 | |||
1116 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) | ||
1117 | device_remove_file(dev, &sda_sf3_arrays[i].dev_attr); | ||
1118 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) | ||
1119 | device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); | ||
1120 | for (i = 0; i < 10; i++) { | ||
1121 | device_remove_file(dev, &sda_in_input[i].dev_attr); | ||
1122 | device_remove_file(dev, &sda_in_alarm[i].dev_attr); | ||
1123 | device_remove_file(dev, &sda_in_min[i].dev_attr); | ||
1124 | device_remove_file(dev, &sda_in_max[i].dev_attr); | ||
1125 | } | ||
1126 | for (i = 0; i < 5; i++) { | ||
1127 | device_remove_file(dev, &sda_fan_input[i].dev_attr); | ||
1128 | device_remove_file(dev, &sda_fan_alarm[i].dev_attr); | ||
1129 | device_remove_file(dev, &sda_fan_div[i].dev_attr); | ||
1130 | device_remove_file(dev, &sda_fan_min[i].dev_attr); | ||
1131 | } | ||
1132 | for (i = 0; i < 4; i++) { | ||
1133 | device_remove_file(dev, &sda_pwm[i].dev_attr); | ||
1134 | device_remove_file(dev, &sda_pwm_mode[i].dev_attr); | ||
1135 | device_remove_file(dev, &sda_pwm_enable[i].dev_attr); | ||
1136 | device_remove_file(dev, &sda_target_temp[i].dev_attr); | ||
1137 | device_remove_file(dev, &sda_tolerance[i].dev_attr); | ||
1138 | } | ||
1139 | for (i = 0; i < ARRAY_SIZE(sda_temp); i++) | ||
1140 | device_remove_file(dev, &sda_temp[i].dev_attr); | ||
1141 | } | ||
1142 | |||
784 | static struct i2c_driver w83627ehf_driver; | 1143 | static struct i2c_driver w83627ehf_driver; |
785 | 1144 | ||
786 | static void w83627ehf_init_client(struct i2c_client *client) | 1145 | static void w83627ehf_init_client(struct i2c_client *client) |
@@ -810,6 +1169,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) | |||
810 | struct i2c_client *client; | 1169 | struct i2c_client *client; |
811 | struct w83627ehf_data *data; | 1170 | struct w83627ehf_data *data; |
812 | struct device *dev; | 1171 | struct device *dev; |
1172 | u8 fan4pin, fan5pin; | ||
813 | int i, err = 0; | 1173 | int i, err = 0; |
814 | 1174 | ||
815 | if (!request_region(address + REGION_OFFSET, REGION_LENGTH, | 1175 | if (!request_region(address + REGION_OFFSET, REGION_LENGTH, |
@@ -848,35 +1208,87 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) | |||
848 | data->fan_min[i] = w83627ehf_read_value(client, | 1208 | data->fan_min[i] = w83627ehf_read_value(client, |
849 | W83627EHF_REG_FAN_MIN[i]); | 1209 | W83627EHF_REG_FAN_MIN[i]); |
850 | 1210 | ||
1211 | /* fan4 and fan5 share some pins with the GPIO and serial flash */ | ||
1212 | |||
1213 | superio_enter(); | ||
1214 | fan5pin = superio_inb(0x24) & 0x2; | ||
1215 | fan4pin = superio_inb(0x29) & 0x6; | ||
1216 | superio_exit(); | ||
1217 | |||
851 | /* It looks like fan4 and fan5 pins can be alternatively used | 1218 | /* It looks like fan4 and fan5 pins can be alternatively used |
852 | as fan on/off switches */ | 1219 | as fan on/off switches */ |
1220 | |||
853 | data->has_fan = 0x07; /* fan1, fan2 and fan3 */ | 1221 | data->has_fan = 0x07; /* fan1, fan2 and fan3 */ |
854 | i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1); | 1222 | i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1); |
855 | if (i & (1 << 2)) | 1223 | if ((i & (1 << 2)) && (!fan4pin)) |
856 | data->has_fan |= (1 << 3); | 1224 | data->has_fan |= (1 << 3); |
857 | if (i & (1 << 0)) | 1225 | if ((i & (1 << 0)) && (!fan5pin)) |
858 | data->has_fan |= (1 << 4); | 1226 | data->has_fan |= (1 << 4); |
859 | 1227 | ||
860 | /* Register sysfs hooks */ | 1228 | /* Register sysfs hooks */ |
861 | data->class_dev = hwmon_device_register(dev); | 1229 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) |
862 | if (IS_ERR(data->class_dev)) { | 1230 | if ((err = device_create_file(dev, |
863 | err = PTR_ERR(data->class_dev); | 1231 | &sda_sf3_arrays[i].dev_attr))) |
864 | goto exit_detach; | 1232 | goto exit_remove; |
865 | } | 1233 | |
1234 | /* if fan4 is enabled create the sf3 files for it */ | ||
1235 | if (data->has_fan & (1 << 3)) | ||
1236 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) { | ||
1237 | if ((err = device_create_file(dev, | ||
1238 | &sda_sf3_arrays_fan4[i].dev_attr))) | ||
1239 | goto exit_remove; | ||
1240 | } | ||
866 | 1241 | ||
867 | for (i = 0; i < 10; i++) | 1242 | for (i = 0; i < 10; i++) |
868 | device_create_file_in(dev, i); | 1243 | if ((err = device_create_file(dev, &sda_in_input[i].dev_attr)) |
1244 | || (err = device_create_file(dev, | ||
1245 | &sda_in_alarm[i].dev_attr)) | ||
1246 | || (err = device_create_file(dev, | ||
1247 | &sda_in_min[i].dev_attr)) | ||
1248 | || (err = device_create_file(dev, | ||
1249 | &sda_in_max[i].dev_attr))) | ||
1250 | goto exit_remove; | ||
869 | 1251 | ||
870 | for (i = 0; i < 5; i++) { | 1252 | for (i = 0; i < 5; i++) { |
871 | if (data->has_fan & (1 << i)) | 1253 | if (data->has_fan & (1 << i)) { |
872 | device_create_file_fan(dev, i); | 1254 | if ((err = device_create_file(dev, |
1255 | &sda_fan_input[i].dev_attr)) | ||
1256 | || (err = device_create_file(dev, | ||
1257 | &sda_fan_alarm[i].dev_attr)) | ||
1258 | || (err = device_create_file(dev, | ||
1259 | &sda_fan_div[i].dev_attr)) | ||
1260 | || (err = device_create_file(dev, | ||
1261 | &sda_fan_min[i].dev_attr))) | ||
1262 | goto exit_remove; | ||
1263 | if (i < 4 && /* w83627ehf only has 4 pwm */ | ||
1264 | ((err = device_create_file(dev, | ||
1265 | &sda_pwm[i].dev_attr)) | ||
1266 | || (err = device_create_file(dev, | ||
1267 | &sda_pwm_mode[i].dev_attr)) | ||
1268 | || (err = device_create_file(dev, | ||
1269 | &sda_pwm_enable[i].dev_attr)) | ||
1270 | || (err = device_create_file(dev, | ||
1271 | &sda_target_temp[i].dev_attr)) | ||
1272 | || (err = device_create_file(dev, | ||
1273 | &sda_tolerance[i].dev_attr)))) | ||
1274 | goto exit_remove; | ||
1275 | } | ||
873 | } | 1276 | } |
1277 | |||
874 | for (i = 0; i < ARRAY_SIZE(sda_temp); i++) | 1278 | for (i = 0; i < ARRAY_SIZE(sda_temp); i++) |
875 | device_create_file(dev, &sda_temp[i].dev_attr); | 1279 | if ((err = device_create_file(dev, &sda_temp[i].dev_attr))) |
1280 | goto exit_remove; | ||
1281 | |||
1282 | data->class_dev = hwmon_device_register(dev); | ||
1283 | if (IS_ERR(data->class_dev)) { | ||
1284 | err = PTR_ERR(data->class_dev); | ||
1285 | goto exit_remove; | ||
1286 | } | ||
876 | 1287 | ||
877 | return 0; | 1288 | return 0; |
878 | 1289 | ||
879 | exit_detach: | 1290 | exit_remove: |
1291 | w83627ehf_device_remove_files(dev); | ||
880 | i2c_detach_client(client); | 1292 | i2c_detach_client(client); |
881 | exit_free: | 1293 | exit_free: |
882 | kfree(data); | 1294 | kfree(data); |
@@ -892,6 +1304,7 @@ static int w83627ehf_detach_client(struct i2c_client *client) | |||
892 | int err; | 1304 | int err; |
893 | 1305 | ||
894 | hwmon_device_unregister(data->class_dev); | 1306 | hwmon_device_unregister(data->class_dev); |
1307 | w83627ehf_device_remove_files(&client->dev); | ||
895 | 1308 | ||
896 | if ((err = i2c_detach_client(client))) | 1309 | if ((err = i2c_detach_client(client))) |
897 | return err; | 1310 | return err; |
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 30295028ea99..dfdc29c77123 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c | |||
@@ -512,13 +512,6 @@ static DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, | |||
512 | static DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, | 512 | static DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, |
513 | show_regs_in_max0, store_regs_in_max0); | 513 | show_regs_in_max0, store_regs_in_max0); |
514 | 514 | ||
515 | #define device_create_file_in(client, offset) \ | ||
516 | do { \ | ||
517 | device_create_file(&client->dev, &dev_attr_in##offset##_input); \ | ||
518 | device_create_file(&client->dev, &dev_attr_in##offset##_min); \ | ||
519 | device_create_file(&client->dev, &dev_attr_in##offset##_max); \ | ||
520 | } while (0) | ||
521 | |||
522 | #define show_fan_reg(reg) \ | 515 | #define show_fan_reg(reg) \ |
523 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ | 516 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ |
524 | { \ | 517 | { \ |
@@ -576,12 +569,6 @@ sysfs_fan_min_offset(2); | |||
576 | sysfs_fan_offset(3); | 569 | sysfs_fan_offset(3); |
577 | sysfs_fan_min_offset(3); | 570 | sysfs_fan_min_offset(3); |
578 | 571 | ||
579 | #define device_create_file_fan(client, offset) \ | ||
580 | do { \ | ||
581 | device_create_file(&client->dev, &dev_attr_fan##offset##_input); \ | ||
582 | device_create_file(&client->dev, &dev_attr_fan##offset##_min); \ | ||
583 | } while (0) | ||
584 | |||
585 | #define show_temp_reg(reg) \ | 572 | #define show_temp_reg(reg) \ |
586 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ | 573 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ |
587 | { \ | 574 | { \ |
@@ -656,13 +643,6 @@ sysfs_temp_offsets(1); | |||
656 | sysfs_temp_offsets(2); | 643 | sysfs_temp_offsets(2); |
657 | sysfs_temp_offsets(3); | 644 | sysfs_temp_offsets(3); |
658 | 645 | ||
659 | #define device_create_file_temp(client, offset) \ | ||
660 | do { \ | ||
661 | device_create_file(&client->dev, &dev_attr_temp##offset##_input); \ | ||
662 | device_create_file(&client->dev, &dev_attr_temp##offset##_max); \ | ||
663 | device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \ | ||
664 | } while (0) | ||
665 | |||
666 | static ssize_t | 646 | static ssize_t |
667 | show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) | 647 | show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) |
668 | { | 648 | { |
@@ -670,8 +650,6 @@ show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) | |||
670 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); | 650 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); |
671 | } | 651 | } |
672 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); | 652 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); |
673 | #define device_create_file_vid(client) \ | ||
674 | device_create_file(&client->dev, &dev_attr_cpu0_vid) | ||
675 | 653 | ||
676 | static ssize_t | 654 | static ssize_t |
677 | show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) | 655 | show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -692,8 +670,6 @@ store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf | |||
692 | return count; | 670 | return count; |
693 | } | 671 | } |
694 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); | 672 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); |
695 | #define device_create_file_vrm(client) \ | ||
696 | device_create_file(&client->dev, &dev_attr_vrm) | ||
697 | 673 | ||
698 | static ssize_t | 674 | static ssize_t |
699 | show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) | 675 | show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -702,8 +678,6 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) | |||
702 | return sprintf(buf, "%ld\n", (long) data->alarms); | 678 | return sprintf(buf, "%ld\n", (long) data->alarms); |
703 | } | 679 | } |
704 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); | 680 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); |
705 | #define device_create_file_alarms(client) \ | ||
706 | device_create_file(&client->dev, &dev_attr_alarms) | ||
707 | 681 | ||
708 | #define show_beep_reg(REG, reg) \ | 682 | #define show_beep_reg(REG, reg) \ |
709 | static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \ | 683 | static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \ |
@@ -766,12 +740,6 @@ static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, \ | |||
766 | sysfs_beep(ENABLE, enable); | 740 | sysfs_beep(ENABLE, enable); |
767 | sysfs_beep(MASK, mask); | 741 | sysfs_beep(MASK, mask); |
768 | 742 | ||
769 | #define device_create_file_beep(client) \ | ||
770 | do { \ | ||
771 | device_create_file(&client->dev, &dev_attr_beep_enable); \ | ||
772 | device_create_file(&client->dev, &dev_attr_beep_mask); \ | ||
773 | } while (0) | ||
774 | |||
775 | static ssize_t | 743 | static ssize_t |
776 | show_fan_div_reg(struct device *dev, char *buf, int nr) | 744 | show_fan_div_reg(struct device *dev, char *buf, int nr) |
777 | { | 745 | { |
@@ -837,11 +805,6 @@ sysfs_fan_div(1); | |||
837 | sysfs_fan_div(2); | 805 | sysfs_fan_div(2); |
838 | sysfs_fan_div(3); | 806 | sysfs_fan_div(3); |
839 | 807 | ||
840 | #define device_create_file_fan_div(client, offset) \ | ||
841 | do { \ | ||
842 | device_create_file(&client->dev, &dev_attr_fan##offset##_div); \ | ||
843 | } while (0) | ||
844 | |||
845 | static ssize_t | 808 | static ssize_t |
846 | show_pwm_reg(struct device *dev, char *buf, int nr) | 809 | show_pwm_reg(struct device *dev, char *buf, int nr) |
847 | { | 810 | { |
@@ -896,11 +859,6 @@ sysfs_pwm(1); | |||
896 | sysfs_pwm(2); | 859 | sysfs_pwm(2); |
897 | sysfs_pwm(3); | 860 | sysfs_pwm(3); |
898 | 861 | ||
899 | #define device_create_file_pwm(client, offset) \ | ||
900 | do { \ | ||
901 | device_create_file(&client->dev, &dev_attr_pwm##offset); \ | ||
902 | } while (0) | ||
903 | |||
904 | static ssize_t | 862 | static ssize_t |
905 | show_sensor_reg(struct device *dev, char *buf, int nr) | 863 | show_sensor_reg(struct device *dev, char *buf, int nr) |
906 | { | 864 | { |
@@ -972,12 +930,6 @@ sysfs_sensor(1); | |||
972 | sysfs_sensor(2); | 930 | sysfs_sensor(2); |
973 | sysfs_sensor(3); | 931 | sysfs_sensor(3); |
974 | 932 | ||
975 | #define device_create_file_sensor(client, offset) \ | ||
976 | do { \ | ||
977 | device_create_file(&client->dev, &dev_attr_temp##offset##_type); \ | ||
978 | } while (0) | ||
979 | |||
980 | |||
981 | static int __init w83627hf_find(int sioaddr, unsigned short *addr) | 933 | static int __init w83627hf_find(int sioaddr, unsigned short *addr) |
982 | { | 934 | { |
983 | u16 val; | 935 | u16 val; |
@@ -1009,6 +961,85 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr) | |||
1009 | return 0; | 961 | return 0; |
1010 | } | 962 | } |
1011 | 963 | ||
964 | static struct attribute *w83627hf_attributes[] = { | ||
965 | &dev_attr_in0_input.attr, | ||
966 | &dev_attr_in0_min.attr, | ||
967 | &dev_attr_in0_max.attr, | ||
968 | &dev_attr_in2_input.attr, | ||
969 | &dev_attr_in2_min.attr, | ||
970 | &dev_attr_in2_max.attr, | ||
971 | &dev_attr_in3_input.attr, | ||
972 | &dev_attr_in3_min.attr, | ||
973 | &dev_attr_in3_max.attr, | ||
974 | &dev_attr_in4_input.attr, | ||
975 | &dev_attr_in4_min.attr, | ||
976 | &dev_attr_in4_max.attr, | ||
977 | &dev_attr_in7_input.attr, | ||
978 | &dev_attr_in7_min.attr, | ||
979 | &dev_attr_in7_max.attr, | ||
980 | &dev_attr_in8_input.attr, | ||
981 | &dev_attr_in8_min.attr, | ||
982 | &dev_attr_in8_max.attr, | ||
983 | |||
984 | &dev_attr_fan1_input.attr, | ||
985 | &dev_attr_fan1_min.attr, | ||
986 | &dev_attr_fan1_div.attr, | ||
987 | &dev_attr_fan2_input.attr, | ||
988 | &dev_attr_fan2_min.attr, | ||
989 | &dev_attr_fan2_div.attr, | ||
990 | |||
991 | &dev_attr_temp1_input.attr, | ||
992 | &dev_attr_temp1_max.attr, | ||
993 | &dev_attr_temp1_max_hyst.attr, | ||
994 | &dev_attr_temp1_type.attr, | ||
995 | &dev_attr_temp2_input.attr, | ||
996 | &dev_attr_temp2_max.attr, | ||
997 | &dev_attr_temp2_max_hyst.attr, | ||
998 | &dev_attr_temp2_type.attr, | ||
999 | |||
1000 | &dev_attr_alarms.attr, | ||
1001 | &dev_attr_beep_enable.attr, | ||
1002 | &dev_attr_beep_mask.attr, | ||
1003 | |||
1004 | &dev_attr_pwm1.attr, | ||
1005 | &dev_attr_pwm2.attr, | ||
1006 | |||
1007 | NULL | ||
1008 | }; | ||
1009 | |||
1010 | static const struct attribute_group w83627hf_group = { | ||
1011 | .attrs = w83627hf_attributes, | ||
1012 | }; | ||
1013 | |||
1014 | static struct attribute *w83627hf_attributes_opt[] = { | ||
1015 | &dev_attr_in1_input.attr, | ||
1016 | &dev_attr_in1_min.attr, | ||
1017 | &dev_attr_in1_max.attr, | ||
1018 | &dev_attr_in5_input.attr, | ||
1019 | &dev_attr_in5_min.attr, | ||
1020 | &dev_attr_in5_max.attr, | ||
1021 | &dev_attr_in6_input.attr, | ||
1022 | &dev_attr_in6_min.attr, | ||
1023 | &dev_attr_in6_max.attr, | ||
1024 | |||
1025 | &dev_attr_fan3_input.attr, | ||
1026 | &dev_attr_fan3_min.attr, | ||
1027 | &dev_attr_fan3_div.attr, | ||
1028 | |||
1029 | &dev_attr_temp3_input.attr, | ||
1030 | &dev_attr_temp3_max.attr, | ||
1031 | &dev_attr_temp3_max_hyst.attr, | ||
1032 | &dev_attr_temp3_type.attr, | ||
1033 | |||
1034 | &dev_attr_pwm3.attr, | ||
1035 | |||
1036 | NULL | ||
1037 | }; | ||
1038 | |||
1039 | static const struct attribute_group w83627hf_group_opt = { | ||
1040 | .attrs = w83627hf_attributes_opt, | ||
1041 | }; | ||
1042 | |||
1012 | static int w83627hf_detect(struct i2c_adapter *adapter) | 1043 | static int w83627hf_detect(struct i2c_adapter *adapter) |
1013 | { | 1044 | { |
1014 | int val, kind; | 1045 | int val, kind; |
@@ -1108,62 +1139,72 @@ static int w83627hf_detect(struct i2c_adapter *adapter) | |||
1108 | data->fan_min[1] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(2)); | 1139 | data->fan_min[1] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(2)); |
1109 | data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3)); | 1140 | data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3)); |
1110 | 1141 | ||
1111 | /* Register sysfs hooks */ | 1142 | /* Register common device attributes */ |
1112 | data->class_dev = hwmon_device_register(&new_client->dev); | 1143 | if ((err = sysfs_create_group(&new_client->dev.kobj, &w83627hf_group))) |
1113 | if (IS_ERR(data->class_dev)) { | ||
1114 | err = PTR_ERR(data->class_dev); | ||
1115 | goto ERROR3; | 1144 | goto ERROR3; |
1116 | } | ||
1117 | |||
1118 | device_create_file_in(new_client, 0); | ||
1119 | if (kind != w83697hf) | ||
1120 | device_create_file_in(new_client, 1); | ||
1121 | device_create_file_in(new_client, 2); | ||
1122 | device_create_file_in(new_client, 3); | ||
1123 | device_create_file_in(new_client, 4); | ||
1124 | if (kind == w83627hf || kind == w83697hf) { | ||
1125 | device_create_file_in(new_client, 5); | ||
1126 | device_create_file_in(new_client, 6); | ||
1127 | } | ||
1128 | device_create_file_in(new_client, 7); | ||
1129 | device_create_file_in(new_client, 8); | ||
1130 | |||
1131 | device_create_file_fan(new_client, 1); | ||
1132 | device_create_file_fan(new_client, 2); | ||
1133 | if (kind != w83697hf) | ||
1134 | device_create_file_fan(new_client, 3); | ||
1135 | |||
1136 | device_create_file_temp(new_client, 1); | ||
1137 | device_create_file_temp(new_client, 2); | ||
1138 | if (kind != w83697hf) | ||
1139 | device_create_file_temp(new_client, 3); | ||
1140 | 1145 | ||
1141 | if (kind != w83697hf && data->vid != 0xff) { | 1146 | /* Register chip-specific device attributes */ |
1142 | device_create_file_vid(new_client); | 1147 | if (kind == w83627hf || kind == w83697hf) |
1143 | device_create_file_vrm(new_client); | 1148 | if ((err = device_create_file(&new_client->dev, |
1144 | } | 1149 | &dev_attr_in5_input)) |
1150 | || (err = device_create_file(&new_client->dev, | ||
1151 | &dev_attr_in5_min)) | ||
1152 | || (err = device_create_file(&new_client->dev, | ||
1153 | &dev_attr_in5_max)) | ||
1154 | || (err = device_create_file(&new_client->dev, | ||
1155 | &dev_attr_in6_input)) | ||
1156 | || (err = device_create_file(&new_client->dev, | ||
1157 | &dev_attr_in6_min)) | ||
1158 | || (err = device_create_file(&new_client->dev, | ||
1159 | &dev_attr_in6_max))) | ||
1160 | goto ERROR4; | ||
1145 | 1161 | ||
1146 | device_create_file_fan_div(new_client, 1); | ||
1147 | device_create_file_fan_div(new_client, 2); | ||
1148 | if (kind != w83697hf) | 1162 | if (kind != w83697hf) |
1149 | device_create_file_fan_div(new_client, 3); | 1163 | if ((err = device_create_file(&new_client->dev, |
1150 | 1164 | &dev_attr_in1_input)) | |
1151 | device_create_file_alarms(new_client); | 1165 | || (err = device_create_file(&new_client->dev, |
1152 | 1166 | &dev_attr_in1_min)) | |
1153 | device_create_file_beep(new_client); | 1167 | || (err = device_create_file(&new_client->dev, |
1168 | &dev_attr_in1_max)) | ||
1169 | || (err = device_create_file(&new_client->dev, | ||
1170 | &dev_attr_fan3_input)) | ||
1171 | || (err = device_create_file(&new_client->dev, | ||
1172 | &dev_attr_fan3_min)) | ||
1173 | || (err = device_create_file(&new_client->dev, | ||
1174 | &dev_attr_fan3_div)) | ||
1175 | || (err = device_create_file(&new_client->dev, | ||
1176 | &dev_attr_temp3_input)) | ||
1177 | || (err = device_create_file(&new_client->dev, | ||
1178 | &dev_attr_temp3_max)) | ||
1179 | || (err = device_create_file(&new_client->dev, | ||
1180 | &dev_attr_temp3_max_hyst)) | ||
1181 | || (err = device_create_file(&new_client->dev, | ||
1182 | &dev_attr_temp3_type))) | ||
1183 | goto ERROR4; | ||
1184 | |||
1185 | if (kind != w83697hf && data->vid != 0xff) | ||
1186 | if ((err = device_create_file(&new_client->dev, | ||
1187 | &dev_attr_cpu0_vid)) | ||
1188 | || (err = device_create_file(&new_client->dev, | ||
1189 | &dev_attr_vrm))) | ||
1190 | goto ERROR4; | ||
1154 | 1191 | ||
1155 | device_create_file_pwm(new_client, 1); | ||
1156 | device_create_file_pwm(new_client, 2); | ||
1157 | if (kind == w83627thf || kind == w83637hf || kind == w83687thf) | 1192 | if (kind == w83627thf || kind == w83637hf || kind == w83687thf) |
1158 | device_create_file_pwm(new_client, 3); | 1193 | if ((err = device_create_file(&new_client->dev, |
1194 | &dev_attr_pwm3))) | ||
1195 | goto ERROR4; | ||
1159 | 1196 | ||
1160 | device_create_file_sensor(new_client, 1); | 1197 | data->class_dev = hwmon_device_register(&new_client->dev); |
1161 | device_create_file_sensor(new_client, 2); | 1198 | if (IS_ERR(data->class_dev)) { |
1162 | if (kind != w83697hf) | 1199 | err = PTR_ERR(data->class_dev); |
1163 | device_create_file_sensor(new_client, 3); | 1200 | goto ERROR4; |
1201 | } | ||
1164 | 1202 | ||
1165 | return 0; | 1203 | return 0; |
1166 | 1204 | ||
1205 | ERROR4: | ||
1206 | sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group); | ||
1207 | sysfs_remove_group(&new_client->dev.kobj, &w83627hf_group_opt); | ||
1167 | ERROR3: | 1208 | ERROR3: |
1168 | i2c_detach_client(new_client); | 1209 | i2c_detach_client(new_client); |
1169 | ERROR2: | 1210 | ERROR2: |
@@ -1181,6 +1222,9 @@ static int w83627hf_detach_client(struct i2c_client *client) | |||
1181 | 1222 | ||
1182 | hwmon_device_unregister(data->class_dev); | 1223 | hwmon_device_unregister(data->class_dev); |
1183 | 1224 | ||
1225 | sysfs_remove_group(&client->dev.kobj, &w83627hf_group); | ||
1226 | sysfs_remove_group(&client->dev.kobj, &w83627hf_group_opt); | ||
1227 | |||
1184 | if ((err = i2c_detach_client(client))) | 1228 | if ((err = i2c_detach_client(client))) |
1185 | return err; | 1229 | return err; |
1186 | 1230 | ||
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 95221b14e13a..a4584ec69842 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/i2c-isa.h> | 41 | #include <linux/i2c-isa.h> |
42 | #include <linux/hwmon.h> | 42 | #include <linux/hwmon.h> |
43 | #include <linux/hwmon-vid.h> | 43 | #include <linux/hwmon-vid.h> |
44 | #include <linux/sysfs.h> | ||
44 | #include <linux/err.h> | 45 | #include <linux/err.h> |
45 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
46 | #include <asm/io.h> | 47 | #include <asm/io.h> |
@@ -360,13 +361,6 @@ sysfs_in_offsets(6); | |||
360 | sysfs_in_offsets(7); | 361 | sysfs_in_offsets(7); |
361 | sysfs_in_offsets(8); | 362 | sysfs_in_offsets(8); |
362 | 363 | ||
363 | #define device_create_file_in(client, offset) \ | ||
364 | do { \ | ||
365 | device_create_file(&client->dev, &dev_attr_in##offset##_input); \ | ||
366 | device_create_file(&client->dev, &dev_attr_in##offset##_min); \ | ||
367 | device_create_file(&client->dev, &dev_attr_in##offset##_max); \ | ||
368 | } while (0) | ||
369 | |||
370 | #define show_fan_reg(reg) \ | 364 | #define show_fan_reg(reg) \ |
371 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ | 365 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ |
372 | { \ | 366 | { \ |
@@ -421,12 +415,6 @@ sysfs_fan_min_offset(2); | |||
421 | sysfs_fan_offset(3); | 415 | sysfs_fan_offset(3); |
422 | sysfs_fan_min_offset(3); | 416 | sysfs_fan_min_offset(3); |
423 | 417 | ||
424 | #define device_create_file_fan(client, offset) \ | ||
425 | do { \ | ||
426 | device_create_file(&client->dev, &dev_attr_fan##offset##_input); \ | ||
427 | device_create_file(&client->dev, &dev_attr_fan##offset##_min); \ | ||
428 | } while (0) | ||
429 | |||
430 | #define show_temp_reg(reg) \ | 418 | #define show_temp_reg(reg) \ |
431 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ | 419 | static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ |
432 | { \ | 420 | { \ |
@@ -497,13 +485,6 @@ sysfs_temp_offsets(1); | |||
497 | sysfs_temp_offsets(2); | 485 | sysfs_temp_offsets(2); |
498 | sysfs_temp_offsets(3); | 486 | sysfs_temp_offsets(3); |
499 | 487 | ||
500 | #define device_create_file_temp(client, offset) \ | ||
501 | do { \ | ||
502 | device_create_file(&client->dev, &dev_attr_temp##offset##_input); \ | ||
503 | device_create_file(&client->dev, &dev_attr_temp##offset##_max); \ | ||
504 | device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \ | ||
505 | } while (0) | ||
506 | |||
507 | static ssize_t | 488 | static ssize_t |
508 | show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) | 489 | show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) |
509 | { | 490 | { |
@@ -511,10 +492,8 @@ show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) | |||
511 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); | 492 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); |
512 | } | 493 | } |
513 | 494 | ||
514 | static | 495 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); |
515 | DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); | 496 | |
516 | #define device_create_file_vid(client) \ | ||
517 | device_create_file(&client->dev, &dev_attr_cpu0_vid); | ||
518 | static ssize_t | 497 | static ssize_t |
519 | show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) | 498 | show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) |
520 | { | 499 | { |
@@ -535,10 +514,8 @@ store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf | |||
535 | return count; | 514 | return count; |
536 | } | 515 | } |
537 | 516 | ||
538 | static | 517 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); |
539 | DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); | 518 | |
540 | #define device_create_file_vrm(client) \ | ||
541 | device_create_file(&client->dev, &dev_attr_vrm); | ||
542 | static ssize_t | 519 | static ssize_t |
543 | show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) | 520 | show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) |
544 | { | 521 | { |
@@ -546,10 +523,8 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) | |||
546 | return sprintf(buf, "%u\n", data->alarms); | 523 | return sprintf(buf, "%u\n", data->alarms); |
547 | } | 524 | } |
548 | 525 | ||
549 | static | 526 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); |
550 | DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); | 527 | |
551 | #define device_create_file_alarms(client) \ | ||
552 | device_create_file(&client->dev, &dev_attr_alarms); | ||
553 | static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf) | 528 | static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf) |
554 | { | 529 | { |
555 | struct w83781d_data *data = w83781d_update_device(dev); | 530 | struct w83781d_data *data = w83781d_update_device(dev); |
@@ -615,12 +590,6 @@ static DEVICE_ATTR(beep_##reg, S_IRUGO | S_IWUSR, show_regs_beep_##reg, store_re | |||
615 | sysfs_beep(ENABLE, enable); | 590 | sysfs_beep(ENABLE, enable); |
616 | sysfs_beep(MASK, mask); | 591 | sysfs_beep(MASK, mask); |
617 | 592 | ||
618 | #define device_create_file_beep(client) \ | ||
619 | do { \ | ||
620 | device_create_file(&client->dev, &dev_attr_beep_enable); \ | ||
621 | device_create_file(&client->dev, &dev_attr_beep_mask); \ | ||
622 | } while (0) | ||
623 | |||
624 | static ssize_t | 593 | static ssize_t |
625 | show_fan_div_reg(struct device *dev, char *buf, int nr) | 594 | show_fan_div_reg(struct device *dev, char *buf, int nr) |
626 | { | 595 | { |
@@ -686,11 +655,6 @@ sysfs_fan_div(1); | |||
686 | sysfs_fan_div(2); | 655 | sysfs_fan_div(2); |
687 | sysfs_fan_div(3); | 656 | sysfs_fan_div(3); |
688 | 657 | ||
689 | #define device_create_file_fan_div(client, offset) \ | ||
690 | do { \ | ||
691 | device_create_file(&client->dev, &dev_attr_fan##offset##_div); \ | ||
692 | } while (0) | ||
693 | |||
694 | static ssize_t | 658 | static ssize_t |
695 | show_pwm_reg(struct device *dev, char *buf, int nr) | 659 | show_pwm_reg(struct device *dev, char *buf, int nr) |
696 | { | 660 | { |
@@ -787,16 +751,6 @@ sysfs_pwmenable(2); /* only PWM2 can be enabled/disabled */ | |||
787 | sysfs_pwm(3); | 751 | sysfs_pwm(3); |
788 | sysfs_pwm(4); | 752 | sysfs_pwm(4); |
789 | 753 | ||
790 | #define device_create_file_pwm(client, offset) \ | ||
791 | do { \ | ||
792 | device_create_file(&client->dev, &dev_attr_pwm##offset); \ | ||
793 | } while (0) | ||
794 | |||
795 | #define device_create_file_pwmenable(client, offset) \ | ||
796 | do { \ | ||
797 | device_create_file(&client->dev, &dev_attr_pwm##offset##_enable); \ | ||
798 | } while (0) | ||
799 | |||
800 | static ssize_t | 754 | static ssize_t |
801 | show_sensor_reg(struct device *dev, char *buf, int nr) | 755 | show_sensor_reg(struct device *dev, char *buf, int nr) |
802 | { | 756 | { |
@@ -865,11 +819,6 @@ sysfs_sensor(1); | |||
865 | sysfs_sensor(2); | 819 | sysfs_sensor(2); |
866 | sysfs_sensor(3); | 820 | sysfs_sensor(3); |
867 | 821 | ||
868 | #define device_create_file_sensor(client, offset) \ | ||
869 | do { \ | ||
870 | device_create_file(&client->dev, &dev_attr_temp##offset##_type); \ | ||
871 | } while (0) | ||
872 | |||
873 | /* This function is called when: | 822 | /* This function is called when: |
874 | * w83781d_driver is inserted (when this module is loaded), for each | 823 | * w83781d_driver is inserted (when this module is loaded), for each |
875 | available adapter | 824 | available adapter |
@@ -994,11 +943,69 @@ ERROR_SC_0: | |||
994 | return err; | 943 | return err; |
995 | } | 944 | } |
996 | 945 | ||
946 | #define IN_UNIT_ATTRS(X) \ | ||
947 | &dev_attr_in##X##_input.attr, \ | ||
948 | &dev_attr_in##X##_min.attr, \ | ||
949 | &dev_attr_in##X##_max.attr | ||
950 | |||
951 | #define FAN_UNIT_ATTRS(X) \ | ||
952 | &dev_attr_fan##X##_input.attr, \ | ||
953 | &dev_attr_fan##X##_min.attr, \ | ||
954 | &dev_attr_fan##X##_div.attr | ||
955 | |||
956 | #define TEMP_UNIT_ATTRS(X) \ | ||
957 | &dev_attr_temp##X##_input.attr, \ | ||
958 | &dev_attr_temp##X##_max.attr, \ | ||
959 | &dev_attr_temp##X##_max_hyst.attr | ||
960 | |||
961 | static struct attribute* w83781d_attributes[] = { | ||
962 | IN_UNIT_ATTRS(0), | ||
963 | IN_UNIT_ATTRS(2), | ||
964 | IN_UNIT_ATTRS(3), | ||
965 | IN_UNIT_ATTRS(4), | ||
966 | IN_UNIT_ATTRS(5), | ||
967 | IN_UNIT_ATTRS(6), | ||
968 | FAN_UNIT_ATTRS(1), | ||
969 | FAN_UNIT_ATTRS(2), | ||
970 | FAN_UNIT_ATTRS(3), | ||
971 | TEMP_UNIT_ATTRS(1), | ||
972 | TEMP_UNIT_ATTRS(2), | ||
973 | &dev_attr_cpu0_vid.attr, | ||
974 | &dev_attr_vrm.attr, | ||
975 | &dev_attr_alarms.attr, | ||
976 | &dev_attr_beep_mask.attr, | ||
977 | &dev_attr_beep_enable.attr, | ||
978 | NULL | ||
979 | }; | ||
980 | static const struct attribute_group w83781d_group = { | ||
981 | .attrs = w83781d_attributes, | ||
982 | }; | ||
983 | |||
984 | static struct attribute *w83781d_attributes_opt[] = { | ||
985 | IN_UNIT_ATTRS(1), | ||
986 | IN_UNIT_ATTRS(7), | ||
987 | IN_UNIT_ATTRS(8), | ||
988 | TEMP_UNIT_ATTRS(3), | ||
989 | &dev_attr_pwm1.attr, | ||
990 | &dev_attr_pwm2.attr, | ||
991 | &dev_attr_pwm2_enable.attr, | ||
992 | &dev_attr_pwm3.attr, | ||
993 | &dev_attr_pwm4.attr, | ||
994 | &dev_attr_temp1_type.attr, | ||
995 | &dev_attr_temp2_type.attr, | ||
996 | &dev_attr_temp3_type.attr, | ||
997 | NULL | ||
998 | }; | ||
999 | static const struct attribute_group w83781d_group_opt = { | ||
1000 | .attrs = w83781d_attributes_opt, | ||
1001 | }; | ||
1002 | |||
997 | static int | 1003 | static int |
998 | w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | 1004 | w83781d_detect(struct i2c_adapter *adapter, int address, int kind) |
999 | { | 1005 | { |
1000 | int i = 0, val1 = 0, val2; | 1006 | int i = 0, val1 = 0, val2; |
1001 | struct i2c_client *new_client; | 1007 | struct i2c_client *client; |
1008 | struct device *dev; | ||
1002 | struct w83781d_data *data; | 1009 | struct w83781d_data *data; |
1003 | int err; | 1010 | int err; |
1004 | const char *client_name = ""; | 1011 | const char *client_name = ""; |
@@ -1075,13 +1082,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1075 | goto ERROR1; | 1082 | goto ERROR1; |
1076 | } | 1083 | } |
1077 | 1084 | ||
1078 | new_client = &data->client; | 1085 | client = &data->client; |
1079 | i2c_set_clientdata(new_client, data); | 1086 | i2c_set_clientdata(client, data); |
1080 | new_client->addr = address; | 1087 | client->addr = address; |
1081 | mutex_init(&data->lock); | 1088 | mutex_init(&data->lock); |
1082 | new_client->adapter = adapter; | 1089 | client->adapter = adapter; |
1083 | new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver; | 1090 | client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver; |
1084 | new_client->flags = 0; | 1091 | client->flags = 0; |
1092 | dev = &client->dev; | ||
1085 | 1093 | ||
1086 | /* Now, we do the remaining detection. */ | 1094 | /* Now, we do the remaining detection. */ |
1087 | 1095 | ||
@@ -1090,20 +1098,18 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1090 | force_*=... parameter, and the Winbond will be reset to the right | 1098 | force_*=... parameter, and the Winbond will be reset to the right |
1091 | bank. */ | 1099 | bank. */ |
1092 | if (kind < 0) { | 1100 | if (kind < 0) { |
1093 | if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80) { | 1101 | if (w83781d_read_value(client, W83781D_REG_CONFIG) & 0x80) { |
1094 | dev_dbg(&new_client->dev, "Detection failed at step " | 1102 | dev_dbg(dev, "Detection failed at step 3\n"); |
1095 | "3\n"); | ||
1096 | err = -ENODEV; | 1103 | err = -ENODEV; |
1097 | goto ERROR2; | 1104 | goto ERROR2; |
1098 | } | 1105 | } |
1099 | val1 = w83781d_read_value(new_client, W83781D_REG_BANK); | 1106 | val1 = w83781d_read_value(client, W83781D_REG_BANK); |
1100 | val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN); | 1107 | val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN); |
1101 | /* Check for Winbond or Asus ID if in bank 0 */ | 1108 | /* Check for Winbond or Asus ID if in bank 0 */ |
1102 | if ((!(val1 & 0x07)) && | 1109 | if ((!(val1 & 0x07)) && |
1103 | (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)) | 1110 | (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)) |
1104 | || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) { | 1111 | || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) { |
1105 | dev_dbg(&new_client->dev, "Detection failed at step " | 1112 | dev_dbg(dev, "Detection failed at step 4\n"); |
1106 | "4\n"); | ||
1107 | err = -ENODEV; | 1113 | err = -ENODEV; |
1108 | goto ERROR2; | 1114 | goto ERROR2; |
1109 | } | 1115 | } |
@@ -1112,9 +1118,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1112 | if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) || | 1118 | if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) || |
1113 | ((val1 & 0x80) && (val2 == 0x5c)))) { | 1119 | ((val1 & 0x80) && (val2 == 0x5c)))) { |
1114 | if (w83781d_read_value | 1120 | if (w83781d_read_value |
1115 | (new_client, W83781D_REG_I2C_ADDR) != address) { | 1121 | (client, W83781D_REG_I2C_ADDR) != address) { |
1116 | dev_dbg(&new_client->dev, "Detection failed " | 1122 | dev_dbg(dev, "Detection failed at step 5\n"); |
1117 | "at step 5\n"); | ||
1118 | err = -ENODEV; | 1123 | err = -ENODEV; |
1119 | goto ERROR2; | 1124 | goto ERROR2; |
1120 | } | 1125 | } |
@@ -1123,27 +1128,26 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1123 | 1128 | ||
1124 | /* We have either had a force parameter, or we have already detected the | 1129 | /* We have either had a force parameter, or we have already detected the |
1125 | Winbond. Put it now into bank 0 and Vendor ID High Byte */ | 1130 | Winbond. Put it now into bank 0 and Vendor ID High Byte */ |
1126 | w83781d_write_value(new_client, W83781D_REG_BANK, | 1131 | w83781d_write_value(client, W83781D_REG_BANK, |
1127 | (w83781d_read_value(new_client, | 1132 | (w83781d_read_value(client, W83781D_REG_BANK) |
1128 | W83781D_REG_BANK) & 0x78) | | 1133 | & 0x78) | 0x80); |
1129 | 0x80); | ||
1130 | 1134 | ||
1131 | /* Determine the chip type. */ | 1135 | /* Determine the chip type. */ |
1132 | if (kind <= 0) { | 1136 | if (kind <= 0) { |
1133 | /* get vendor ID */ | 1137 | /* get vendor ID */ |
1134 | val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN); | 1138 | val2 = w83781d_read_value(client, W83781D_REG_CHIPMAN); |
1135 | if (val2 == 0x5c) | 1139 | if (val2 == 0x5c) |
1136 | vendid = winbond; | 1140 | vendid = winbond; |
1137 | else if (val2 == 0x12) | 1141 | else if (val2 == 0x12) |
1138 | vendid = asus; | 1142 | vendid = asus; |
1139 | else { | 1143 | else { |
1140 | dev_dbg(&new_client->dev, "Chip was made by neither " | 1144 | dev_dbg(dev, "Chip was made by neither " |
1141 | "Winbond nor Asus?\n"); | 1145 | "Winbond nor Asus?\n"); |
1142 | err = -ENODEV; | 1146 | err = -ENODEV; |
1143 | goto ERROR2; | 1147 | goto ERROR2; |
1144 | } | 1148 | } |
1145 | 1149 | ||
1146 | val1 = w83781d_read_value(new_client, W83781D_REG_WCHIPID); | 1150 | val1 = w83781d_read_value(client, W83781D_REG_WCHIPID); |
1147 | if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond) | 1151 | if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond) |
1148 | kind = w83781d; | 1152 | kind = w83781d; |
1149 | else if (val1 == 0x30 && vendid == winbond) | 1153 | else if (val1 == 0x30 && vendid == winbond) |
@@ -1157,7 +1161,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1157 | kind = as99127f; | 1161 | kind = as99127f; |
1158 | else { | 1162 | else { |
1159 | if (kind == 0) | 1163 | if (kind == 0) |
1160 | dev_warn(&new_client->dev, "Ignoring 'force' " | 1164 | dev_warn(dev, "Ignoring 'force' " |
1161 | "parameter for unknown chip at " | 1165 | "parameter for unknown chip at " |
1162 | "adapter %d, address 0x%02x\n", | 1166 | "adapter %d, address 0x%02x\n", |
1163 | i2c_adapter_id(adapter), address); | 1167 | i2c_adapter_id(adapter), address); |
@@ -1179,20 +1183,20 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1179 | } | 1183 | } |
1180 | 1184 | ||
1181 | /* Fill in the remaining client fields and put into the global list */ | 1185 | /* Fill in the remaining client fields and put into the global list */ |
1182 | strlcpy(new_client->name, client_name, I2C_NAME_SIZE); | 1186 | strlcpy(client->name, client_name, I2C_NAME_SIZE); |
1183 | data->type = kind; | 1187 | data->type = kind; |
1184 | 1188 | ||
1185 | data->valid = 0; | 1189 | data->valid = 0; |
1186 | mutex_init(&data->update_lock); | 1190 | mutex_init(&data->update_lock); |
1187 | 1191 | ||
1188 | /* Tell the I2C layer a new client has arrived */ | 1192 | /* Tell the I2C layer a new client has arrived */ |
1189 | if ((err = i2c_attach_client(new_client))) | 1193 | if ((err = i2c_attach_client(client))) |
1190 | goto ERROR2; | 1194 | goto ERROR2; |
1191 | 1195 | ||
1192 | /* attach secondary i2c lm75-like clients */ | 1196 | /* attach secondary i2c lm75-like clients */ |
1193 | if (!is_isa) { | 1197 | if (!is_isa) { |
1194 | if ((err = w83781d_detect_subclients(adapter, address, | 1198 | if ((err = w83781d_detect_subclients(adapter, address, |
1195 | kind, new_client))) | 1199 | kind, client))) |
1196 | goto ERROR3; | 1200 | goto ERROR3; |
1197 | } else { | 1201 | } else { |
1198 | data->lm75[0] = NULL; | 1202 | data->lm75[0] = NULL; |
@@ -1200,11 +1204,11 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1200 | } | 1204 | } |
1201 | 1205 | ||
1202 | /* Initialize the chip */ | 1206 | /* Initialize the chip */ |
1203 | w83781d_init_client(new_client); | 1207 | w83781d_init_client(client); |
1204 | 1208 | ||
1205 | /* A few vars need to be filled upon startup */ | 1209 | /* A few vars need to be filled upon startup */ |
1206 | for (i = 1; i <= 3; i++) { | 1210 | for (i = 1; i <= 3; i++) { |
1207 | data->fan_min[i - 1] = w83781d_read_value(new_client, | 1211 | data->fan_min[i - 1] = w83781d_read_value(client, |
1208 | W83781D_REG_FAN_MIN(i)); | 1212 | W83781D_REG_FAN_MIN(i)); |
1209 | } | 1213 | } |
1210 | if (kind != w83781d && kind != as99127f) | 1214 | if (kind != w83781d && kind != as99127f) |
@@ -1212,65 +1216,68 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1212 | data->pwmenable[i] = 1; | 1216 | data->pwmenable[i] = 1; |
1213 | 1217 | ||
1214 | /* Register sysfs hooks */ | 1218 | /* Register sysfs hooks */ |
1215 | data->class_dev = hwmon_device_register(&new_client->dev); | 1219 | if ((err = sysfs_create_group(&dev->kobj, &w83781d_group))) |
1216 | if (IS_ERR(data->class_dev)) { | ||
1217 | err = PTR_ERR(data->class_dev); | ||
1218 | goto ERROR4; | 1220 | goto ERROR4; |
1219 | } | ||
1220 | 1221 | ||
1221 | device_create_file_in(new_client, 0); | 1222 | if (kind != w83783s) { |
1222 | if (kind != w83783s) | 1223 | if ((err = device_create_file(dev, &dev_attr_in1_input)) |
1223 | device_create_file_in(new_client, 1); | 1224 | || (err = device_create_file(dev, &dev_attr_in1_min)) |
1224 | device_create_file_in(new_client, 2); | 1225 | || (err = device_create_file(dev, &dev_attr_in1_max))) |
1225 | device_create_file_in(new_client, 3); | 1226 | goto ERROR4; |
1226 | device_create_file_in(new_client, 4); | 1227 | } |
1227 | device_create_file_in(new_client, 5); | ||
1228 | device_create_file_in(new_client, 6); | ||
1229 | if (kind != as99127f && kind != w83781d && kind != w83783s) { | 1228 | if (kind != as99127f && kind != w83781d && kind != w83783s) { |
1230 | device_create_file_in(new_client, 7); | 1229 | if ((err = device_create_file(dev, &dev_attr_in7_input)) |
1231 | device_create_file_in(new_client, 8); | 1230 | || (err = device_create_file(dev, &dev_attr_in7_min)) |
1231 | || (err = device_create_file(dev, &dev_attr_in7_max)) | ||
1232 | || (err = device_create_file(dev, &dev_attr_in8_input)) | ||
1233 | || (err = device_create_file(dev, &dev_attr_in8_min)) | ||
1234 | || (err = device_create_file(dev, &dev_attr_in8_max))) | ||
1235 | goto ERROR4; | ||
1236 | } | ||
1237 | if (kind != w83783s) { | ||
1238 | if ((err = device_create_file(dev, &dev_attr_temp3_input)) | ||
1239 | || (err = device_create_file(dev, &dev_attr_temp3_max)) | ||
1240 | || (err = device_create_file(dev, | ||
1241 | &dev_attr_temp3_max_hyst))) | ||
1242 | goto ERROR4; | ||
1232 | } | 1243 | } |
1233 | |||
1234 | device_create_file_fan(new_client, 1); | ||
1235 | device_create_file_fan(new_client, 2); | ||
1236 | device_create_file_fan(new_client, 3); | ||
1237 | |||
1238 | device_create_file_temp(new_client, 1); | ||
1239 | device_create_file_temp(new_client, 2); | ||
1240 | if (kind != w83783s) | ||
1241 | device_create_file_temp(new_client, 3); | ||
1242 | |||
1243 | device_create_file_vid(new_client); | ||
1244 | device_create_file_vrm(new_client); | ||
1245 | |||
1246 | device_create_file_fan_div(new_client, 1); | ||
1247 | device_create_file_fan_div(new_client, 2); | ||
1248 | device_create_file_fan_div(new_client, 3); | ||
1249 | |||
1250 | device_create_file_alarms(new_client); | ||
1251 | |||
1252 | device_create_file_beep(new_client); | ||
1253 | 1244 | ||
1254 | if (kind != w83781d && kind != as99127f) { | 1245 | if (kind != w83781d && kind != as99127f) { |
1255 | device_create_file_pwm(new_client, 1); | 1246 | if ((err = device_create_file(dev, &dev_attr_pwm1)) |
1256 | device_create_file_pwm(new_client, 2); | 1247 | || (err = device_create_file(dev, &dev_attr_pwm2)) |
1257 | device_create_file_pwmenable(new_client, 2); | 1248 | || (err = device_create_file(dev, &dev_attr_pwm2_enable))) |
1249 | goto ERROR4; | ||
1258 | } | 1250 | } |
1259 | if (kind == w83782d && !is_isa) { | 1251 | if (kind == w83782d && !is_isa) { |
1260 | device_create_file_pwm(new_client, 3); | 1252 | if ((err = device_create_file(dev, &dev_attr_pwm3)) |
1261 | device_create_file_pwm(new_client, 4); | 1253 | || (err = device_create_file(dev, &dev_attr_pwm4))) |
1254 | goto ERROR4; | ||
1262 | } | 1255 | } |
1263 | 1256 | ||
1264 | if (kind != as99127f && kind != w83781d) { | 1257 | if (kind != as99127f && kind != w83781d) { |
1265 | device_create_file_sensor(new_client, 1); | 1258 | if ((err = device_create_file(dev, &dev_attr_temp1_type)) |
1266 | device_create_file_sensor(new_client, 2); | 1259 | || (err = device_create_file(dev, |
1267 | if (kind != w83783s) | 1260 | &dev_attr_temp2_type))) |
1268 | device_create_file_sensor(new_client, 3); | 1261 | goto ERROR4; |
1262 | if (kind != w83783s) { | ||
1263 | if ((err = device_create_file(dev, | ||
1264 | &dev_attr_temp3_type))) | ||
1265 | goto ERROR4; | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | data->class_dev = hwmon_device_register(dev); | ||
1270 | if (IS_ERR(data->class_dev)) { | ||
1271 | err = PTR_ERR(data->class_dev); | ||
1272 | goto ERROR4; | ||
1269 | } | 1273 | } |
1270 | 1274 | ||
1271 | return 0; | 1275 | return 0; |
1272 | 1276 | ||
1273 | ERROR4: | 1277 | ERROR4: |
1278 | sysfs_remove_group(&dev->kobj, &w83781d_group); | ||
1279 | sysfs_remove_group(&dev->kobj, &w83781d_group_opt); | ||
1280 | |||
1274 | if (data->lm75[1]) { | 1281 | if (data->lm75[1]) { |
1275 | i2c_detach_client(data->lm75[1]); | 1282 | i2c_detach_client(data->lm75[1]); |
1276 | kfree(data->lm75[1]); | 1283 | kfree(data->lm75[1]); |
@@ -1280,7 +1287,7 @@ ERROR4: | |||
1280 | kfree(data->lm75[0]); | 1287 | kfree(data->lm75[0]); |
1281 | } | 1288 | } |
1282 | ERROR3: | 1289 | ERROR3: |
1283 | i2c_detach_client(new_client); | 1290 | i2c_detach_client(client); |
1284 | ERROR2: | 1291 | ERROR2: |
1285 | kfree(data); | 1292 | kfree(data); |
1286 | ERROR1: | 1293 | ERROR1: |
@@ -1297,9 +1304,11 @@ w83781d_detach_client(struct i2c_client *client) | |||
1297 | int err; | 1304 | int err; |
1298 | 1305 | ||
1299 | /* main client */ | 1306 | /* main client */ |
1300 | if (data) | 1307 | if (data) { |
1301 | hwmon_device_unregister(data->class_dev); | 1308 | hwmon_device_unregister(data->class_dev); |
1302 | 1309 | sysfs_remove_group(&client->dev.kobj, &w83781d_group); | |
1310 | sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt); | ||
1311 | } | ||
1303 | if (i2c_is_isa_client(client)) | 1312 | if (i2c_is_isa_client(client)) |
1304 | release_region(client->addr, W83781D_EXTENT); | 1313 | release_region(client->addr, W83781D_EXTENT); |
1305 | 1314 | ||
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index eec43abd57fb..d965d074cd61 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c | |||
@@ -27,9 +27,9 @@ | |||
27 | 27 | ||
28 | The w83791d chip appears to be part way between the 83781d and the | 28 | The w83791d chip appears to be part way between the 83781d and the |
29 | 83792d. Thus, this file is derived from both the w83792d.c and | 29 | 83792d. Thus, this file is derived from both the w83792d.c and |
30 | w83781d.c files, but its output is more along the lines of the | 30 | w83781d.c files. |
31 | 83781d (which means there are no changes to the user-mode sensors | 31 | |
32 | program which treats the 83791d as an 83781d). | 32 | The w83791g chip is the same as the w83791d but lead-free. |
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include <linux/config.h> | 35 | #include <linux/config.h> |
@@ -1172,6 +1172,7 @@ static struct w83791d_data *w83791d_update_device(struct device *dev) | |||
1172 | (w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) + | 1172 | (w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) + |
1173 | (w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16); | 1173 | (w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16); |
1174 | 1174 | ||
1175 | /* Extract global beep enable flag */ | ||
1175 | data->beep_enable = | 1176 | data->beep_enable = |
1176 | (data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01; | 1177 | (data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01; |
1177 | 1178 | ||
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 7576ec9426a3..4e108262576f 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/hwmon-sysfs.h> | 43 | #include <linux/hwmon-sysfs.h> |
44 | #include <linux/err.h> | 44 | #include <linux/err.h> |
45 | #include <linux/mutex.h> | 45 | #include <linux/mutex.h> |
46 | #include <linux/sysfs.h> | ||
46 | 47 | ||
47 | /* Addresses to scan */ | 48 | /* Addresses to scan */ |
48 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; | 49 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; |
@@ -381,41 +382,6 @@ static ssize_t store_in_##reg (struct device *dev, \ | |||
381 | store_in_reg(MIN, min); | 382 | store_in_reg(MIN, min); |
382 | store_in_reg(MAX, max); | 383 | store_in_reg(MAX, max); |
383 | 384 | ||
384 | static struct sensor_device_attribute sda_in_input[] = { | ||
385 | SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), | ||
386 | SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), | ||
387 | SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), | ||
388 | SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), | ||
389 | SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), | ||
390 | SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), | ||
391 | SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), | ||
392 | SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), | ||
393 | SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), | ||
394 | }; | ||
395 | static struct sensor_device_attribute sda_in_min[] = { | ||
396 | SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), | ||
397 | SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), | ||
398 | SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), | ||
399 | SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), | ||
400 | SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), | ||
401 | SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), | ||
402 | SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), | ||
403 | SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), | ||
404 | SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), | ||
405 | }; | ||
406 | static struct sensor_device_attribute sda_in_max[] = { | ||
407 | SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), | ||
408 | SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), | ||
409 | SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), | ||
410 | SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), | ||
411 | SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), | ||
412 | SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), | ||
413 | SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), | ||
414 | SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), | ||
415 | SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), | ||
416 | }; | ||
417 | |||
418 | |||
419 | #define show_fan_reg(reg) \ | 385 | #define show_fan_reg(reg) \ |
420 | static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ | 386 | static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ |
421 | char *buf) \ | 387 | char *buf) \ |
@@ -499,35 +465,6 @@ store_fan_div(struct device *dev, struct device_attribute *attr, | |||
499 | return count; | 465 | return count; |
500 | } | 466 | } |
501 | 467 | ||
502 | static struct sensor_device_attribute sda_fan_input[] = { | ||
503 | SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1), | ||
504 | SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2), | ||
505 | SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3), | ||
506 | SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4), | ||
507 | SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5), | ||
508 | SENSOR_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6), | ||
509 | SENSOR_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7), | ||
510 | }; | ||
511 | static struct sensor_device_attribute sda_fan_min[] = { | ||
512 | SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 1), | ||
513 | SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 2), | ||
514 | SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 3), | ||
515 | SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 4), | ||
516 | SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 5), | ||
517 | SENSOR_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 6), | ||
518 | SENSOR_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, store_fan_min, 7), | ||
519 | }; | ||
520 | static struct sensor_device_attribute sda_fan_div[] = { | ||
521 | SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 1), | ||
522 | SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 2), | ||
523 | SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 3), | ||
524 | SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 4), | ||
525 | SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 5), | ||
526 | SENSOR_ATTR(fan6_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 6), | ||
527 | SENSOR_ATTR(fan7_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 7), | ||
528 | }; | ||
529 | |||
530 | |||
531 | /* read/write the temperature1, includes measured value and limits */ | 468 | /* read/write the temperature1, includes measured value and limits */ |
532 | 469 | ||
533 | static ssize_t show_temp1(struct device *dev, struct device_attribute *attr, | 470 | static ssize_t show_temp1(struct device *dev, struct device_attribute *attr, |
@@ -595,24 +532,6 @@ static ssize_t store_temp23(struct device *dev, struct device_attribute *attr, | |||
595 | return count; | 532 | return count; |
596 | } | 533 | } |
597 | 534 | ||
598 | static struct sensor_device_attribute_2 sda_temp_input[] = { | ||
599 | SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0), | ||
600 | SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0), | ||
601 | SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0), | ||
602 | }; | ||
603 | |||
604 | static struct sensor_device_attribute_2 sda_temp_max[] = { | ||
605 | SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 1), | ||
606 | SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 2), | ||
607 | SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 2), | ||
608 | }; | ||
609 | |||
610 | static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { | ||
611 | SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1, store_temp1, 0, 2), | ||
612 | SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 0, 4), | ||
613 | SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 4), | ||
614 | }; | ||
615 | |||
616 | /* get reatime status of all sensors items: voltage, temp, fan */ | 535 | /* get reatime status of all sensors items: voltage, temp, fan */ |
617 | static ssize_t | 536 | static ssize_t |
618 | show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) | 537 | show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -621,9 +540,6 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) | |||
621 | return sprintf(buf, "%d\n", data->alarms); | 540 | return sprintf(buf, "%d\n", data->alarms); |
622 | } | 541 | } |
623 | 542 | ||
624 | static | ||
625 | DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); | ||
626 | |||
627 | static ssize_t | 543 | static ssize_t |
628 | show_pwm(struct device *dev, struct device_attribute *attr, | 544 | show_pwm(struct device *dev, struct device_attribute *attr, |
629 | char *buf) | 545 | char *buf) |
@@ -715,21 +631,6 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, | |||
715 | return count; | 631 | return count; |
716 | } | 632 | } |
717 | 633 | ||
718 | static struct sensor_device_attribute sda_pwm[] = { | ||
719 | SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0), | ||
720 | SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), | ||
721 | SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), | ||
722 | }; | ||
723 | static struct sensor_device_attribute sda_pwm_enable[] = { | ||
724 | SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, | ||
725 | show_pwmenable, store_pwmenable, 1), | ||
726 | SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, | ||
727 | show_pwmenable, store_pwmenable, 2), | ||
728 | SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, | ||
729 | show_pwmenable, store_pwmenable, 3), | ||
730 | }; | ||
731 | |||
732 | |||
733 | static ssize_t | 634 | static ssize_t |
734 | show_pwm_mode(struct device *dev, struct device_attribute *attr, | 635 | show_pwm_mode(struct device *dev, struct device_attribute *attr, |
735 | char *buf) | 636 | char *buf) |
@@ -767,16 +668,6 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, | |||
767 | return count; | 668 | return count; |
768 | } | 669 | } |
769 | 670 | ||
770 | static struct sensor_device_attribute sda_pwm_mode[] = { | ||
771 | SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, | ||
772 | show_pwm_mode, store_pwm_mode, 0), | ||
773 | SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, | ||
774 | show_pwm_mode, store_pwm_mode, 1), | ||
775 | SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, | ||
776 | show_pwm_mode, store_pwm_mode, 2), | ||
777 | }; | ||
778 | |||
779 | |||
780 | static ssize_t | 671 | static ssize_t |
781 | show_regs_chassis(struct device *dev, struct device_attribute *attr, | 672 | show_regs_chassis(struct device *dev, struct device_attribute *attr, |
782 | char *buf) | 673 | char *buf) |
@@ -785,8 +676,6 @@ show_regs_chassis(struct device *dev, struct device_attribute *attr, | |||
785 | return sprintf(buf, "%d\n", data->chassis); | 676 | return sprintf(buf, "%d\n", data->chassis); |
786 | } | 677 | } |
787 | 678 | ||
788 | static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); | ||
789 | |||
790 | static ssize_t | 679 | static ssize_t |
791 | show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) | 680 | show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) |
792 | { | 681 | { |
@@ -815,9 +704,6 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr, | |||
815 | return count; | 704 | return count; |
816 | } | 705 | } |
817 | 706 | ||
818 | static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, | ||
819 | show_chassis_clear, store_chassis_clear); | ||
820 | |||
821 | /* For Smart Fan I / Thermal Cruise */ | 707 | /* For Smart Fan I / Thermal Cruise */ |
822 | static ssize_t | 708 | static ssize_t |
823 | show_thermal_cruise(struct device *dev, struct device_attribute *attr, | 709 | show_thermal_cruise(struct device *dev, struct device_attribute *attr, |
@@ -853,15 +739,6 @@ store_thermal_cruise(struct device *dev, struct device_attribute *attr, | |||
853 | return count; | 739 | return count; |
854 | } | 740 | } |
855 | 741 | ||
856 | static struct sensor_device_attribute sda_thermal_cruise[] = { | ||
857 | SENSOR_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO, | ||
858 | show_thermal_cruise, store_thermal_cruise, 1), | ||
859 | SENSOR_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO, | ||
860 | show_thermal_cruise, store_thermal_cruise, 2), | ||
861 | SENSOR_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO, | ||
862 | show_thermal_cruise, store_thermal_cruise, 3), | ||
863 | }; | ||
864 | |||
865 | /* For Smart Fan I/Thermal Cruise and Smart Fan II */ | 742 | /* For Smart Fan I/Thermal Cruise and Smart Fan II */ |
866 | static ssize_t | 743 | static ssize_t |
867 | show_tolerance(struct device *dev, struct device_attribute *attr, | 744 | show_tolerance(struct device *dev, struct device_attribute *attr, |
@@ -901,15 +778,6 @@ store_tolerance(struct device *dev, struct device_attribute *attr, | |||
901 | return count; | 778 | return count; |
902 | } | 779 | } |
903 | 780 | ||
904 | static struct sensor_device_attribute sda_tolerance[] = { | ||
905 | SENSOR_ATTR(tolerance1, S_IWUSR | S_IRUGO, | ||
906 | show_tolerance, store_tolerance, 1), | ||
907 | SENSOR_ATTR(tolerance2, S_IWUSR | S_IRUGO, | ||
908 | show_tolerance, store_tolerance, 2), | ||
909 | SENSOR_ATTR(tolerance3, S_IWUSR | S_IRUGO, | ||
910 | show_tolerance, store_tolerance, 3), | ||
911 | }; | ||
912 | |||
913 | /* For Smart Fan II */ | 781 | /* For Smart Fan II */ |
914 | static ssize_t | 782 | static ssize_t |
915 | show_sf2_point(struct device *dev, struct device_attribute *attr, | 783 | show_sf2_point(struct device *dev, struct device_attribute *attr, |
@@ -946,36 +814,6 @@ store_sf2_point(struct device *dev, struct device_attribute *attr, | |||
946 | return count; | 814 | return count; |
947 | } | 815 | } |
948 | 816 | ||
949 | static struct sensor_device_attribute_2 sda_sf2_point[] = { | ||
950 | SENSOR_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR, | ||
951 | show_sf2_point, store_sf2_point, 1, 1), | ||
952 | SENSOR_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR, | ||
953 | show_sf2_point, store_sf2_point, 2, 1), | ||
954 | SENSOR_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR, | ||
955 | show_sf2_point, store_sf2_point, 3, 1), | ||
956 | SENSOR_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR, | ||
957 | show_sf2_point, store_sf2_point, 4, 1), | ||
958 | |||
959 | SENSOR_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR, | ||
960 | show_sf2_point, store_sf2_point, 1, 2), | ||
961 | SENSOR_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR, | ||
962 | show_sf2_point, store_sf2_point, 2, 2), | ||
963 | SENSOR_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR, | ||
964 | show_sf2_point, store_sf2_point, 3, 2), | ||
965 | SENSOR_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR, | ||
966 | show_sf2_point, store_sf2_point, 4, 2), | ||
967 | |||
968 | SENSOR_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR, | ||
969 | show_sf2_point, store_sf2_point, 1, 3), | ||
970 | SENSOR_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR, | ||
971 | show_sf2_point, store_sf2_point, 2, 3), | ||
972 | SENSOR_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR, | ||
973 | show_sf2_point, store_sf2_point, 3, 3), | ||
974 | SENSOR_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR, | ||
975 | show_sf2_point, store_sf2_point, 4, 3), | ||
976 | }; | ||
977 | |||
978 | |||
979 | static ssize_t | 817 | static ssize_t |
980 | show_sf2_level(struct device *dev, struct device_attribute *attr, | 818 | show_sf2_level(struct device *dev, struct device_attribute *attr, |
981 | char *buf) | 819 | char *buf) |
@@ -1016,29 +854,6 @@ store_sf2_level(struct device *dev, struct device_attribute *attr, | |||
1016 | return count; | 854 | return count; |
1017 | } | 855 | } |
1018 | 856 | ||
1019 | static struct sensor_device_attribute_2 sda_sf2_level[] = { | ||
1020 | SENSOR_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR, | ||
1021 | show_sf2_level, store_sf2_level, 1, 1), | ||
1022 | SENSOR_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR, | ||
1023 | show_sf2_level, store_sf2_level, 2, 1), | ||
1024 | SENSOR_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR, | ||
1025 | show_sf2_level, store_sf2_level, 3, 1), | ||
1026 | |||
1027 | SENSOR_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR, | ||
1028 | show_sf2_level, store_sf2_level, 1, 2), | ||
1029 | SENSOR_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR, | ||
1030 | show_sf2_level, store_sf2_level, 2, 2), | ||
1031 | SENSOR_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR, | ||
1032 | show_sf2_level, store_sf2_level, 3, 2), | ||
1033 | |||
1034 | SENSOR_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR, | ||
1035 | show_sf2_level, store_sf2_level, 1, 3), | ||
1036 | SENSOR_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR, | ||
1037 | show_sf2_level, store_sf2_level, 2, 3), | ||
1038 | SENSOR_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR, | ||
1039 | show_sf2_level, store_sf2_level, 3, 3), | ||
1040 | }; | ||
1041 | |||
1042 | /* This function is called when: | 857 | /* This function is called when: |
1043 | * w83792d_driver is inserted (when this module is loaded), for each | 858 | * w83792d_driver is inserted (when this module is loaded), for each |
1044 | available adapter | 859 | available adapter |
@@ -1139,12 +954,297 @@ ERROR_SC_0: | |||
1139 | return err; | 954 | return err; |
1140 | } | 955 | } |
1141 | 956 | ||
1142 | static void device_create_file_fan(struct device *dev, int i) | 957 | static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0); |
1143 | { | 958 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1); |
1144 | device_create_file(dev, &sda_fan_input[i].dev_attr); | 959 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2); |
1145 | device_create_file(dev, &sda_fan_div[i].dev_attr); | 960 | static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3); |
1146 | device_create_file(dev, &sda_fan_min[i].dev_attr); | 961 | static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4); |
1147 | } | 962 | static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5); |
963 | static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6); | ||
964 | static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7); | ||
965 | static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8); | ||
966 | static SENSOR_DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, | ||
967 | show_in_min, store_in_min, 0); | ||
968 | static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, | ||
969 | show_in_min, store_in_min, 1); | ||
970 | static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, | ||
971 | show_in_min, store_in_min, 2); | ||
972 | static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, | ||
973 | show_in_min, store_in_min, 3); | ||
974 | static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, | ||
975 | show_in_min, store_in_min, 4); | ||
976 | static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, | ||
977 | show_in_min, store_in_min, 5); | ||
978 | static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, | ||
979 | show_in_min, store_in_min, 6); | ||
980 | static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, | ||
981 | show_in_min, store_in_min, 7); | ||
982 | static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, | ||
983 | show_in_min, store_in_min, 8); | ||
984 | static SENSOR_DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO, | ||
985 | show_in_max, store_in_max, 0); | ||
986 | static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, | ||
987 | show_in_max, store_in_max, 1); | ||
988 | static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, | ||
989 | show_in_max, store_in_max, 2); | ||
990 | static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, | ||
991 | show_in_max, store_in_max, 3); | ||
992 | static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, | ||
993 | show_in_max, store_in_max, 4); | ||
994 | static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, | ||
995 | show_in_max, store_in_max, 5); | ||
996 | static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, | ||
997 | show_in_max, store_in_max, 6); | ||
998 | static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, | ||
999 | show_in_max, store_in_max, 7); | ||
1000 | static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, | ||
1001 | show_in_max, store_in_max, 8); | ||
1002 | static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0); | ||
1003 | static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0); | ||
1004 | static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0); | ||
1005 | static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, | ||
1006 | show_temp1, store_temp1, 0, 1); | ||
1007 | static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23, | ||
1008 | store_temp23, 0, 2); | ||
1009 | static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, | ||
1010 | store_temp23, 1, 2); | ||
1011 | static SENSOR_DEVICE_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, | ||
1012 | show_temp1, store_temp1, 0, 2); | ||
1013 | static SENSOR_DEVICE_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, | ||
1014 | show_temp23, store_temp23, 0, 4); | ||
1015 | static SENSOR_DEVICE_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, | ||
1016 | show_temp23, store_temp23, 1, 4); | ||
1017 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); | ||
1018 | static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); | ||
1019 | static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, | ||
1020 | show_chassis_clear, store_chassis_clear); | ||
1021 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0); | ||
1022 | static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1); | ||
1023 | static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2); | ||
1024 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, | ||
1025 | show_pwmenable, store_pwmenable, 1); | ||
1026 | static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, | ||
1027 | show_pwmenable, store_pwmenable, 2); | ||
1028 | static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, | ||
1029 | show_pwmenable, store_pwmenable, 3); | ||
1030 | static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, | ||
1031 | show_pwm_mode, store_pwm_mode, 0); | ||
1032 | static SENSOR_DEVICE_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, | ||
1033 | show_pwm_mode, store_pwm_mode, 1); | ||
1034 | static SENSOR_DEVICE_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, | ||
1035 | show_pwm_mode, store_pwm_mode, 2); | ||
1036 | static SENSOR_DEVICE_ATTR(tolerance1, S_IWUSR | S_IRUGO, | ||
1037 | show_tolerance, store_tolerance, 1); | ||
1038 | static SENSOR_DEVICE_ATTR(tolerance2, S_IWUSR | S_IRUGO, | ||
1039 | show_tolerance, store_tolerance, 2); | ||
1040 | static SENSOR_DEVICE_ATTR(tolerance3, S_IWUSR | S_IRUGO, | ||
1041 | show_tolerance, store_tolerance, 3); | ||
1042 | static SENSOR_DEVICE_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO, | ||
1043 | show_thermal_cruise, store_thermal_cruise, 1); | ||
1044 | static SENSOR_DEVICE_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO, | ||
1045 | show_thermal_cruise, store_thermal_cruise, 2); | ||
1046 | static SENSOR_DEVICE_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO, | ||
1047 | show_thermal_cruise, store_thermal_cruise, 3); | ||
1048 | static SENSOR_DEVICE_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR, | ||
1049 | show_sf2_point, store_sf2_point, 1, 1); | ||
1050 | static SENSOR_DEVICE_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR, | ||
1051 | show_sf2_point, store_sf2_point, 2, 1); | ||
1052 | static SENSOR_DEVICE_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR, | ||
1053 | show_sf2_point, store_sf2_point, 3, 1); | ||
1054 | static SENSOR_DEVICE_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR, | ||
1055 | show_sf2_point, store_sf2_point, 4, 1); | ||
1056 | static SENSOR_DEVICE_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR, | ||
1057 | show_sf2_point, store_sf2_point, 1, 2); | ||
1058 | static SENSOR_DEVICE_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR, | ||
1059 | show_sf2_point, store_sf2_point, 2, 2); | ||
1060 | static SENSOR_DEVICE_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR, | ||
1061 | show_sf2_point, store_sf2_point, 3, 2); | ||
1062 | static SENSOR_DEVICE_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR, | ||
1063 | show_sf2_point, store_sf2_point, 4, 2); | ||
1064 | static SENSOR_DEVICE_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR, | ||
1065 | show_sf2_point, store_sf2_point, 1, 3); | ||
1066 | static SENSOR_DEVICE_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR, | ||
1067 | show_sf2_point, store_sf2_point, 2, 3); | ||
1068 | static SENSOR_DEVICE_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR, | ||
1069 | show_sf2_point, store_sf2_point, 3, 3); | ||
1070 | static SENSOR_DEVICE_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR, | ||
1071 | show_sf2_point, store_sf2_point, 4, 3); | ||
1072 | static SENSOR_DEVICE_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR, | ||
1073 | show_sf2_level, store_sf2_level, 1, 1); | ||
1074 | static SENSOR_DEVICE_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR, | ||
1075 | show_sf2_level, store_sf2_level, 2, 1); | ||
1076 | static SENSOR_DEVICE_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR, | ||
1077 | show_sf2_level, store_sf2_level, 3, 1); | ||
1078 | static SENSOR_DEVICE_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR, | ||
1079 | show_sf2_level, store_sf2_level, 1, 2); | ||
1080 | static SENSOR_DEVICE_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR, | ||
1081 | show_sf2_level, store_sf2_level, 2, 2); | ||
1082 | static SENSOR_DEVICE_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR, | ||
1083 | show_sf2_level, store_sf2_level, 3, 2); | ||
1084 | static SENSOR_DEVICE_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR, | ||
1085 | show_sf2_level, store_sf2_level, 1, 3); | ||
1086 | static SENSOR_DEVICE_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR, | ||
1087 | show_sf2_level, store_sf2_level, 2, 3); | ||
1088 | static SENSOR_DEVICE_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR, | ||
1089 | show_sf2_level, store_sf2_level, 3, 3); | ||
1090 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1); | ||
1091 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2); | ||
1092 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3); | ||
1093 | static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4); | ||
1094 | static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5); | ||
1095 | static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6); | ||
1096 | static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7); | ||
1097 | static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, | ||
1098 | show_fan_min, store_fan_min, 1); | ||
1099 | static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, | ||
1100 | show_fan_min, store_fan_min, 2); | ||
1101 | static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, | ||
1102 | show_fan_min, store_fan_min, 3); | ||
1103 | static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, | ||
1104 | show_fan_min, store_fan_min, 4); | ||
1105 | static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, | ||
1106 | show_fan_min, store_fan_min, 5); | ||
1107 | static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, | ||
1108 | show_fan_min, store_fan_min, 6); | ||
1109 | static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, | ||
1110 | show_fan_min, store_fan_min, 7); | ||
1111 | static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, | ||
1112 | show_fan_div, store_fan_div, 1); | ||
1113 | static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, | ||
1114 | show_fan_div, store_fan_div, 2); | ||
1115 | static SENSOR_DEVICE_ATTR(fan3_div, S_IWUSR | S_IRUGO, | ||
1116 | show_fan_div, store_fan_div, 3); | ||
1117 | static SENSOR_DEVICE_ATTR(fan4_div, S_IWUSR | S_IRUGO, | ||
1118 | show_fan_div, store_fan_div, 4); | ||
1119 | static SENSOR_DEVICE_ATTR(fan5_div, S_IWUSR | S_IRUGO, | ||
1120 | show_fan_div, store_fan_div, 5); | ||
1121 | static SENSOR_DEVICE_ATTR(fan6_div, S_IWUSR | S_IRUGO, | ||
1122 | show_fan_div, store_fan_div, 6); | ||
1123 | static SENSOR_DEVICE_ATTR(fan7_div, S_IWUSR | S_IRUGO, | ||
1124 | show_fan_div, store_fan_div, 7); | ||
1125 | |||
1126 | static struct attribute *w83792d_attributes_fan[4][4] = { | ||
1127 | { | ||
1128 | &sensor_dev_attr_fan4_input.dev_attr.attr, | ||
1129 | &sensor_dev_attr_fan4_min.dev_attr.attr, | ||
1130 | &sensor_dev_attr_fan4_div.dev_attr.attr, | ||
1131 | NULL | ||
1132 | }, { | ||
1133 | &sensor_dev_attr_fan5_input.dev_attr.attr, | ||
1134 | &sensor_dev_attr_fan5_min.dev_attr.attr, | ||
1135 | &sensor_dev_attr_fan5_div.dev_attr.attr, | ||
1136 | NULL | ||
1137 | }, { | ||
1138 | &sensor_dev_attr_fan6_input.dev_attr.attr, | ||
1139 | &sensor_dev_attr_fan6_min.dev_attr.attr, | ||
1140 | &sensor_dev_attr_fan6_div.dev_attr.attr, | ||
1141 | NULL | ||
1142 | }, { | ||
1143 | &sensor_dev_attr_fan7_input.dev_attr.attr, | ||
1144 | &sensor_dev_attr_fan7_min.dev_attr.attr, | ||
1145 | &sensor_dev_attr_fan7_div.dev_attr.attr, | ||
1146 | NULL | ||
1147 | } | ||
1148 | }; | ||
1149 | |||
1150 | static const struct attribute_group w83792d_group_fan[4] = { | ||
1151 | { .attrs = w83792d_attributes_fan[0] }, | ||
1152 | { .attrs = w83792d_attributes_fan[1] }, | ||
1153 | { .attrs = w83792d_attributes_fan[2] }, | ||
1154 | { .attrs = w83792d_attributes_fan[3] }, | ||
1155 | }; | ||
1156 | |||
1157 | static struct attribute *w83792d_attributes[] = { | ||
1158 | &sensor_dev_attr_in0_input.dev_attr.attr, | ||
1159 | &sensor_dev_attr_in0_max.dev_attr.attr, | ||
1160 | &sensor_dev_attr_in0_min.dev_attr.attr, | ||
1161 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
1162 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
1163 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
1164 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
1165 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
1166 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
1167 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
1168 | &sensor_dev_attr_in3_max.dev_attr.attr, | ||
1169 | &sensor_dev_attr_in3_min.dev_attr.attr, | ||
1170 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
1171 | &sensor_dev_attr_in4_max.dev_attr.attr, | ||
1172 | &sensor_dev_attr_in4_min.dev_attr.attr, | ||
1173 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
1174 | &sensor_dev_attr_in5_max.dev_attr.attr, | ||
1175 | &sensor_dev_attr_in5_min.dev_attr.attr, | ||
1176 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
1177 | &sensor_dev_attr_in6_max.dev_attr.attr, | ||
1178 | &sensor_dev_attr_in6_min.dev_attr.attr, | ||
1179 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
1180 | &sensor_dev_attr_in7_max.dev_attr.attr, | ||
1181 | &sensor_dev_attr_in7_min.dev_attr.attr, | ||
1182 | &sensor_dev_attr_in8_input.dev_attr.attr, | ||
1183 | &sensor_dev_attr_in8_max.dev_attr.attr, | ||
1184 | &sensor_dev_attr_in8_min.dev_attr.attr, | ||
1185 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
1186 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
1187 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | ||
1188 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
1189 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
1190 | &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, | ||
1191 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
1192 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
1193 | &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, | ||
1194 | &sensor_dev_attr_pwm1.dev_attr.attr, | ||
1195 | &sensor_dev_attr_pwm1_mode.dev_attr.attr, | ||
1196 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
1197 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
1198 | &sensor_dev_attr_pwm2_mode.dev_attr.attr, | ||
1199 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
1200 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
1201 | &sensor_dev_attr_pwm3_mode.dev_attr.attr, | ||
1202 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
1203 | &dev_attr_alarms.attr, | ||
1204 | &dev_attr_chassis.attr, | ||
1205 | &dev_attr_chassis_clear.attr, | ||
1206 | &sensor_dev_attr_tolerance1.dev_attr.attr, | ||
1207 | &sensor_dev_attr_thermal_cruise1.dev_attr.attr, | ||
1208 | &sensor_dev_attr_tolerance2.dev_attr.attr, | ||
1209 | &sensor_dev_attr_thermal_cruise2.dev_attr.attr, | ||
1210 | &sensor_dev_attr_tolerance3.dev_attr.attr, | ||
1211 | &sensor_dev_attr_thermal_cruise3.dev_attr.attr, | ||
1212 | &sensor_dev_attr_sf2_point1_fan1.dev_attr.attr, | ||
1213 | &sensor_dev_attr_sf2_point2_fan1.dev_attr.attr, | ||
1214 | &sensor_dev_attr_sf2_point3_fan1.dev_attr.attr, | ||
1215 | &sensor_dev_attr_sf2_point4_fan1.dev_attr.attr, | ||
1216 | &sensor_dev_attr_sf2_point1_fan2.dev_attr.attr, | ||
1217 | &sensor_dev_attr_sf2_point2_fan2.dev_attr.attr, | ||
1218 | &sensor_dev_attr_sf2_point3_fan2.dev_attr.attr, | ||
1219 | &sensor_dev_attr_sf2_point4_fan2.dev_attr.attr, | ||
1220 | &sensor_dev_attr_sf2_point1_fan3.dev_attr.attr, | ||
1221 | &sensor_dev_attr_sf2_point2_fan3.dev_attr.attr, | ||
1222 | &sensor_dev_attr_sf2_point3_fan3.dev_attr.attr, | ||
1223 | &sensor_dev_attr_sf2_point4_fan3.dev_attr.attr, | ||
1224 | &sensor_dev_attr_sf2_level1_fan1.dev_attr.attr, | ||
1225 | &sensor_dev_attr_sf2_level2_fan1.dev_attr.attr, | ||
1226 | &sensor_dev_attr_sf2_level3_fan1.dev_attr.attr, | ||
1227 | &sensor_dev_attr_sf2_level1_fan2.dev_attr.attr, | ||
1228 | &sensor_dev_attr_sf2_level2_fan2.dev_attr.attr, | ||
1229 | &sensor_dev_attr_sf2_level3_fan2.dev_attr.attr, | ||
1230 | &sensor_dev_attr_sf2_level1_fan3.dev_attr.attr, | ||
1231 | &sensor_dev_attr_sf2_level2_fan3.dev_attr.attr, | ||
1232 | &sensor_dev_attr_sf2_level3_fan3.dev_attr.attr, | ||
1233 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
1234 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
1235 | &sensor_dev_attr_fan1_div.dev_attr.attr, | ||
1236 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
1237 | &sensor_dev_attr_fan2_min.dev_attr.attr, | ||
1238 | &sensor_dev_attr_fan2_div.dev_attr.attr, | ||
1239 | &sensor_dev_attr_fan3_input.dev_attr.attr, | ||
1240 | &sensor_dev_attr_fan3_min.dev_attr.attr, | ||
1241 | &sensor_dev_attr_fan3_div.dev_attr.attr, | ||
1242 | NULL | ||
1243 | }; | ||
1244 | |||
1245 | static const struct attribute_group w83792d_group = { | ||
1246 | .attrs = w83792d_attributes, | ||
1247 | }; | ||
1148 | 1248 | ||
1149 | static int | 1249 | static int |
1150 | w83792d_detect(struct i2c_adapter *adapter, int address, int kind) | 1250 | w83792d_detect(struct i2c_adapter *adapter, int address, int kind) |
@@ -1268,59 +1368,46 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1268 | } | 1368 | } |
1269 | 1369 | ||
1270 | /* Register sysfs hooks */ | 1370 | /* Register sysfs hooks */ |
1271 | data->class_dev = hwmon_device_register(dev); | 1371 | if ((err = sysfs_create_group(&dev->kobj, &w83792d_group))) |
1272 | if (IS_ERR(data->class_dev)) { | ||
1273 | err = PTR_ERR(data->class_dev); | ||
1274 | goto ERROR3; | 1372 | goto ERROR3; |
1275 | } | ||
1276 | for (i = 0; i < 9; i++) { | ||
1277 | device_create_file(dev, &sda_in_input[i].dev_attr); | ||
1278 | device_create_file(dev, &sda_in_max[i].dev_attr); | ||
1279 | device_create_file(dev, &sda_in_min[i].dev_attr); | ||
1280 | } | ||
1281 | for (i = 0; i < 3; i++) | ||
1282 | device_create_file_fan(dev, i); | ||
1283 | 1373 | ||
1284 | /* Read GPIO enable register to check if pins for fan 4,5 are used as | 1374 | /* Read GPIO enable register to check if pins for fan 4,5 are used as |
1285 | GPIO */ | 1375 | GPIO */ |
1286 | val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN); | 1376 | val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN); |
1377 | |||
1287 | if (!(val1 & 0x40)) | 1378 | if (!(val1 & 0x40)) |
1288 | device_create_file_fan(dev, 3); | 1379 | if ((err = sysfs_create_group(&dev->kobj, |
1380 | &w83792d_group_fan[0]))) | ||
1381 | goto exit_remove_files; | ||
1382 | |||
1289 | if (!(val1 & 0x20)) | 1383 | if (!(val1 & 0x20)) |
1290 | device_create_file_fan(dev, 4); | 1384 | if ((err = sysfs_create_group(&dev->kobj, |
1385 | &w83792d_group_fan[1]))) | ||
1386 | goto exit_remove_files; | ||
1291 | 1387 | ||
1292 | val1 = w83792d_read_value(client, W83792D_REG_PIN); | 1388 | val1 = w83792d_read_value(client, W83792D_REG_PIN); |
1293 | if (val1 & 0x40) | 1389 | if (val1 & 0x40) |
1294 | device_create_file_fan(dev, 5); | 1390 | if ((err = sysfs_create_group(&dev->kobj, |
1391 | &w83792d_group_fan[2]))) | ||
1392 | goto exit_remove_files; | ||
1393 | |||
1295 | if (val1 & 0x04) | 1394 | if (val1 & 0x04) |
1296 | device_create_file_fan(dev, 6); | 1395 | if ((err = sysfs_create_group(&dev->kobj, |
1297 | 1396 | &w83792d_group_fan[3]))) | |
1298 | for (i = 0; i < 3; i++) { | 1397 | goto exit_remove_files; |
1299 | device_create_file(dev, &sda_temp_input[i].dev_attr); | ||
1300 | device_create_file(dev, &sda_temp_max[i].dev_attr); | ||
1301 | device_create_file(dev, &sda_temp_max_hyst[i].dev_attr); | ||
1302 | device_create_file(dev, &sda_thermal_cruise[i].dev_attr); | ||
1303 | device_create_file(dev, &sda_tolerance[i].dev_attr); | ||
1304 | } | ||
1305 | 1398 | ||
1306 | for (i = 0; i < ARRAY_SIZE(sda_pwm); i++) { | 1399 | data->class_dev = hwmon_device_register(dev); |
1307 | device_create_file(dev, &sda_pwm[i].dev_attr); | 1400 | if (IS_ERR(data->class_dev)) { |
1308 | device_create_file(dev, &sda_pwm_enable[i].dev_attr); | 1401 | err = PTR_ERR(data->class_dev); |
1309 | device_create_file(dev, &sda_pwm_mode[i].dev_attr); | 1402 | goto exit_remove_files; |
1310 | } | 1403 | } |
1311 | 1404 | ||
1312 | device_create_file(dev, &dev_attr_alarms); | ||
1313 | device_create_file(dev, &dev_attr_chassis); | ||
1314 | device_create_file(dev, &dev_attr_chassis_clear); | ||
1315 | |||
1316 | for (i = 0; i < ARRAY_SIZE(sda_sf2_point); i++) | ||
1317 | device_create_file(dev, &sda_sf2_point[i].dev_attr); | ||
1318 | |||
1319 | for (i = 0; i < ARRAY_SIZE(sda_sf2_level); i++) | ||
1320 | device_create_file(dev, &sda_sf2_level[i].dev_attr); | ||
1321 | |||
1322 | return 0; | 1405 | return 0; |
1323 | 1406 | ||
1407 | exit_remove_files: | ||
1408 | sysfs_remove_group(&dev->kobj, &w83792d_group); | ||
1409 | for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) | ||
1410 | sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]); | ||
1324 | ERROR3: | 1411 | ERROR3: |
1325 | if (data->lm75[0] != NULL) { | 1412 | if (data->lm75[0] != NULL) { |
1326 | i2c_detach_client(data->lm75[0]); | 1413 | i2c_detach_client(data->lm75[0]); |
@@ -1342,11 +1429,16 @@ static int | |||
1342 | w83792d_detach_client(struct i2c_client *client) | 1429 | w83792d_detach_client(struct i2c_client *client) |
1343 | { | 1430 | { |
1344 | struct w83792d_data *data = i2c_get_clientdata(client); | 1431 | struct w83792d_data *data = i2c_get_clientdata(client); |
1345 | int err; | 1432 | int err, i; |
1346 | 1433 | ||
1347 | /* main client */ | 1434 | /* main client */ |
1348 | if (data) | 1435 | if (data) { |
1349 | hwmon_device_unregister(data->class_dev); | 1436 | hwmon_device_unregister(data->class_dev); |
1437 | sysfs_remove_group(&client->dev.kobj, &w83792d_group); | ||
1438 | for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) | ||
1439 | sysfs_remove_group(&client->dev.kobj, | ||
1440 | &w83792d_group_fan[i]); | ||
1441 | } | ||
1350 | 1442 | ||
1351 | if ((err = i2c_detach_client(client))) | 1443 | if ((err = i2c_detach_client(client))) |
1352 | return err; | 1444 | return err; |
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c index 3f2bac125fb1..a3fcace412f0 100644 --- a/drivers/hwmon/w83l785ts.c +++ b/drivers/hwmon/w83l785ts.c | |||
@@ -236,21 +236,30 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind) | |||
236 | * Nothing yet, assume it is already started. | 236 | * Nothing yet, assume it is already started. |
237 | */ | 237 | */ |
238 | 238 | ||
239 | err = device_create_file(&new_client->dev, | ||
240 | &sensor_dev_attr_temp1_input.dev_attr); | ||
241 | if (err) | ||
242 | goto exit_remove; | ||
243 | |||
244 | err = device_create_file(&new_client->dev, | ||
245 | &sensor_dev_attr_temp1_max.dev_attr); | ||
246 | if (err) | ||
247 | goto exit_remove; | ||
248 | |||
239 | /* Register sysfs hooks */ | 249 | /* Register sysfs hooks */ |
240 | data->class_dev = hwmon_device_register(&new_client->dev); | 250 | data->class_dev = hwmon_device_register(&new_client->dev); |
241 | if (IS_ERR(data->class_dev)) { | 251 | if (IS_ERR(data->class_dev)) { |
242 | err = PTR_ERR(data->class_dev); | 252 | err = PTR_ERR(data->class_dev); |
243 | goto exit_detach; | 253 | goto exit_remove; |
244 | } | 254 | } |
245 | 255 | ||
246 | device_create_file(&new_client->dev, | ||
247 | &sensor_dev_attr_temp1_input.dev_attr); | ||
248 | device_create_file(&new_client->dev, | ||
249 | &sensor_dev_attr_temp1_max.dev_attr); | ||
250 | |||
251 | return 0; | 256 | return 0; |
252 | 257 | ||
253 | exit_detach: | 258 | exit_remove: |
259 | device_remove_file(&new_client->dev, | ||
260 | &sensor_dev_attr_temp1_input.dev_attr); | ||
261 | device_remove_file(&new_client->dev, | ||
262 | &sensor_dev_attr_temp1_max.dev_attr); | ||
254 | i2c_detach_client(new_client); | 263 | i2c_detach_client(new_client); |
255 | exit_free: | 264 | exit_free: |
256 | kfree(data); | 265 | kfree(data); |
@@ -264,7 +273,10 @@ static int w83l785ts_detach_client(struct i2c_client *client) | |||
264 | int err; | 273 | int err; |
265 | 274 | ||
266 | hwmon_device_unregister(data->class_dev); | 275 | hwmon_device_unregister(data->class_dev); |
267 | 276 | device_remove_file(&client->dev, | |
277 | &sensor_dev_attr_temp1_input.dev_attr); | ||
278 | device_remove_file(&client->dev, | ||
279 | &sensor_dev_attr_temp1_max.dev_attr); | ||
268 | if ((err = i2c_detach_client(client))) | 280 | if ((err = i2c_detach_client(client))) |
269 | return err; | 281 | return err; |
270 | 282 | ||
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ab032ceafa84..61db1907f06f 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -479,6 +479,7 @@ | |||
479 | 479 | ||
480 | #define PCI_VENDOR_ID_AMD 0x1022 | 480 | #define PCI_VENDOR_ID_AMD 0x1022 |
481 | #define PCI_DEVICE_ID_AMD_K8_NB 0x1100 | 481 | #define PCI_DEVICE_ID_AMD_K8_NB 0x1100 |
482 | #define PCI_DEVICE_ID_AMD_K8_NB_MISC 0x1103 | ||
482 | #define PCI_DEVICE_ID_AMD_LANCE 0x2000 | 483 | #define PCI_DEVICE_ID_AMD_LANCE 0x2000 |
483 | #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 | 484 | #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 |
484 | #define PCI_DEVICE_ID_AMD_SCSI 0x2020 | 485 | #define PCI_DEVICE_ID_AMD_SCSI 0x2020 |