593ed2a0555c8c87cd2d772f5e8bc6728bd88763
[safe/jmp/linux-2.6] / drivers / hwmon / f71882fg.c
1 /***************************************************************************
2  *   Copyright (C) 2006 by Hans Edgington <hans@edgington.nl>              *
3  *   Copyright (C) 2007,2008 by Hans de Goede <hdegoede@redhat.com>        *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 #include <linux/module.h>
22 #include <linux/init.h>
23 #include <linux/slab.h>
24 #include <linux/jiffies.h>
25 #include <linux/platform_device.h>
26 #include <linux/hwmon.h>
27 #include <linux/hwmon-sysfs.h>
28 #include <linux/err.h>
29 #include <linux/mutex.h>
30 #include <linux/io.h>
31
32 #define DRVNAME "f71882fg"
33
34 #define SIO_F71882FG_LD_HWM     0x04    /* Hardware monitor logical device */
35 #define SIO_UNLOCK_KEY          0x87    /* Key to enable Super-I/O */
36 #define SIO_LOCK_KEY            0xAA    /* Key to diasble Super-I/O */
37
38 #define SIO_REG_LDSEL           0x07    /* Logical device select */
39 #define SIO_REG_DEVID           0x20    /* Device ID (2 bytes) */
40 #define SIO_REG_DEVREV          0x22    /* Device revision */
41 #define SIO_REG_MANID           0x23    /* Fintek ID (2 bytes) */
42 #define SIO_REG_ENABLE          0x30    /* Logical device enable */
43 #define SIO_REG_ADDR            0x60    /* Logical device address (2 bytes) */
44
45 #define SIO_FINTEK_ID           0x1934  /* Manufacturers ID */
46 #define SIO_F71882_ID           0x0541  /* Chipset ID */
47
48 #define REGION_LENGTH           8
49 #define ADDR_REG_OFFSET         5
50 #define DATA_REG_OFFSET         6
51
52 #define F71882FG_REG_PECI               0x0A
53
54 #define F71882FG_REG_IN_STATUS          0x12
55 #define F71882FG_REG_IN_BEEP            0x13
56 #define F71882FG_REG_IN(nr)             (0x20  + (nr))
57 #define F71882FG_REG_IN1_HIGH           0x32
58
59 #define F71882FG_REG_FAN(nr)            (0xA0 + (16 * (nr)))
60 #define F71882FG_REG_FAN_TARGET(nr)     (0xA2 + (16 * (nr)))
61 #define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))
62 #define F71882FG_REG_FAN_STATUS         0x92
63 #define F71882FG_REG_FAN_BEEP           0x93
64
65 #define F71882FG_REG_TEMP(nr)           (0x72 + 2 * (nr))
66 #define F71882FG_REG_TEMP_OVT(nr)       (0x82 + 2 * (nr))
67 #define F71882FG_REG_TEMP_HIGH(nr)      (0x83 + 2 * (nr))
68 #define F71882FG_REG_TEMP_STATUS        0x62
69 #define F71882FG_REG_TEMP_BEEP          0x63
70 #define F71882FG_REG_TEMP_HYST1         0x6C
71 #define F71882FG_REG_TEMP_HYST23        0x6D
72 #define F71882FG_REG_TEMP_TYPE          0x6B
73 #define F71882FG_REG_TEMP_DIODE_OPEN    0x6F
74
75 #define F71882FG_REG_PWM(nr)            (0xA3 + (16 * (nr)))
76 #define F71882FG_REG_PWM_TYPE           0x94
77 #define F71882FG_REG_PWM_ENABLE         0x96
78
79 #define F71882FG_REG_FAN_HYST0          0x98
80 #define F71882FG_REG_FAN_HYST1          0x99
81
82 #define F71882FG_REG_POINT_PWM(pwm, point)      (0xAA + (point) + (16 * (pwm)))
83 #define F71882FG_REG_POINT_TEMP(pwm, point)     (0xA6 + (point) + (16 * (pwm)))
84 #define F71882FG_REG_POINT_MAPPING(nr)          (0xAF + 16 * (nr))
85
86 #define F71882FG_REG_START              0x01
87
88 #define FAN_MIN_DETECT                  366 /* Lowest detectable fanspeed */
89
90 static unsigned short force_id;
91 module_param(force_id, ushort, 0);
92 MODULE_PARM_DESC(force_id, "Override the detected device ID");
93
94 static int fan_mode[4] = { 0, 0, 0, 0 };
95 module_param_array(fan_mode, int, NULL, 0644);
96 MODULE_PARM_DESC(fan_mode, "List of fan control modes (f71882fg only) "
97                  "(0=don't change, 1=pwm, 2=rpm)\n"
98                  "Note: this needs a write to pwm#_enable to take effect");
99
100 static struct platform_device *f71882fg_pdev;
101
102 /* Super-I/O Function prototypes */
103 static inline int superio_inb(int base, int reg);
104 static inline int superio_inw(int base, int reg);
105 static inline void superio_enter(int base);
106 static inline void superio_select(int base, int ld);
107 static inline void superio_exit(int base);
108
109 struct f71882fg_data {
110         unsigned short addr;
111         struct device *hwmon_dev;
112
113         struct mutex update_lock;
114         char valid;                     /* !=0 if following fields are valid */
115         unsigned long last_updated;     /* In jiffies */
116         unsigned long last_limits;      /* In jiffies */
117
118         /* Register Values */
119         u8      in[9];
120         u8      in1_max;
121         u8      in_status;
122         u8      in_beep;
123         u16     fan[4];
124         u16     fan_target[4];
125         u16     fan_full_speed[4];
126         u8      fan_status;
127         u8      fan_beep;
128         u8      temp[3];
129         u8      temp_ovt[3];
130         u8      temp_high[3];
131         u8      temp_hyst[3];
132         u8      temp_type[3];
133         u8      temp_status;
134         u8      temp_beep;
135         u8      temp_diode_open;
136         u8      pwm[4];
137         u8      pwm_enable;
138         u8      pwm_auto_point_hyst[2];
139         u8      pwm_auto_point_mapping[4];
140         u8      pwm_auto_point_pwm[4][5];
141         u8      pwm_auto_point_temp[4][4];
142 };
143
144 /* Sysfs in */
145 static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
146         char *buf);
147 static ssize_t show_in_max(struct device *dev, struct device_attribute
148         *devattr, char *buf);
149 static ssize_t store_in_max(struct device *dev, struct device_attribute
150         *devattr, const char *buf, size_t count);
151 static ssize_t show_in_beep(struct device *dev, struct device_attribute
152         *devattr, char *buf);
153 static ssize_t store_in_beep(struct device *dev, struct device_attribute
154         *devattr, const char *buf, size_t count);
155 static ssize_t show_in_alarm(struct device *dev, struct device_attribute
156         *devattr, char *buf);
157 /* Sysfs Fan */
158 static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
159         char *buf);
160 static ssize_t show_fan_full_speed(struct device *dev,
161         struct device_attribute *devattr, char *buf);
162 static ssize_t store_fan_full_speed(struct device *dev,
163         struct device_attribute *devattr, const char *buf, size_t count);
164 static ssize_t show_fan_beep(struct device *dev, struct device_attribute
165         *devattr, char *buf);
166 static ssize_t store_fan_beep(struct device *dev, struct device_attribute
167         *devattr, const char *buf, size_t count);
168 static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
169         *devattr, char *buf);
170 /* Sysfs Temp */
171 static ssize_t show_temp(struct device *dev, struct device_attribute
172         *devattr, char *buf);
173 static ssize_t show_temp_max(struct device *dev, struct device_attribute
174         *devattr, char *buf);
175 static ssize_t store_temp_max(struct device *dev, struct device_attribute
176         *devattr, const char *buf, size_t count);
177 static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
178         *devattr, char *buf);
179 static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
180         *devattr, const char *buf, size_t count);
181 static ssize_t show_temp_crit(struct device *dev, struct device_attribute
182         *devattr, char *buf);
183 static ssize_t store_temp_crit(struct device *dev, struct device_attribute
184         *devattr, const char *buf, size_t count);
185 static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
186         *devattr, char *buf);
187 static ssize_t show_temp_type(struct device *dev, struct device_attribute
188         *devattr, char *buf);
189 static ssize_t show_temp_beep(struct device *dev, struct device_attribute
190         *devattr, char *buf);
191 static ssize_t store_temp_beep(struct device *dev, struct device_attribute
192         *devattr, const char *buf, size_t count);
193 static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
194         *devattr, char *buf);
195 static ssize_t show_temp_fault(struct device *dev, struct device_attribute
196         *devattr, char *buf);
197 /* PWM and Auto point control */
198 static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
199         char *buf);
200 static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
201         const char *buf, size_t count);
202 static ssize_t show_pwm_enable(struct device *dev,
203         struct device_attribute *devattr, char *buf);
204 static ssize_t store_pwm_enable(struct device *dev,
205         struct device_attribute *devattr, const char *buf, size_t count);
206 static ssize_t show_pwm_interpolate(struct device *dev,
207         struct device_attribute *devattr, char *buf);
208 static ssize_t store_pwm_interpolate(struct device *dev,
209         struct device_attribute *devattr, const char *buf, size_t count);
210 static ssize_t show_pwm_auto_point_channel(struct device *dev,
211         struct device_attribute *devattr, char *buf);
212 static ssize_t store_pwm_auto_point_channel(struct device *dev,
213         struct device_attribute *devattr, const char *buf, size_t count);
214 static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
215         struct device_attribute *devattr, char *buf);
216 static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
217         struct device_attribute *devattr, const char *buf, size_t count);
218 static ssize_t show_pwm_auto_point_pwm(struct device *dev,
219         struct device_attribute *devattr, char *buf);
220 static ssize_t store_pwm_auto_point_pwm(struct device *dev,
221         struct device_attribute *devattr, const char *buf, size_t count);
222 static ssize_t show_pwm_auto_point_temp(struct device *dev,
223         struct device_attribute *devattr, char *buf);
224 static ssize_t store_pwm_auto_point_temp(struct device *dev,
225         struct device_attribute *devattr, const char *buf, size_t count);
226 /* Sysfs misc */
227 static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
228         char *buf);
229
230 static int __devinit f71882fg_probe(struct platform_device * pdev);
231 static int f71882fg_remove(struct platform_device *pdev);
232
233 static struct platform_driver f71882fg_driver = {
234         .driver = {
235                 .owner  = THIS_MODULE,
236                 .name   = DRVNAME,
237         },
238         .probe          = f71882fg_probe,
239         .remove         = __devexit_p(f71882fg_remove),
240 };
241
242 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
243
244 static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = {
245         SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
246         SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
247         SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
248                 0, 1),
249         SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
250                 0, 1),
251         SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
252         SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
253         SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
254         SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
255         SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
256         SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
257         SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
258         SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
259         SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
260         SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
261                 store_temp_max, 0, 0),
262         SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
263                 store_temp_max_hyst, 0, 0),
264         SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
265                 store_temp_crit, 0, 0),
266         SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
267                 0, 0),
268         SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 0),
269         SENSOR_ATTR_2(temp1_beep, S_IRUGO|S_IWUSR, show_temp_beep,
270                 store_temp_beep, 0, 0),
271         SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 0),
272         SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
273         SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
274         SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
275                 store_temp_max, 0, 1),
276         SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
277                 store_temp_max_hyst, 0, 1),
278         SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
279                 store_temp_crit, 0, 1),
280         SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
281                 0, 1),
282         SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1),
283         SENSOR_ATTR_2(temp2_beep, S_IRUGO|S_IWUSR, show_temp_beep,
284                 store_temp_beep, 0, 1),
285         SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
286         SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
287         SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
288         SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
289                 store_temp_max, 0, 2),
290         SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
291                 store_temp_max_hyst, 0, 2),
292         SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
293                 store_temp_crit, 0, 2),
294         SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
295                 0, 2),
296         SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 2),
297         SENSOR_ATTR_2(temp3_beep, S_IRUGO|S_IWUSR, show_temp_beep,
298                 store_temp_beep, 0, 2),
299         SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
300         SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
301 };
302
303 static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
304         SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
305         SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
306                       show_fan_full_speed,
307                       store_fan_full_speed, 0, 0),
308         SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
309                 store_fan_beep, 0, 0),
310         SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),
311         SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
312         SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
313                       show_fan_full_speed,
314                       store_fan_full_speed, 0, 1),
315         SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
316                 store_fan_beep, 0, 1),
317         SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
318         SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
319         SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
320                       show_fan_full_speed,
321                       store_fan_full_speed, 0, 2),
322         SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
323                 store_fan_beep, 0, 2),
324         SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
325         SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
326         SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
327                       show_fan_full_speed,
328                       store_fan_full_speed, 0, 3),
329         SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
330                 store_fan_beep, 0, 3),
331         SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
332
333         SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
334         SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
335                       store_pwm_enable, 0, 0),
336         SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,
337                       show_pwm_interpolate, store_pwm_interpolate, 0, 0),
338         SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
339                       show_pwm_auto_point_channel,
340                       store_pwm_auto_point_channel, 0, 0),
341         SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
342                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
343                       0, 0),
344         SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
345                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
346                       1, 0),
347         SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
348                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
349                       2, 0),
350         SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,
351                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
352                       3, 0),
353         SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,
354                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
355                       4, 0),
356         SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
357                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
358                       0, 0),
359         SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
360                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
361                       1, 0),
362         SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,
363                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
364                       2, 0),
365         SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,
366                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
367                       3, 0),
368         SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
369                       show_pwm_auto_point_temp_hyst,
370                       store_pwm_auto_point_temp_hyst,
371                       0, 0),
372         SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
373                       show_pwm_auto_point_temp_hyst, NULL, 1, 0),
374         SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO,
375                       show_pwm_auto_point_temp_hyst, NULL, 2, 0),
376         SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
377                       show_pwm_auto_point_temp_hyst, NULL, 3, 0),
378
379         SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
380         SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
381                       store_pwm_enable, 0, 1),
382         SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
383                       show_pwm_interpolate, store_pwm_interpolate, 0, 1),
384         SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
385                       show_pwm_auto_point_channel,
386                       store_pwm_auto_point_channel, 0, 1),
387         SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
388                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
389                       0, 1),
390         SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
391                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
392                       1, 1),
393         SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
394                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
395                       2, 1),
396         SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,
397                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
398                       3, 1),
399         SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,
400                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
401                       4, 1),
402         SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
403                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
404                       0, 1),
405         SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
406                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
407                       1, 1),
408         SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR,
409                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
410                       2, 1),
411         SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,
412                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
413                       3, 1),
414         SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
415                       show_pwm_auto_point_temp_hyst,
416                       store_pwm_auto_point_temp_hyst,
417                       0, 1),
418         SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
419                       show_pwm_auto_point_temp_hyst, NULL, 1, 1),
420         SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO,
421                       show_pwm_auto_point_temp_hyst, NULL, 2, 1),
422         SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
423                       show_pwm_auto_point_temp_hyst, NULL, 3, 1),
424
425         SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
426         SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
427                       store_pwm_enable, 0, 2),
428         SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
429                       show_pwm_interpolate, store_pwm_interpolate, 0, 2),
430         SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
431                       show_pwm_auto_point_channel,
432                       store_pwm_auto_point_channel, 0, 2),
433         SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
434                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
435                       0, 2),
436         SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
437                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
438                       1, 2),
439         SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
440                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
441                       2, 2),
442         SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR,
443                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
444                       3, 2),
445         SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,
446                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
447                       4, 2),
448         SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
449                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
450                       0, 2),
451         SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
452                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
453                       1, 2),
454         SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR,
455                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
456                       2, 2),
457         SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR,
458                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
459                       3, 2),
460         SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
461                       show_pwm_auto_point_temp_hyst,
462                       store_pwm_auto_point_temp_hyst,
463                       0, 2),
464         SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
465                       show_pwm_auto_point_temp_hyst, NULL, 1, 2),
466         SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO,
467                       show_pwm_auto_point_temp_hyst, NULL, 2, 2),
468         SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
469                       show_pwm_auto_point_temp_hyst, NULL, 3, 2),
470
471         SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
472         SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
473                       store_pwm_enable, 0, 3),
474         SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
475                       show_pwm_interpolate, store_pwm_interpolate, 0, 3),
476         SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
477                       show_pwm_auto_point_channel,
478                       store_pwm_auto_point_channel, 0, 3),
479         SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,
480                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
481                       0, 3),
482         SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,
483                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
484                       1, 3),
485         SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,
486                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
487                       2, 3),
488         SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR,
489                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
490                       3, 3),
491         SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR,
492                       show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
493                       4, 3),
494         SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,
495                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
496                       0, 3),
497         SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,
498                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
499                       1, 3),
500         SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,
501                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
502                       2, 3),
503         SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,
504                       show_pwm_auto_point_temp, store_pwm_auto_point_temp,
505                       3, 3),
506         SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
507                       show_pwm_auto_point_temp_hyst,
508                       store_pwm_auto_point_temp_hyst,
509                       0, 3),
510         SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO,
511                       show_pwm_auto_point_temp_hyst, NULL, 1, 3),
512         SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO,
513                       show_pwm_auto_point_temp_hyst, NULL, 2, 3),
514         SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,
515                       show_pwm_auto_point_temp_hyst, NULL, 3, 3),
516 };
517
518
519 /* Super I/O functions */
520 static inline int superio_inb(int base, int reg)
521 {
522         outb(reg, base);
523         return inb(base + 1);
524 }
525
526 static int superio_inw(int base, int reg)
527 {
528         int val;
529         outb(reg++, base);
530         val = inb(base + 1) << 8;
531         outb(reg, base);
532         val |= inb(base + 1);
533         return val;
534 }
535
536 static inline void superio_enter(int base)
537 {
538         /* according to the datasheet the key must be send twice! */
539         outb( SIO_UNLOCK_KEY, base);
540         outb( SIO_UNLOCK_KEY, base);
541 }
542
543 static inline void superio_select( int base, int ld)
544 {
545         outb(SIO_REG_LDSEL, base);
546         outb(ld, base + 1);
547 }
548
549 static inline void superio_exit(int base)
550 {
551         outb(SIO_LOCK_KEY, base);
552 }
553
554 static inline u16 fan_from_reg(u16 reg)
555 {
556         return reg ? (1500000 / reg) : 0;
557 }
558
559 static inline u16 fan_to_reg(u16 fan)
560 {
561         return fan ? (1500000 / fan) : 0;
562 }
563
564 static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg)
565 {
566         u8 val;
567
568         outb(reg, data->addr + ADDR_REG_OFFSET);
569         val = inb(data->addr + DATA_REG_OFFSET);
570
571         return val;
572 }
573
574 static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg)
575 {
576         u16 val;
577
578         outb(reg++, data->addr + ADDR_REG_OFFSET);
579         val = inb(data->addr + DATA_REG_OFFSET) << 8;
580         outb(reg, data->addr + ADDR_REG_OFFSET);
581         val |= inb(data->addr + DATA_REG_OFFSET);
582
583         return val;
584 }
585
586 static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)
587 {
588         outb(reg, data->addr + ADDR_REG_OFFSET);
589         outb(val, data->addr + DATA_REG_OFFSET);
590 }
591
592 static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)
593 {
594         outb(reg++, data->addr + ADDR_REG_OFFSET);
595         outb(val >> 8, data->addr + DATA_REG_OFFSET);
596         outb(reg, data->addr + ADDR_REG_OFFSET);
597         outb(val & 255, data->addr + DATA_REG_OFFSET);
598 }
599
600 static struct f71882fg_data *f71882fg_update_device(struct device *dev)
601 {
602         struct f71882fg_data *data = dev_get_drvdata(dev);
603         int nr, reg, reg2;
604
605         mutex_lock(&data->update_lock);
606
607         /* Update once every 60 seconds */
608         if ( time_after(jiffies, data->last_limits + 60 * HZ ) ||
609                         !data->valid) {
610                 data->in1_max = f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
611                 data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
612
613                 /* Get High & boundary temps*/
614                 for (nr = 0; nr < 3; nr++) {
615                         data->temp_ovt[nr] = f71882fg_read8(data,
616                                                 F71882FG_REG_TEMP_OVT(nr));
617                         data->temp_high[nr] = f71882fg_read8(data,
618                                                 F71882FG_REG_TEMP_HIGH(nr));
619                 }
620
621                 /* Have to hardcode hyst*/
622                 data->temp_hyst[0] = f71882fg_read8(data,
623                                                 F71882FG_REG_TEMP_HYST1) >> 4;
624                 /* Hyst temps 2 & 3 stored in same register */
625                 reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST23);
626                 data->temp_hyst[1] = reg & 0x0F;
627                 data->temp_hyst[2] = reg >> 4;
628
629                 /* Have to hardcode type, because temp1 is special */
630                 reg  = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
631                 reg2 = f71882fg_read8(data, F71882FG_REG_PECI);
632                 if ((reg2 & 0x03) == 0x01)
633                         data->temp_type[0] = 6 /* PECI */;
634                 else if ((reg2 & 0x03) == 0x02)
635                         data->temp_type[0] = 5 /* AMDSI */;
636                 else
637                         data->temp_type[0] = (reg & 0x02) ? 2 : 4;
638
639                 data->temp_type[1] = (reg & 0x04) ? 2 : 4;
640                 data->temp_type[2] = (reg & 0x08) ? 2 : 4;
641
642                 data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);
643
644                 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
645
646                 data->pwm_enable = f71882fg_read8(data,
647                                                   F71882FG_REG_PWM_ENABLE);
648                 data->pwm_auto_point_hyst[0] = f71882fg_read8(data,
649                                                       F71882FG_REG_FAN_HYST0);
650                 data->pwm_auto_point_hyst[1] = f71882fg_read8(data,
651                                                       F71882FG_REG_FAN_HYST1);
652                 for (nr = 0; nr < 4; nr++) {
653                         int point;
654
655                         data->pwm_auto_point_mapping[nr] =
656                             f71882fg_read8(data,
657                                            F71882FG_REG_POINT_MAPPING(nr));
658
659                         for (point = 0; point < 5; point++) {
660                                 data->pwm_auto_point_pwm[nr][point] =
661                                     f71882fg_read8(data,
662                                                    F71882FG_REG_POINT_PWM
663                                                    (nr, point));
664                         }
665                         for (point = 0; point < 4; point++) {
666                                 data->pwm_auto_point_temp[nr][point] =
667                                     f71882fg_read8(data,
668                                                    F71882FG_REG_POINT_TEMP
669                                                    (nr, point));
670                         }
671                 }
672                 data->last_limits = jiffies;
673         }
674
675         /* Update every second */
676         if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
677                 data->temp_status = f71882fg_read8(data,
678                                                 F71882FG_REG_TEMP_STATUS);
679                 data->temp_diode_open = f71882fg_read8(data,
680                                                 F71882FG_REG_TEMP_DIODE_OPEN);
681                 for (nr = 0; nr < 3; nr++)
682                         data->temp[nr] = f71882fg_read8(data,
683                                                 F71882FG_REG_TEMP(nr));
684
685                 data->fan_status = f71882fg_read8(data,
686                                                 F71882FG_REG_FAN_STATUS);
687                 for (nr = 0; nr < 4; nr++) {
688                         data->fan[nr] = f71882fg_read16(data,
689                                                 F71882FG_REG_FAN(nr));
690                         data->fan_target[nr] =
691                             f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr));
692                         data->fan_full_speed[nr] =
693                             f71882fg_read16(data,
694                                             F71882FG_REG_FAN_FULL_SPEED(nr));
695                         data->pwm[nr] =
696                             f71882fg_read8(data, F71882FG_REG_PWM(nr));
697                 }
698
699                 data->in_status = f71882fg_read8(data,
700                                                 F71882FG_REG_IN_STATUS);
701                 for (nr = 0; nr < 9; nr++)
702                         data->in[nr] = f71882fg_read8(data,
703                                                 F71882FG_REG_IN(nr));
704
705                 data->last_updated = jiffies;
706                 data->valid = 1;
707         }
708
709         mutex_unlock(&data->update_lock);
710
711         return data;
712 }
713
714 /* Sysfs Interface */
715 static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
716         char *buf)
717 {
718         struct f71882fg_data *data = f71882fg_update_device(dev);
719         int nr = to_sensor_dev_attr_2(devattr)->index;
720         int speed = fan_from_reg(data->fan[nr]);
721
722         if (speed == FAN_MIN_DETECT)
723                 speed = 0;
724
725         return sprintf(buf, "%d\n", speed);
726 }
727
728 static ssize_t show_fan_full_speed(struct device *dev,
729                                    struct device_attribute *devattr, char *buf)
730 {
731         struct f71882fg_data *data = f71882fg_update_device(dev);
732         int nr = to_sensor_dev_attr_2(devattr)->index;
733         int speed = fan_from_reg(data->fan_full_speed[nr]);
734         return sprintf(buf, "%d\n", speed);
735 }
736
737 static ssize_t store_fan_full_speed(struct device *dev,
738                                     struct device_attribute *devattr,
739                                     const char *buf, size_t count)
740 {
741         struct f71882fg_data *data = dev_get_drvdata(dev);
742         int nr = to_sensor_dev_attr_2(devattr)->index;
743         long val = simple_strtol(buf, NULL, 10);
744
745         val = SENSORS_LIMIT(val, 23, 1500000);
746         val = fan_to_reg(val);
747
748         mutex_lock(&data->update_lock);
749         if (data->pwm_enable & (1 << (2 * nr)))
750                 /* PWM mode */
751                 count = -EINVAL;
752         else {
753                 /* RPM mode */
754                 f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val);
755                 data->fan_full_speed[nr] = val;
756         }
757         mutex_unlock(&data->update_lock);
758
759         return count;
760 }
761
762 static ssize_t show_fan_beep(struct device *dev, struct device_attribute
763         *devattr, char *buf)
764 {
765         struct f71882fg_data *data = f71882fg_update_device(dev);
766         int nr = to_sensor_dev_attr_2(devattr)->index;
767
768         if (data->fan_beep & (1 << nr))
769                 return sprintf(buf, "1\n");
770         else
771                 return sprintf(buf, "0\n");
772 }
773
774 static ssize_t store_fan_beep(struct device *dev, struct device_attribute
775         *devattr, const char *buf, size_t count)
776 {
777         struct f71882fg_data *data = dev_get_drvdata(dev);
778         int nr = to_sensor_dev_attr_2(devattr)->index;
779         int val = simple_strtoul(buf, NULL, 10);
780
781         mutex_lock(&data->update_lock);
782         if (val)
783                 data->fan_beep |= 1 << nr;
784         else
785                 data->fan_beep &= ~(1 << nr);
786
787         f71882fg_write8(data, F71882FG_REG_FAN_BEEP, data->fan_beep);
788         mutex_unlock(&data->update_lock);
789
790         return count;
791 }
792
793 static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
794         *devattr, char *buf)
795 {
796         struct f71882fg_data *data = f71882fg_update_device(dev);
797         int nr = to_sensor_dev_attr_2(devattr)->index;
798
799         if (data->fan_status & (1 << nr))
800                 return sprintf(buf, "1\n");
801         else
802                 return sprintf(buf, "0\n");
803 }
804
805 static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
806         char *buf)
807 {
808         struct f71882fg_data *data = f71882fg_update_device(dev);
809         int nr = to_sensor_dev_attr_2(devattr)->index;
810
811         return sprintf(buf, "%d\n", data->in[nr] * 8);
812 }
813
814 static ssize_t show_in_max(struct device *dev, struct device_attribute
815         *devattr, char *buf)
816 {
817         struct f71882fg_data *data = f71882fg_update_device(dev);
818
819         return sprintf(buf, "%d\n", data->in1_max * 8);
820 }
821
822 static ssize_t store_in_max(struct device *dev, struct device_attribute
823         *devattr, const char *buf, size_t count)
824 {
825         struct f71882fg_data *data = dev_get_drvdata(dev);
826         int val = simple_strtoul(buf, NULL, 10) / 8;
827
828         if (val > 255)
829                 val = 255;
830
831         mutex_lock(&data->update_lock);
832         f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
833         data->in1_max = val;
834         mutex_unlock(&data->update_lock);
835
836         return count;
837 }
838
839 static ssize_t show_in_beep(struct device *dev, struct device_attribute
840         *devattr, char *buf)
841 {
842         struct f71882fg_data *data = f71882fg_update_device(dev);
843         int nr = to_sensor_dev_attr_2(devattr)->index;
844
845         if (data->in_beep & (1 << nr))
846                 return sprintf(buf, "1\n");
847         else
848                 return sprintf(buf, "0\n");
849 }
850
851 static ssize_t store_in_beep(struct device *dev, struct device_attribute
852         *devattr, const char *buf, size_t count)
853 {
854         struct f71882fg_data *data = dev_get_drvdata(dev);
855         int nr = to_sensor_dev_attr_2(devattr)->index;
856         int val = simple_strtoul(buf, NULL, 10);
857
858         mutex_lock(&data->update_lock);
859         if (val)
860                 data->in_beep |= 1 << nr;
861         else
862                 data->in_beep &= ~(1 << nr);
863
864         f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
865         mutex_unlock(&data->update_lock);
866
867         return count;
868 }
869
870 static ssize_t show_in_alarm(struct device *dev, struct device_attribute
871         *devattr, char *buf)
872 {
873         struct f71882fg_data *data = f71882fg_update_device(dev);
874         int nr = to_sensor_dev_attr_2(devattr)->index;
875
876         if (data->in_status & (1 << nr))
877                 return sprintf(buf, "1\n");
878         else
879                 return sprintf(buf, "0\n");
880 }
881
882 static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
883         char *buf)
884 {
885         struct f71882fg_data *data = f71882fg_update_device(dev);
886         int nr = to_sensor_dev_attr_2(devattr)->index;
887
888         return sprintf(buf, "%d\n", data->temp[nr] * 1000);
889 }
890
891 static ssize_t show_temp_max(struct device *dev, struct device_attribute
892         *devattr, char *buf)
893 {
894         struct f71882fg_data *data = f71882fg_update_device(dev);
895         int nr = to_sensor_dev_attr_2(devattr)->index;
896
897         return sprintf(buf, "%d\n", data->temp_high[nr] * 1000);
898 }
899
900 static ssize_t store_temp_max(struct device *dev, struct device_attribute
901         *devattr, const char *buf, size_t count)
902 {
903         struct f71882fg_data *data = dev_get_drvdata(dev);
904         int nr = to_sensor_dev_attr_2(devattr)->index;
905         int val = simple_strtoul(buf, NULL, 10) / 1000;
906
907         if (val > 255)
908                 val = 255;
909
910         mutex_lock(&data->update_lock);
911         f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val);
912         data->temp_high[nr] = val;
913         mutex_unlock(&data->update_lock);
914
915         return count;
916 }
917
918 static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
919         *devattr, char *buf)
920 {
921         struct f71882fg_data *data = f71882fg_update_device(dev);
922         int nr = to_sensor_dev_attr_2(devattr)->index;
923
924         return sprintf(buf, "%d\n",
925                 (data->temp_high[nr] - data->temp_hyst[nr]) * 1000);
926 }
927
928 static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
929         *devattr, const char *buf, size_t count)
930 {
931         struct f71882fg_data *data = dev_get_drvdata(dev);
932         int nr = to_sensor_dev_attr_2(devattr)->index;
933         int val = simple_strtoul(buf, NULL, 10) / 1000;
934         ssize_t ret = count;
935
936         mutex_lock(&data->update_lock);
937
938         /* convert abs to relative and check */
939         val = data->temp_high[nr] - val;
940         if (val < 0 || val > 15) {
941                 ret = -EINVAL;
942                 goto store_temp_max_hyst_exit;
943         }
944
945         data->temp_hyst[nr] = val;
946
947         /* convert value to register contents */
948         switch (nr) {
949                 case 0:
950                         val = val << 4;
951                         break;
952                 case 1:
953                         val = val | (data->temp_hyst[2] << 4);
954                         break;
955                 case 2:
956                         val = data->temp_hyst[1] | (val << 4);
957                         break;
958         }
959
960         f71882fg_write8(data, nr ? F71882FG_REG_TEMP_HYST23 :
961                 F71882FG_REG_TEMP_HYST1, val);
962
963 store_temp_max_hyst_exit:
964         mutex_unlock(&data->update_lock);
965         return ret;
966 }
967
968 static ssize_t show_temp_crit(struct device *dev, struct device_attribute
969         *devattr, char *buf)
970 {
971         struct f71882fg_data *data = f71882fg_update_device(dev);
972         int nr = to_sensor_dev_attr_2(devattr)->index;
973
974         return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000);
975 }
976
977 static ssize_t store_temp_crit(struct device *dev, struct device_attribute
978         *devattr, const char *buf, size_t count)
979 {
980         struct f71882fg_data *data = dev_get_drvdata(dev);
981         int nr = to_sensor_dev_attr_2(devattr)->index;
982         int val = simple_strtoul(buf, NULL, 10) / 1000;
983
984         if (val > 255)
985                 val = 255;
986
987         mutex_lock(&data->update_lock);
988         f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val);
989         data->temp_ovt[nr] = val;
990         mutex_unlock(&data->update_lock);
991
992         return count;
993 }
994
995 static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
996         *devattr, char *buf)
997 {
998         struct f71882fg_data *data = f71882fg_update_device(dev);
999         int nr = to_sensor_dev_attr_2(devattr)->index;
1000
1001         return sprintf(buf, "%d\n",
1002                 (data->temp_ovt[nr] - data->temp_hyst[nr]) * 1000);
1003 }
1004
1005 static ssize_t show_temp_type(struct device *dev, struct device_attribute
1006         *devattr, char *buf)
1007 {
1008         struct f71882fg_data *data = f71882fg_update_device(dev);
1009         int nr = to_sensor_dev_attr_2(devattr)->index;
1010
1011         return sprintf(buf, "%d\n", data->temp_type[nr]);
1012 }
1013
1014 static ssize_t show_temp_beep(struct device *dev, struct device_attribute
1015         *devattr, char *buf)
1016 {
1017         struct f71882fg_data *data = f71882fg_update_device(dev);
1018         int nr = to_sensor_dev_attr_2(devattr)->index;
1019
1020         if (data->temp_beep & (1 << (nr + 1)))
1021                 return sprintf(buf, "1\n");
1022         else
1023                 return sprintf(buf, "0\n");
1024 }
1025
1026 static ssize_t store_temp_beep(struct device *dev, struct device_attribute
1027         *devattr, const char *buf, size_t count)
1028 {
1029         struct f71882fg_data *data = dev_get_drvdata(dev);
1030         int nr = to_sensor_dev_attr_2(devattr)->index;
1031         int val = simple_strtoul(buf, NULL, 10);
1032
1033         mutex_lock(&data->update_lock);
1034         if (val)
1035                 data->temp_beep |= 1 << (nr + 1);
1036         else
1037                 data->temp_beep &= ~(1 << (nr + 1));
1038
1039         f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep);
1040         mutex_unlock(&data->update_lock);
1041
1042         return count;
1043 }
1044
1045 static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
1046         *devattr, char *buf)
1047 {
1048         struct f71882fg_data *data = f71882fg_update_device(dev);
1049         int nr = to_sensor_dev_attr_2(devattr)->index;
1050
1051         if (data->temp_status & (1 << (nr + 1)))
1052                 return sprintf(buf, "1\n");
1053         else
1054                 return sprintf(buf, "0\n");
1055 }
1056
1057 static ssize_t show_temp_fault(struct device *dev, struct device_attribute
1058         *devattr, char *buf)
1059 {
1060         struct f71882fg_data *data = f71882fg_update_device(dev);
1061         int nr = to_sensor_dev_attr_2(devattr)->index;
1062
1063         if (data->temp_diode_open & (1 << (nr + 1)))
1064                 return sprintf(buf, "1\n");
1065         else
1066                 return sprintf(buf, "0\n");
1067 }
1068
1069 static ssize_t show_pwm(struct device *dev,
1070                         struct device_attribute *devattr, char *buf)
1071 {
1072         struct f71882fg_data *data = f71882fg_update_device(dev);
1073         int val, nr = to_sensor_dev_attr_2(devattr)->index;
1074         if (data->pwm_enable & (1 << (2 * nr)))
1075                 /* PWM mode */
1076                 val = data->pwm[nr];
1077         else {
1078                 /* RPM mode */
1079                 mutex_lock(&data->update_lock);
1080                 val = 255 * fan_from_reg(data->fan_target[nr])
1081                         / fan_from_reg(data->fan_full_speed[nr]);
1082                 mutex_unlock(&data->update_lock);
1083         }
1084         return sprintf(buf, "%d\n", val);
1085 }
1086
1087 static ssize_t store_pwm(struct device *dev,
1088                          struct device_attribute *devattr, const char *buf,
1089                          size_t count)
1090 {
1091         /* struct f71882fg_data *data = dev_get_drvdata(dev); */
1092         struct f71882fg_data *data = f71882fg_update_device(dev);
1093         int nr = to_sensor_dev_attr_2(devattr)->index;
1094         long val = simple_strtol(buf, NULL, 10);
1095         val = SENSORS_LIMIT(val, 0, 255);
1096
1097         mutex_lock(&data->update_lock);
1098         if (data->pwm_enable & (1 << (2 * nr))) {
1099                 /* PWM mode */
1100                 f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
1101                 data->pwm[nr] = val;
1102         } else {
1103                 /* RPM mode */
1104                 int target = val * fan_from_reg(data->fan_full_speed[nr]) / 255;
1105                 f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr),
1106                                  fan_to_reg(target));
1107                 data->fan_target[nr] = fan_to_reg(target);
1108         }
1109         mutex_unlock(&data->update_lock);
1110
1111         return count;
1112 }
1113
1114 static ssize_t show_pwm_enable(struct device *dev,
1115                                struct device_attribute *devattr, char *buf)
1116 {
1117         int result;
1118         struct f71882fg_data *data = f71882fg_update_device(dev);
1119         int nr = to_sensor_dev_attr_2(devattr)->index;
1120
1121         if (data->pwm_enable & (2 << (2 * nr)))
1122                 result = 1;
1123         else
1124                 result = 2;
1125
1126         return sprintf(buf, "%d\n", result);
1127 }
1128
1129 static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
1130                                 *devattr, const char *buf, size_t count)
1131 {
1132         struct f71882fg_data *data = dev_get_drvdata(dev);
1133         int nr = to_sensor_dev_attr_2(devattr)->index;
1134         long val = simple_strtol(buf, NULL, 10);
1135         if (val < 1 || val > 2)
1136                 return -EINVAL;
1137
1138         mutex_lock(&data->update_lock);
1139         switch (val) {
1140         case 1:
1141                 data->pwm_enable |= 2 << (2 * nr);
1142                 break;          /* Manual */
1143         case 2:
1144                 data->pwm_enable &= ~(2 << (2 * nr));
1145                 break;          /* Temperature ctrl */
1146         }
1147         switch (fan_mode[nr]) {
1148         case 1:
1149                 data->pwm_enable |= 1 << (2 * nr);
1150                 break;          /* Duty cycle mode */
1151         case 2:
1152                 data->pwm_enable &= ~(1 << (2 * nr));
1153                 break;          /* RPM mode */
1154         }
1155         f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
1156         mutex_unlock(&data->update_lock);
1157
1158         return count;
1159 }
1160
1161 static ssize_t show_pwm_auto_point_pwm(struct device *dev,
1162                                        struct device_attribute *devattr,
1163                                        char *buf)
1164 {
1165         int result;
1166         struct f71882fg_data *data = f71882fg_update_device(dev);
1167         int pwm = to_sensor_dev_attr_2(devattr)->index;
1168         int point = to_sensor_dev_attr_2(devattr)->nr;
1169
1170         if (data->pwm_enable & (1 << (2 * pwm))) {
1171                 /* PWM mode */
1172                 result = data->pwm_auto_point_pwm[pwm][point];
1173         } else {
1174                 /* RPM mode */
1175                 result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]);
1176         }
1177
1178         return sprintf(buf, "%d\n", result);
1179 }
1180
1181 static ssize_t store_pwm_auto_point_pwm(struct device *dev,
1182                                         struct device_attribute *devattr,
1183                                         const char *buf, size_t count)
1184 {
1185         /* struct f71882fg_data *data = dev_get_drvdata(dev); */
1186         struct f71882fg_data *data = f71882fg_update_device(dev);
1187         int pwm = to_sensor_dev_attr_2(devattr)->index;
1188         int point = to_sensor_dev_attr_2(devattr)->nr;
1189         int val = simple_strtoul(buf, NULL, 10);
1190         val = SENSORS_LIMIT(val, 0, 255);
1191
1192         mutex_lock(&data->update_lock);
1193         if (data->pwm_enable & (1 << (2 * pwm))) {
1194                 /* PWM mode */
1195         } else {
1196                 /* RPM mode */
1197                 if (val < 29)   /* Prevent negative numbers */
1198                         val = 255;
1199                 else
1200                         val = (255 - val) * 32 / val;
1201         }
1202         f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val);
1203         data->pwm_auto_point_pwm[pwm][point] = val;
1204         mutex_unlock(&data->update_lock);
1205
1206         return count;
1207 }
1208
1209 static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
1210                                              struct device_attribute *devattr,
1211                                              char *buf)
1212 {
1213         int result = 0;
1214         struct f71882fg_data *data = f71882fg_update_device(dev);
1215         int nr = to_sensor_dev_attr_2(devattr)->index;
1216         int point = to_sensor_dev_attr_2(devattr)->nr;
1217
1218         mutex_lock(&data->update_lock);
1219         switch (nr) {
1220         case 0:
1221                 result = data->pwm_auto_point_hyst[0] & 0x0f;
1222                 break;
1223         case 1:
1224                 result = data->pwm_auto_point_hyst[0] >> 4;
1225                 break;
1226         case 2:
1227                 result = data->pwm_auto_point_hyst[1] & 0x0f;
1228                 break;
1229         case 3:
1230                 result = data->pwm_auto_point_hyst[1] >> 4;
1231                 break;
1232         }
1233         result = 1000 * (data->pwm_auto_point_temp[nr][point] - result);
1234         mutex_unlock(&data->update_lock);
1235
1236         return sprintf(buf, "%d\n", result);
1237 }
1238
1239 static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
1240                                               struct device_attribute *devattr,
1241                                               const char *buf, size_t count)
1242 {
1243         struct f71882fg_data *data = f71882fg_update_device(dev);
1244         int nr = to_sensor_dev_attr_2(devattr)->index;
1245         int point = to_sensor_dev_attr_2(devattr)->nr;
1246         long val = simple_strtol(buf, NULL, 10) / 1000;
1247
1248         mutex_lock(&data->update_lock);
1249         val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15,
1250                                 data->pwm_auto_point_temp[nr][point]);
1251         val = data->pwm_auto_point_temp[nr][point] - val;
1252
1253         switch (nr) {
1254         case 0:
1255                 val = (data->pwm_auto_point_hyst[0] & 0xf0) | val;
1256                 break;
1257         case 1:
1258                 val = (data->pwm_auto_point_hyst[0] & 0x0f) | (val << 4);
1259                 break;
1260         case 2:
1261                 val = (data->pwm_auto_point_hyst[1] & 0xf0) | val;
1262                 break;
1263         case 3:
1264                 val = (data->pwm_auto_point_hyst[1] & 0x0f) | (val << 4);
1265                 break;
1266         }
1267         if (nr == 0 || nr == 1) {
1268                 f71882fg_write8(data, F71882FG_REG_FAN_HYST0, val);
1269                 data->pwm_auto_point_hyst[0] = val;
1270         } else {
1271                 f71882fg_write8(data, F71882FG_REG_FAN_HYST1, val);
1272                 data->pwm_auto_point_hyst[1] = val;
1273         }
1274         mutex_unlock(&data->update_lock);
1275
1276         return count;
1277 }
1278
1279 static ssize_t show_pwm_interpolate(struct device *dev,
1280                                     struct device_attribute *devattr, char *buf)
1281 {
1282         int result;
1283         struct f71882fg_data *data = f71882fg_update_device(dev);
1284         int nr = to_sensor_dev_attr_2(devattr)->index;
1285
1286         result = (data->pwm_auto_point_mapping[nr] >> 4) & 1;
1287
1288         return sprintf(buf, "%d\n", result);
1289 }
1290
1291 static ssize_t store_pwm_interpolate(struct device *dev,
1292                                      struct device_attribute *devattr,
1293                                      const char *buf, size_t count)
1294 {
1295         /* struct f71882fg_data *data = dev_get_drvdata(dev); */
1296         struct f71882fg_data *data = f71882fg_update_device(dev);
1297         int nr = to_sensor_dev_attr_2(devattr)->index;
1298         int val = simple_strtoul(buf, NULL, 10);
1299         mutex_lock(&data->update_lock);
1300         if (val)
1301                 val = data->pwm_auto_point_mapping[nr] | (1 << 4);
1302         else
1303                 val = data->pwm_auto_point_mapping[nr] & (~(1 << 4));
1304         f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1305         data->pwm_auto_point_mapping[nr] = val;
1306         mutex_unlock(&data->update_lock);
1307
1308         return count;
1309 }
1310
1311 static ssize_t show_pwm_auto_point_channel(struct device *dev,
1312                                            struct device_attribute *devattr,
1313                                            char *buf)
1314 {
1315         int result;
1316         struct f71882fg_data *data = f71882fg_update_device(dev);
1317         int nr = to_sensor_dev_attr_2(devattr)->index;
1318
1319         result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - 1);
1320
1321         return sprintf(buf, "%d\n", result);
1322 }
1323
1324 static ssize_t store_pwm_auto_point_channel(struct device *dev,
1325                                             struct device_attribute *devattr,
1326                                             const char *buf, size_t count)
1327 {
1328         /* struct f71882fg_data *data = dev_get_drvdata(dev); */
1329         struct f71882fg_data *data = f71882fg_update_device(dev);
1330         int nr = to_sensor_dev_attr_2(devattr)->index;
1331         long val = simple_strtol(buf, NULL, 10);
1332         switch (val) {
1333         case 1:
1334                 val = 1;
1335                 break;
1336         case 2:
1337                 val = 2;
1338                 break;
1339         case 4:
1340                 val = 3;
1341                 break;
1342         default:
1343                 return -EINVAL;
1344         }
1345         mutex_lock(&data->update_lock);
1346         val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val;
1347         f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1348         data->pwm_auto_point_mapping[nr] = val;
1349         mutex_unlock(&data->update_lock);
1350
1351         return count;
1352 }
1353
1354 static ssize_t show_pwm_auto_point_temp(struct device *dev,
1355                                         struct device_attribute *devattr,
1356                                         char *buf)
1357 {
1358         int result;
1359         struct f71882fg_data *data = f71882fg_update_device(dev);
1360         int pwm = to_sensor_dev_attr_2(devattr)->index;
1361         int point = to_sensor_dev_attr_2(devattr)->nr;
1362
1363         result = data->pwm_auto_point_temp[pwm][point];
1364         return sprintf(buf, "%d\n", 1000 * result);
1365 }
1366
1367 static ssize_t store_pwm_auto_point_temp(struct device *dev,
1368                                          struct device_attribute *devattr,
1369                                          const char *buf, size_t count)
1370 {
1371         /* struct f71882fg_data *data = dev_get_drvdata(dev); */
1372         struct f71882fg_data *data = f71882fg_update_device(dev);
1373         int pwm = to_sensor_dev_attr_2(devattr)->index;
1374         int point = to_sensor_dev_attr_2(devattr)->nr;
1375         long val = simple_strtol(buf, NULL, 10) / 1000;
1376         val = SENSORS_LIMIT(val, 0, 255);
1377
1378         mutex_lock(&data->update_lock);
1379         f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
1380         data->pwm_auto_point_temp[pwm][point] = val;
1381         mutex_unlock(&data->update_lock);
1382
1383         return count;
1384 }
1385
1386 static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
1387         char *buf)
1388 {
1389         return sprintf(buf, DRVNAME "\n");
1390 }
1391
1392 static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
1393         struct sensor_device_attribute_2 *attr, int count)
1394 {
1395         int err, i;
1396
1397         for (i = 0; i < count; i++) {
1398                 err = device_create_file(&pdev->dev, &attr[i].dev_attr);
1399                 if (err)
1400                         return err;
1401         }
1402         return 0;
1403 }
1404
1405 static int __devinit f71882fg_probe(struct platform_device *pdev)
1406 {
1407         struct f71882fg_data *data;
1408         int err;
1409         u8 start_reg;
1410
1411         data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
1412         if (!data)
1413                 return -ENOMEM;
1414
1415         data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
1416         mutex_init(&data->update_lock);
1417         platform_set_drvdata(pdev, data);
1418
1419         /* Register sysfs interface files */
1420         err = device_create_file(&pdev->dev, &dev_attr_name);
1421         if (err)
1422                 goto exit_unregister_sysfs;
1423
1424         start_reg = f71882fg_read8(data, F71882FG_REG_START);
1425         if (start_reg & 0x01) {
1426                 err = f71882fg_create_sysfs_files(pdev, f71882fg_in_temp_attr,
1427                                         ARRAY_SIZE(f71882fg_in_temp_attr));
1428                 if (err)
1429                         goto exit_unregister_sysfs;
1430         }
1431
1432         if (start_reg & 0x02) {
1433                 err = f71882fg_create_sysfs_files(pdev, f71882fg_fan_attr,
1434                                         ARRAY_SIZE(f71882fg_fan_attr));
1435                 if (err)
1436                         goto exit_unregister_sysfs;
1437         }
1438
1439         data->hwmon_dev = hwmon_device_register(&pdev->dev);
1440         if (IS_ERR(data->hwmon_dev)) {
1441                 err = PTR_ERR(data->hwmon_dev);
1442                 data->hwmon_dev = NULL;
1443                 goto exit_unregister_sysfs;
1444         }
1445
1446         return 0;
1447
1448 exit_unregister_sysfs:
1449         f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
1450
1451         return err;
1452 }
1453
1454 static int f71882fg_remove(struct platform_device *pdev)
1455 {
1456         int i;
1457         struct f71882fg_data *data = platform_get_drvdata(pdev);
1458
1459         platform_set_drvdata(pdev, NULL);
1460         if (data->hwmon_dev)
1461                 hwmon_device_unregister(data->hwmon_dev);
1462
1463         device_remove_file(&pdev->dev, &dev_attr_name);
1464
1465         for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++)
1466                 device_remove_file(&pdev->dev,
1467                                         &f71882fg_in_temp_attr[i].dev_attr);
1468
1469         for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++)
1470                 device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr);
1471
1472         kfree(data);
1473
1474         return 0;
1475 }
1476
1477 static int __init f71882fg_find(int sioaddr, unsigned short *address)
1478 {
1479         int err = -ENODEV;
1480         u16 devid;
1481         u8 start_reg;
1482         struct f71882fg_data data;
1483
1484         superio_enter(sioaddr);
1485
1486         devid = superio_inw(sioaddr, SIO_REG_MANID);
1487         if (devid != SIO_FINTEK_ID) {
1488                 printk(KERN_INFO DRVNAME ": Not a Fintek device\n");
1489                 goto exit;
1490         }
1491
1492         devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
1493         if (devid != SIO_F71882_ID) {
1494                 printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n");
1495                 goto exit;
1496         }
1497
1498         superio_select(sioaddr, SIO_F71882FG_LD_HWM);
1499         if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
1500                 printk(KERN_WARNING DRVNAME ": Device not activated\n");
1501                 goto exit;
1502         }
1503
1504         *address = superio_inw(sioaddr, SIO_REG_ADDR);
1505         if (*address == 0)
1506         {
1507                 printk(KERN_WARNING DRVNAME ": Base address not set\n");
1508                 goto exit;
1509         }
1510         *address &= ~(REGION_LENGTH - 1);       /* Ignore 3 LSB */
1511
1512         data.addr = *address;
1513         start_reg = f71882fg_read8(&data, F71882FG_REG_START);
1514         if (!(start_reg & 0x03)) {
1515                 printk(KERN_WARNING DRVNAME
1516                         ": Hardware monitoring not activated\n");
1517                 goto exit;
1518         }
1519
1520         err = 0;
1521         printk(KERN_INFO DRVNAME ": Found F71882FG chip at %#x, revision %d\n",
1522                 (unsigned int)*address,
1523                 (int)superio_inb(sioaddr, SIO_REG_DEVREV));
1524 exit:
1525         superio_exit(sioaddr);
1526         return err;
1527 }
1528
1529 static int __init f71882fg_device_add(unsigned short address)
1530 {
1531         struct resource res = {
1532                 .start  = address,
1533                 .end    = address + REGION_LENGTH - 1,
1534                 .flags  = IORESOURCE_IO,
1535         };
1536         int err;
1537
1538         f71882fg_pdev = platform_device_alloc(DRVNAME, address);
1539         if (!f71882fg_pdev)
1540                 return -ENOMEM;
1541
1542         res.name = f71882fg_pdev->name;
1543         err = platform_device_add_resources(f71882fg_pdev, &res, 1);
1544         if (err) {
1545                 printk(KERN_ERR DRVNAME ": Device resource addition failed\n");
1546                 goto exit_device_put;
1547         }
1548
1549         err = platform_device_add(f71882fg_pdev);
1550         if (err) {
1551                 printk(KERN_ERR DRVNAME ": Device addition failed\n");
1552                 goto exit_device_put;
1553         }
1554
1555         return 0;
1556
1557 exit_device_put:
1558         platform_device_put(f71882fg_pdev);
1559
1560         return err;
1561 }
1562
1563 static int __init f71882fg_init(void)
1564 {
1565         int err = -ENODEV;
1566         unsigned short address;
1567
1568         if (f71882fg_find(0x2e, &address) && f71882fg_find(0x4e, &address))
1569                 goto exit;
1570
1571         err = platform_driver_register(&f71882fg_driver);
1572         if (err)
1573                 goto exit;
1574
1575         err = f71882fg_device_add(address);
1576         if (err)
1577                 goto exit_driver;
1578
1579         return 0;
1580
1581 exit_driver:
1582         platform_driver_unregister(&f71882fg_driver);
1583 exit:
1584         return err;
1585 }
1586
1587 static void __exit f71882fg_exit(void)
1588 {
1589         platform_device_unregister(f71882fg_pdev);
1590         platform_driver_unregister(&f71882fg_driver);
1591 }
1592
1593 MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");
1594 MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)");
1595 MODULE_LICENSE("GPL");
1596
1597 module_init(f71882fg_init);
1598 module_exit(f71882fg_exit);