]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/hwmon/f71882fg.c
hwmon: (f71882fg) Add missing pwm3 attr for f71862fg
[net-next-2.6.git] / drivers / hwmon / f71882fg.c
CommitLineData
45fb3669
HG
1/***************************************************************************
2 * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> *
c13548c5 3 * Copyright (C) 2007,2008 by Hans de Goede <hdegoede@redhat.com> *
45fb3669
HG
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>
77a4a3e2 30#include <linux/io.h>
45fb3669
HG
31
32#define DRVNAME "f71882fg"
33
77a4a3e2 34#define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */
45fb3669
HG
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 */
498be968 46#define SIO_F71862_ID 0x0601 /* Chipset ID */
45fb3669 47#define SIO_F71882_ID 0x0541 /* Chipset ID */
ed4f7c20 48#define SIO_F8000_ID 0x0581 /* Chipset ID */
45fb3669
HG
49
50#define REGION_LENGTH 8
51#define ADDR_REG_OFFSET 5
52#define DATA_REG_OFFSET 6
53
54#define F71882FG_REG_PECI 0x0A
55
498be968
HG
56#define F71882FG_REG_IN_STATUS 0x12 /* f71882fg only */
57#define F71882FG_REG_IN_BEEP 0x13 /* f71882fg only */
45fb3669 58#define F71882FG_REG_IN(nr) (0x20 + (nr))
498be968 59#define F71882FG_REG_IN1_HIGH 0x32 /* f71882fg only */
45fb3669
HG
60
61#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr)))
9ab796eb
MD
62#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))
63#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))
45fb3669
HG
64#define F71882FG_REG_FAN_STATUS 0x92
65#define F71882FG_REG_FAN_BEEP 0x93
66
7567a043
HG
67#define F71882FG_REG_TEMP(nr) (0x70 + 2 * (nr))
68#define F71882FG_REG_TEMP_OVT(nr) (0x80 + 2 * (nr))
69#define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr))
45fb3669
HG
70#define F71882FG_REG_TEMP_STATUS 0x62
71#define F71882FG_REG_TEMP_BEEP 0x63
bc27490f 72#define F71882FG_REG_TEMP_HYST(nr) (0x6C + (nr))
45fb3669
HG
73#define F71882FG_REG_TEMP_TYPE 0x6B
74#define F71882FG_REG_TEMP_DIODE_OPEN 0x6F
75
9ab796eb
MD
76#define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr)))
77#define F71882FG_REG_PWM_TYPE 0x94
78#define F71882FG_REG_PWM_ENABLE 0x96
79
bc27490f 80#define F71882FG_REG_FAN_HYST(nr) (0x98 + (nr))
9ab796eb
MD
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
45fb3669
HG
86#define F71882FG_REG_START 0x01
87
88#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */
89
67b671bc
JD
90static unsigned short force_id;
91module_param(force_id, ushort, 0);
92MODULE_PARM_DESC(force_id, "Override the detected device ID");
93
ed4f7c20 94enum chips { f71862fg, f71882fg, f8000 };
498be968
HG
95
96static const char *f71882fg_names[] = {
97 "f71862fg",
98 "f71882fg",
ed4f7c20 99 "f8000",
498be968
HG
100};
101
77a4a3e2 102static struct platform_device *f71882fg_pdev;
45fb3669
HG
103
104/* Super-I/O Function prototypes */
105static inline int superio_inb(int base, int reg);
106static inline int superio_inw(int base, int reg);
107static inline void superio_enter(int base);
108static inline void superio_select(int base, int ld);
109static inline void superio_exit(int base);
110
498be968
HG
111struct f71882fg_sio_data {
112 enum chips type;
113};
114
45fb3669
HG
115struct f71882fg_data {
116 unsigned short addr;
498be968 117 enum chips type;
1beeffe4 118 struct device *hwmon_dev;
45fb3669
HG
119
120 struct mutex update_lock;
121 char valid; /* !=0 if following fields are valid */
122 unsigned long last_updated; /* In jiffies */
123 unsigned long last_limits; /* In jiffies */
124
125 /* Register Values */
126 u8 in[9];
127 u8 in1_max;
128 u8 in_status;
129 u8 in_beep;
130 u16 fan[4];
9ab796eb
MD
131 u16 fan_target[4];
132 u16 fan_full_speed[4];
45fb3669
HG
133 u8 fan_status;
134 u8 fan_beep;
7567a043
HG
135 /* Note: all models have only 3 temperature channels, but on some
136 they are addressed as 0-2 and on others as 1-3, so for coding
137 convenience we reserve space for 4 channels */
138 u8 temp[4];
139 u8 temp_ovt[4];
140 u8 temp_high[4];
bc27490f 141 u8 temp_hyst[2]; /* 2 hysts stored per reg */
7567a043 142 u8 temp_type[4];
45fb3669
HG
143 u8 temp_status;
144 u8 temp_beep;
145 u8 temp_diode_open;
9ab796eb
MD
146 u8 pwm[4];
147 u8 pwm_enable;
148 u8 pwm_auto_point_hyst[2];
149 u8 pwm_auto_point_mapping[4];
150 u8 pwm_auto_point_pwm[4][5];
151 u8 pwm_auto_point_temp[4][4];
45fb3669
HG
152};
153
77a4a3e2 154/* Sysfs in */
45fb3669
HG
155static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
156 char *buf);
157static ssize_t show_in_max(struct device *dev, struct device_attribute
158 *devattr, char *buf);
159static ssize_t store_in_max(struct device *dev, struct device_attribute
160 *devattr, const char *buf, size_t count);
161static ssize_t show_in_beep(struct device *dev, struct device_attribute
162 *devattr, char *buf);
163static ssize_t store_in_beep(struct device *dev, struct device_attribute
164 *devattr, const char *buf, size_t count);
165static ssize_t show_in_alarm(struct device *dev, struct device_attribute
166 *devattr, char *buf);
167/* Sysfs Fan */
168static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
169 char *buf);
9ab796eb
MD
170static ssize_t show_fan_full_speed(struct device *dev,
171 struct device_attribute *devattr, char *buf);
172static ssize_t store_fan_full_speed(struct device *dev,
173 struct device_attribute *devattr, const char *buf, size_t count);
45fb3669
HG
174static ssize_t show_fan_beep(struct device *dev, struct device_attribute
175 *devattr, char *buf);
176static ssize_t store_fan_beep(struct device *dev, struct device_attribute
177 *devattr, const char *buf, size_t count);
178static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
179 *devattr, char *buf);
180/* Sysfs Temp */
181static ssize_t show_temp(struct device *dev, struct device_attribute
182 *devattr, char *buf);
183static ssize_t show_temp_max(struct device *dev, struct device_attribute
184 *devattr, char *buf);
185static ssize_t store_temp_max(struct device *dev, struct device_attribute
186 *devattr, const char *buf, size_t count);
187static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
188 *devattr, char *buf);
189static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
190 *devattr, const char *buf, size_t count);
191static ssize_t show_temp_crit(struct device *dev, struct device_attribute
192 *devattr, char *buf);
193static ssize_t store_temp_crit(struct device *dev, struct device_attribute
194 *devattr, const char *buf, size_t count);
195static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
196 *devattr, char *buf);
197static ssize_t show_temp_type(struct device *dev, struct device_attribute
198 *devattr, char *buf);
199static ssize_t show_temp_beep(struct device *dev, struct device_attribute
200 *devattr, char *buf);
201static ssize_t store_temp_beep(struct device *dev, struct device_attribute
202 *devattr, const char *buf, size_t count);
203static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
204 *devattr, char *buf);
205static ssize_t show_temp_fault(struct device *dev, struct device_attribute
206 *devattr, char *buf);
9ab796eb
MD
207/* PWM and Auto point control */
208static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
209 char *buf);
210static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
211 const char *buf, size_t count);
212static ssize_t show_pwm_enable(struct device *dev,
213 struct device_attribute *devattr, char *buf);
214static ssize_t store_pwm_enable(struct device *dev,
215 struct device_attribute *devattr, const char *buf, size_t count);
216static ssize_t show_pwm_interpolate(struct device *dev,
217 struct device_attribute *devattr, char *buf);
218static ssize_t store_pwm_interpolate(struct device *dev,
219 struct device_attribute *devattr, const char *buf, size_t count);
220static ssize_t show_pwm_auto_point_channel(struct device *dev,
221 struct device_attribute *devattr, char *buf);
222static ssize_t store_pwm_auto_point_channel(struct device *dev,
223 struct device_attribute *devattr, const char *buf, size_t count);
224static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
225 struct device_attribute *devattr, char *buf);
226static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
227 struct device_attribute *devattr, const char *buf, size_t count);
228static ssize_t show_pwm_auto_point_pwm(struct device *dev,
229 struct device_attribute *devattr, char *buf);
230static ssize_t store_pwm_auto_point_pwm(struct device *dev,
231 struct device_attribute *devattr, const char *buf, size_t count);
232static ssize_t show_pwm_auto_point_temp(struct device *dev,
233 struct device_attribute *devattr, char *buf);
234static ssize_t store_pwm_auto_point_temp(struct device *dev,
235 struct device_attribute *devattr, const char *buf, size_t count);
45fb3669
HG
236/* Sysfs misc */
237static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
238 char *buf);
239
240static int __devinit f71882fg_probe(struct platform_device * pdev);
c13548c5 241static int f71882fg_remove(struct platform_device *pdev);
45fb3669
HG
242
243static struct platform_driver f71882fg_driver = {
244 .driver = {
245 .owner = THIS_MODULE,
246 .name = DRVNAME,
247 },
248 .probe = f71882fg_probe,
249 .remove = __devexit_p(f71882fg_remove),
250};
251
c13548c5 252static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
45fb3669 253
ed4f7c20 254/* Temp and in attr common to both the f71862fg and f71882fg */
498be968 255static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = {
bc37ae71
MD
256 SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
257 SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
bc37ae71
MD
258 SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
259 SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
260 SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
261 SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
262 SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
263 SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
264 SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
7567a043 265 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1),
bc37ae71 266 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
7567a043 267 store_temp_max, 0, 1),
bc37ae71 268 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
7567a043 269 store_temp_max_hyst, 0, 1),
754a5907
HG
270 /* Should really be temp1_max_alarm, but older versions did not handle
271 the max and crit alarms separately and lm_sensors v2 depends on the
272 presence of temp#_alarm files. The same goes for temp2/3 _alarm. */
273 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
274 SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
275 store_temp_beep, 0, 1),
bc37ae71 276 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
7567a043 277 store_temp_crit, 0, 1),
bc37ae71 278 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
7567a043 279 0, 1),
754a5907
HG
280 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
281 SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
282 store_temp_beep, 0, 5),
7567a043 283 SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1),
7567a043
HG
284 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
285 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2),
bc37ae71 286 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
7567a043 287 store_temp_max, 0, 2),
bc37ae71 288 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
7567a043 289 store_temp_max_hyst, 0, 2),
754a5907
HG
290 /* Should be temp2_max_alarm, see temp1_alarm note */
291 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
292 SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
293 store_temp_beep, 0, 2),
bc37ae71 294 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
7567a043 295 store_temp_crit, 0, 2),
bc37ae71 296 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
7567a043 297 0, 2),
754a5907
HG
298 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
299 SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
300 store_temp_beep, 0, 6),
7567a043 301 SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2),
7567a043
HG
302 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
303 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3),
bc37ae71 304 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
7567a043 305 store_temp_max, 0, 3),
bc37ae71 306 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
7567a043 307 store_temp_max_hyst, 0, 3),
754a5907
HG
308 /* Should be temp3_max_alarm, see temp1_alarm note */
309 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3),
310 SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
311 store_temp_beep, 0, 3),
bc37ae71 312 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
7567a043 313 store_temp_crit, 0, 3),
bc37ae71 314 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
7567a043 315 0, 3),
754a5907
HG
316 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7),
317 SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
318 store_temp_beep, 0, 7),
7567a043 319 SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3),
7567a043 320 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),
45fb3669
HG
321};
322
ed4f7c20 323/* Temp and in attr found only on the f71882fg */
498be968
HG
324static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = {
325 SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
326 0, 1),
327 SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
328 0, 1),
329 SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
330};
331
ed4f7c20
HG
332/* Temp and in attr for the f8000
333 Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
334 is used as hysteresis value to clear alarms
335 */
336static struct sensor_device_attribute_2 f8000_in_temp_attr[] = {
337 SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
338 SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
339 SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
340 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
341 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit,
342 store_temp_crit, 0, 0),
343 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
344 store_temp_max, 0, 0),
345 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
346 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
347 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit,
348 store_temp_crit, 0, 1),
349 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
350 store_temp_max, 0, 1),
351 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
352 SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1),
353 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
354 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit,
355 store_temp_crit, 0, 2),
356 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
357 store_temp_max, 0, 2),
358 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
359};
360
361/* Fan / PWM attr common to all models */
362static struct sensor_device_attribute_2 fxxxx_fan_attr[] = {
bc37ae71 363 SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
9ab796eb
MD
364 SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
365 show_fan_full_speed,
366 store_fan_full_speed, 0, 0),
bc37ae71
MD
367 SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),
368 SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
9ab796eb
MD
369 SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
370 show_fan_full_speed,
371 store_fan_full_speed, 0, 1),
bc37ae71
MD
372 SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
373 SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
9ab796eb
MD
374 SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
375 show_fan_full_speed,
376 store_fan_full_speed, 0, 2),
bc37ae71 377 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
9ab796eb
MD
378
379 SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
380 SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
381 store_pwm_enable, 0, 0),
382 SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,
383 show_pwm_interpolate, store_pwm_interpolate, 0, 0),
384 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
385 show_pwm_auto_point_channel,
386 store_pwm_auto_point_channel, 0, 0),
498be968
HG
387
388 SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
389 SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
390 store_pwm_enable, 0, 1),
391 SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
392 show_pwm_interpolate, store_pwm_interpolate, 0, 1),
393 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
394 show_pwm_auto_point_channel,
395 store_pwm_auto_point_channel, 0, 1),
396
498be968
HG
397 SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
398 show_pwm_interpolate, store_pwm_interpolate, 0, 2),
399 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
400 show_pwm_auto_point_channel,
401 store_pwm_auto_point_channel, 0, 2),
402};
403
ed4f7c20
HG
404/* Fan / PWM attr for the f71862fg, less pwms and less zones per pwm than the
405 f71882fg */
498be968 406static struct sensor_device_attribute_2 f71862fg_fan_attr[] = {
ed4f7c20
HG
407 SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
408 store_fan_beep, 0, 0),
409 SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
410 store_fan_beep, 0, 1),
411 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
412 store_fan_beep, 0, 2),
413
498be968
HG
414 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
415 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
416 1, 0),
417 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
418 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
419 4, 0),
420 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
421 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
422 0, 0),
423 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
424 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
425 3, 0),
426 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
427 show_pwm_auto_point_temp_hyst,
428 store_pwm_auto_point_temp_hyst,
429 0, 0),
430 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
431 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
432
433 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
434 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
435 1, 1),
436 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
437 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
438 4, 1),
439 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
440 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
441 0, 1),
442 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
443 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
444 3, 1),
445 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
446 show_pwm_auto_point_temp_hyst,
447 store_pwm_auto_point_temp_hyst,
448 0, 1),
449 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
450 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
4901062f
HG
451
452 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
453 SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
454 store_pwm_enable, 0, 2),
455 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
456 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
457 1, 2),
458 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
459 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
460 4, 2),
461 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
462 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
463 0, 2),
464 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
465 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
466 3, 2),
467 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
468 show_pwm_auto_point_temp_hyst,
469 store_pwm_auto_point_temp_hyst,
470 0, 2),
471 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
472 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
498be968
HG
473};
474
ed4f7c20 475/* Fan / PWM attr for the f71882fg */
498be968 476static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
ed4f7c20
HG
477 SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
478 store_fan_beep, 0, 0),
479 SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
480 store_fan_beep, 0, 1),
481 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
482 store_fan_beep, 0, 2),
498be968
HG
483 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
484 SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
485 show_fan_full_speed,
486 store_fan_full_speed, 0, 3),
487 SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
488 store_fan_beep, 0, 3),
489 SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
490
9ab796eb
MD
491 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
492 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
493 0, 0),
494 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
495 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
496 1, 0),
497 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
498 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
499 2, 0),
500 SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,
501 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
502 3, 0),
503 SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,
504 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
505 4, 0),
506 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
507 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
508 0, 0),
509 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
510 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
511 1, 0),
512 SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,
513 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
514 2, 0),
515 SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,
516 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
517 3, 0),
518 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
519 show_pwm_auto_point_temp_hyst,
520 store_pwm_auto_point_temp_hyst,
521 0, 0),
522 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
523 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
524 SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO,
525 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
526 SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
527 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
528
9ab796eb
MD
529 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
530 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
531 0, 1),
532 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
533 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
534 1, 1),
535 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
536 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
537 2, 1),
538 SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,
539 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
540 3, 1),
541 SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,
542 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
543 4, 1),
544 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
545 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
546 0, 1),
547 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
548 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
549 1, 1),
550 SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR,
551 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
552 2, 1),
553 SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,
554 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
555 3, 1),
556 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
557 show_pwm_auto_point_temp_hyst,
558 store_pwm_auto_point_temp_hyst,
559 0, 1),
560 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
561 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
562 SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO,
563 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
564 SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
565 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
566
ed4f7c20
HG
567 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
568 SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
569 store_pwm_enable, 0, 2),
9ab796eb
MD
570 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
571 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
572 0, 2),
573 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
574 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
575 1, 2),
576 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
577 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
578 2, 2),
579 SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR,
580 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
581 3, 2),
582 SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,
583 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
584 4, 2),
585 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
586 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
587 0, 2),
588 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
589 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
590 1, 2),
591 SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR,
592 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
593 2, 2),
594 SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR,
595 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
596 3, 2),
597 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
598 show_pwm_auto_point_temp_hyst,
599 store_pwm_auto_point_temp_hyst,
600 0, 2),
601 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
602 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
603 SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO,
604 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
605 SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
606 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
607
608 SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
609 SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
610 store_pwm_enable, 0, 3),
611 SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
612 show_pwm_interpolate, store_pwm_interpolate, 0, 3),
613 SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
614 show_pwm_auto_point_channel,
615 store_pwm_auto_point_channel, 0, 3),
616 SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,
617 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
618 0, 3),
619 SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,
620 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
621 1, 3),
622 SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,
623 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
624 2, 3),
625 SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR,
626 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
627 3, 3),
628 SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR,
629 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
630 4, 3),
631 SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,
632 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
633 0, 3),
634 SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,
635 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
636 1, 3),
637 SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,
638 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
639 2, 3),
640 SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,
641 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
642 3, 3),
643 SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
644 show_pwm_auto_point_temp_hyst,
645 store_pwm_auto_point_temp_hyst,
646 0, 3),
647 SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO,
648 show_pwm_auto_point_temp_hyst, NULL, 1, 3),
649 SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO,
650 show_pwm_auto_point_temp_hyst, NULL, 2, 3),
651 SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,
652 show_pwm_auto_point_temp_hyst, NULL, 3, 3),
45fb3669
HG
653};
654
ed4f7c20
HG
655/* Fan / PWM attr for the f8000, zones mapped to temp instead of to pwm!
656 Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
657 F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
658static struct sensor_device_attribute_2 f8000_fan_attr[] = {
659 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
660
661 SENSOR_ATTR_2(pwm3, S_IRUGO, show_pwm, NULL, 0, 2),
662
663 SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR,
664 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
665 0, 2),
666 SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR,
667 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
668 1, 2),
669 SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR,
670 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
671 2, 2),
672 SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR,
673 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
674 3, 2),
675 SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR,
676 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
677 4, 2),
678 SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR,
679 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
680 0, 2),
681 SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR,
682 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
683 1, 2),
684 SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR,
685 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
686 2, 2),
687 SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR,
688 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
689 3, 2),
690 SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
691 show_pwm_auto_point_temp_hyst,
692 store_pwm_auto_point_temp_hyst,
693 0, 2),
694 SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO,
695 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
696 SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO,
697 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
698 SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
699 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
700
701 SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR,
702 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
703 0, 0),
704 SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR,
705 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
706 1, 0),
707 SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR,
708 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
709 2, 0),
710 SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR,
711 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
712 3, 0),
713 SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR,
714 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
715 4, 0),
716 SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR,
717 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
718 0, 0),
719 SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR,
720 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
721 1, 0),
722 SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR,
723 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
724 2, 0),
725 SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR,
726 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
727 3, 0),
728 SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
729 show_pwm_auto_point_temp_hyst,
730 store_pwm_auto_point_temp_hyst,
731 0, 0),
732 SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO,
733 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
734 SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO,
735 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
736 SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
737 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
738
739 SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR,
740 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
741 0, 1),
742 SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR,
743 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
744 1, 1),
745 SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR,
746 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
747 2, 1),
748 SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR,
749 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
750 3, 1),
751 SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR,
752 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
753 4, 1),
754 SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR,
755 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
756 0, 1),
757 SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR,
758 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
759 1, 1),
760 SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR,
761 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
762 2, 1),
763 SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR,
764 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
765 3, 1),
766 SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
767 show_pwm_auto_point_temp_hyst,
768 store_pwm_auto_point_temp_hyst,
769 0, 1),
770 SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO,
771 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
772 SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO,
773 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
774 SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
775 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
776};
45fb3669
HG
777
778/* Super I/O functions */
779static inline int superio_inb(int base, int reg)
780{
781 outb(reg, base);
782 return inb(base + 1);
783}
784
785static int superio_inw(int base, int reg)
786{
787 int val;
788 outb(reg++, base);
789 val = inb(base + 1) << 8;
790 outb(reg, base);
791 val |= inb(base + 1);
792 return val;
793}
794
795static inline void superio_enter(int base)
796{
797 /* according to the datasheet the key must be send twice! */
798 outb( SIO_UNLOCK_KEY, base);
799 outb( SIO_UNLOCK_KEY, base);
800}
801
802static inline void superio_select( int base, int ld)
803{
804 outb(SIO_REG_LDSEL, base);
805 outb(ld, base + 1);
806}
807
808static inline void superio_exit(int base)
809{
810 outb(SIO_LOCK_KEY, base);
811}
812
813static inline u16 fan_from_reg(u16 reg)
814{
815 return reg ? (1500000 / reg) : 0;
816}
817
9ab796eb
MD
818static inline u16 fan_to_reg(u16 fan)
819{
820 return fan ? (1500000 / fan) : 0;
821}
822
45fb3669
HG
823static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg)
824{
825 u8 val;
826
827 outb(reg, data->addr + ADDR_REG_OFFSET);
828 val = inb(data->addr + DATA_REG_OFFSET);
829
830 return val;
831}
832
833static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg)
834{
835 u16 val;
836
837 outb(reg++, data->addr + ADDR_REG_OFFSET);
838 val = inb(data->addr + DATA_REG_OFFSET) << 8;
839 outb(reg, data->addr + ADDR_REG_OFFSET);
840 val |= inb(data->addr + DATA_REG_OFFSET);
841
842 return val;
843}
844
845static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)
846{
847 outb(reg, data->addr + ADDR_REG_OFFSET);
848 outb(val, data->addr + DATA_REG_OFFSET);
849}
850
9ab796eb
MD
851static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)
852{
853 outb(reg++, data->addr + ADDR_REG_OFFSET);
854 outb(val >> 8, data->addr + DATA_REG_OFFSET);
855 outb(reg, data->addr + ADDR_REG_OFFSET);
856 outb(val & 255, data->addr + DATA_REG_OFFSET);
857}
858
77a4a3e2 859static struct f71882fg_data *f71882fg_update_device(struct device *dev)
45fb3669
HG
860{
861 struct f71882fg_data *data = dev_get_drvdata(dev);
ed4f7c20
HG
862 int nr, reg = 0, reg2;
863 int nr_fans = (data->type == f71882fg) ? 4 : 3;
864 int nr_ins = (data->type == f8000) ? 3 : 9;
865 int temp_start = (data->type == f8000) ? 0 : 1;
45fb3669
HG
866
867 mutex_lock(&data->update_lock);
868
869 /* Update once every 60 seconds */
870 if ( time_after(jiffies, data->last_limits + 60 * HZ ) ||
871 !data->valid) {
498be968
HG
872 if (data->type == f71882fg) {
873 data->in1_max =
874 f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
875 data->in_beep =
876 f71882fg_read8(data, F71882FG_REG_IN_BEEP);
877 }
45fb3669
HG
878
879 /* Get High & boundary temps*/
ed4f7c20 880 for (nr = temp_start; nr < 3 + temp_start; nr++) {
45fb3669
HG
881 data->temp_ovt[nr] = f71882fg_read8(data,
882 F71882FG_REG_TEMP_OVT(nr));
883 data->temp_high[nr] = f71882fg_read8(data,
884 F71882FG_REG_TEMP_HIGH(nr));
885 }
886
ed4f7c20
HG
887 if (data->type != f8000) {
888 data->fan_beep = f71882fg_read8(data,
889 F71882FG_REG_FAN_BEEP);
890 data->temp_beep = f71882fg_read8(data,
891 F71882FG_REG_TEMP_BEEP);
892 data->temp_hyst[0] = f71882fg_read8(data,
893 F71882FG_REG_TEMP_HYST(0));
894 data->temp_hyst[1] = f71882fg_read8(data,
895 F71882FG_REG_TEMP_HYST(1));
896 /* Have to hardcode type, because temp1 is special */
897 reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
898 data->temp_type[2] = (reg & 0x04) ? 2 : 4;
899 data->temp_type[3] = (reg & 0x08) ? 2 : 4;
900 }
45fb3669
HG
901 reg2 = f71882fg_read8(data, F71882FG_REG_PECI);
902 if ((reg2 & 0x03) == 0x01)
7567a043 903 data->temp_type[1] = 6 /* PECI */;
45fb3669 904 else if ((reg2 & 0x03) == 0x02)
7567a043 905 data->temp_type[1] = 5 /* AMDSI */;
ed4f7c20 906 else if (data->type != f8000)
7567a043 907 data->temp_type[1] = (reg & 0x02) ? 2 : 4;
ed4f7c20
HG
908 else
909 data->temp_type[1] = 2; /* F8000 only supports BJT */
45fb3669 910
9ab796eb
MD
911 data->pwm_enable = f71882fg_read8(data,
912 F71882FG_REG_PWM_ENABLE);
bc27490f
HG
913 data->pwm_auto_point_hyst[0] =
914 f71882fg_read8(data, F71882FG_REG_FAN_HYST(0));
915 data->pwm_auto_point_hyst[1] =
916 f71882fg_read8(data, F71882FG_REG_FAN_HYST(1));
917
498be968 918 for (nr = 0; nr < nr_fans; nr++) {
9ab796eb
MD
919 data->pwm_auto_point_mapping[nr] =
920 f71882fg_read8(data,
921 F71882FG_REG_POINT_MAPPING(nr));
922
ed4f7c20 923 if (data->type != f71862fg) {
498be968
HG
924 int point;
925 for (point = 0; point < 5; point++) {
926 data->pwm_auto_point_pwm[nr][point] =
927 f71882fg_read8(data,
928 F71882FG_REG_POINT_PWM
929 (nr, point));
930 }
931 for (point = 0; point < 4; point++) {
932 data->pwm_auto_point_temp[nr][point] =
933 f71882fg_read8(data,
934 F71882FG_REG_POINT_TEMP
935 (nr, point));
936 }
937 } else {
938 data->pwm_auto_point_pwm[nr][1] =
939 f71882fg_read8(data,
940 F71882FG_REG_POINT_PWM
941 (nr, 1));
942 data->pwm_auto_point_pwm[nr][4] =
943 f71882fg_read8(data,
944 F71882FG_REG_POINT_PWM
945 (nr, 4));
946 data->pwm_auto_point_temp[nr][0] =
947 f71882fg_read8(data,
948 F71882FG_REG_POINT_TEMP
949 (nr, 0));
950 data->pwm_auto_point_temp[nr][3] =
951 f71882fg_read8(data,
952 F71882FG_REG_POINT_TEMP
953 (nr, 3));
9ab796eb
MD
954 }
955 }
45fb3669
HG
956 data->last_limits = jiffies;
957 }
958
959 /* Update every second */
8afb1049 960 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
45fb3669
HG
961 data->temp_status = f71882fg_read8(data,
962 F71882FG_REG_TEMP_STATUS);
963 data->temp_diode_open = f71882fg_read8(data,
964 F71882FG_REG_TEMP_DIODE_OPEN);
ed4f7c20 965 for (nr = temp_start; nr < 3 + temp_start; nr++)
45fb3669
HG
966 data->temp[nr] = f71882fg_read8(data,
967 F71882FG_REG_TEMP(nr));
968
969 data->fan_status = f71882fg_read8(data,
970 F71882FG_REG_FAN_STATUS);
498be968 971 for (nr = 0; nr < nr_fans; nr++) {
45fb3669
HG
972 data->fan[nr] = f71882fg_read16(data,
973 F71882FG_REG_FAN(nr));
9ab796eb
MD
974 data->fan_target[nr] =
975 f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr));
976 data->fan_full_speed[nr] =
977 f71882fg_read16(data,
978 F71882FG_REG_FAN_FULL_SPEED(nr));
979 data->pwm[nr] =
980 f71882fg_read8(data, F71882FG_REG_PWM(nr));
981 }
45fb3669 982
ed4f7c20
HG
983 /* The f8000 can monitor 1 more fan, but has no pwm for it */
984 if (data->type == f8000)
985 data->fan[3] = f71882fg_read16(data,
986 F71882FG_REG_FAN(3));
498be968
HG
987 if (data->type == f71882fg)
988 data->in_status = f71882fg_read8(data,
45fb3669 989 F71882FG_REG_IN_STATUS);
ed4f7c20 990 for (nr = 0; nr < nr_ins; nr++)
45fb3669
HG
991 data->in[nr] = f71882fg_read8(data,
992 F71882FG_REG_IN(nr));
993
994 data->last_updated = jiffies;
995 data->valid = 1;
996 }
997
998 mutex_unlock(&data->update_lock);
999
1000 return data;
1001}
1002
1003/* Sysfs Interface */
1004static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
1005 char *buf)
1006{
1007 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1008 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1009 int speed = fan_from_reg(data->fan[nr]);
1010
1011 if (speed == FAN_MIN_DETECT)
1012 speed = 0;
1013
1014 return sprintf(buf, "%d\n", speed);
1015}
1016
9ab796eb
MD
1017static ssize_t show_fan_full_speed(struct device *dev,
1018 struct device_attribute *devattr, char *buf)
1019{
1020 struct f71882fg_data *data = f71882fg_update_device(dev);
1021 int nr = to_sensor_dev_attr_2(devattr)->index;
1022 int speed = fan_from_reg(data->fan_full_speed[nr]);
1023 return sprintf(buf, "%d\n", speed);
1024}
1025
1026static ssize_t store_fan_full_speed(struct device *dev,
1027 struct device_attribute *devattr,
1028 const char *buf, size_t count)
1029{
1030 struct f71882fg_data *data = dev_get_drvdata(dev);
1031 int nr = to_sensor_dev_attr_2(devattr)->index;
1032 long val = simple_strtol(buf, NULL, 10);
1033
1034 val = SENSORS_LIMIT(val, 23, 1500000);
1035 val = fan_to_reg(val);
1036
1037 mutex_lock(&data->update_lock);
4c82c38a
HG
1038 f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val);
1039 data->fan_full_speed[nr] = val;
9ab796eb
MD
1040 mutex_unlock(&data->update_lock);
1041
1042 return count;
1043}
1044
45fb3669
HG
1045static ssize_t show_fan_beep(struct device *dev, struct device_attribute
1046 *devattr, char *buf)
1047{
1048 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1049 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1050
1051 if (data->fan_beep & (1 << nr))
1052 return sprintf(buf, "1\n");
1053 else
1054 return sprintf(buf, "0\n");
1055}
1056
1057static ssize_t store_fan_beep(struct device *dev, struct device_attribute
1058 *devattr, const char *buf, size_t count)
1059{
1060 struct f71882fg_data *data = dev_get_drvdata(dev);
bc37ae71 1061 int nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e 1062 unsigned long val = simple_strtoul(buf, NULL, 10);
45fb3669
HG
1063
1064 mutex_lock(&data->update_lock);
ce0bfa5e 1065 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
45fb3669
HG
1066 if (val)
1067 data->fan_beep |= 1 << nr;
1068 else
1069 data->fan_beep &= ~(1 << nr);
1070
1071 f71882fg_write8(data, F71882FG_REG_FAN_BEEP, data->fan_beep);
1072 mutex_unlock(&data->update_lock);
1073
1074 return count;
1075}
1076
1077static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
1078 *devattr, char *buf)
1079{
1080 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1081 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1082
1083 if (data->fan_status & (1 << nr))
1084 return sprintf(buf, "1\n");
1085 else
1086 return sprintf(buf, "0\n");
1087}
1088
1089static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
1090 char *buf)
1091{
1092 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1093 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1094
1095 return sprintf(buf, "%d\n", data->in[nr] * 8);
1096}
1097
1098static ssize_t show_in_max(struct device *dev, struct device_attribute
1099 *devattr, char *buf)
1100{
1101 struct f71882fg_data *data = f71882fg_update_device(dev);
1102
1103 return sprintf(buf, "%d\n", data->in1_max * 8);
1104}
1105
1106static ssize_t store_in_max(struct device *dev, struct device_attribute
1107 *devattr, const char *buf, size_t count)
1108{
1109 struct f71882fg_data *data = dev_get_drvdata(dev);
ce0bfa5e
HG
1110 long val = simple_strtol(buf, NULL, 10) / 8;
1111 val = SENSORS_LIMIT(val, 0, 255);
45fb3669
HG
1112
1113 mutex_lock(&data->update_lock);
1114 f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
1115 data->in1_max = val;
1116 mutex_unlock(&data->update_lock);
1117
1118 return count;
1119}
1120
1121static ssize_t show_in_beep(struct device *dev, struct device_attribute
1122 *devattr, char *buf)
1123{
1124 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1125 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1126
1127 if (data->in_beep & (1 << nr))
1128 return sprintf(buf, "1\n");
1129 else
1130 return sprintf(buf, "0\n");
1131}
1132
1133static ssize_t store_in_beep(struct device *dev, struct device_attribute
1134 *devattr, const char *buf, size_t count)
1135{
1136 struct f71882fg_data *data = dev_get_drvdata(dev);
bc37ae71 1137 int nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e 1138 unsigned long val = simple_strtoul(buf, NULL, 10);
45fb3669
HG
1139
1140 mutex_lock(&data->update_lock);
ce0bfa5e 1141 data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
45fb3669
HG
1142 if (val)
1143 data->in_beep |= 1 << nr;
1144 else
1145 data->in_beep &= ~(1 << nr);
1146
1147 f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
1148 mutex_unlock(&data->update_lock);
1149
1150 return count;
1151}
1152
1153static ssize_t show_in_alarm(struct device *dev, struct device_attribute
1154 *devattr, char *buf)
1155{
1156 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1157 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1158
1159 if (data->in_status & (1 << nr))
1160 return sprintf(buf, "1\n");
1161 else
1162 return sprintf(buf, "0\n");
1163}
1164
1165static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
1166 char *buf)
1167{
1168 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1169 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1170
1171 return sprintf(buf, "%d\n", data->temp[nr] * 1000);
1172}
1173
1174static ssize_t show_temp_max(struct device *dev, struct device_attribute
1175 *devattr, char *buf)
1176{
1177 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1178 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1179
1180 return sprintf(buf, "%d\n", data->temp_high[nr] * 1000);
1181}
1182
1183static ssize_t store_temp_max(struct device *dev, struct device_attribute
1184 *devattr, const char *buf, size_t count)
1185{
1186 struct f71882fg_data *data = dev_get_drvdata(dev);
bc37ae71 1187 int nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e
HG
1188 long val = simple_strtol(buf, NULL, 10) / 1000;
1189 val = SENSORS_LIMIT(val, 0, 255);
45fb3669
HG
1190
1191 mutex_lock(&data->update_lock);
1192 f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val);
1193 data->temp_high[nr] = val;
1194 mutex_unlock(&data->update_lock);
1195
1196 return count;
1197}
1198
1199static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
1200 *devattr, char *buf)
1201{
1202 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1203 int nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e 1204 int temp_max_hyst;
45fb3669 1205
ce0bfa5e 1206 mutex_lock(&data->update_lock);
bc27490f
HG
1207 if (nr & 1)
1208 temp_max_hyst = data->temp_hyst[nr / 2] >> 4;
1209 else
1210 temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f;
1211 temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000;
ce0bfa5e
HG
1212 mutex_unlock(&data->update_lock);
1213
1214 return sprintf(buf, "%d\n", temp_max_hyst);
45fb3669
HG
1215}
1216
1217static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
1218 *devattr, const char *buf, size_t count)
1219{
1220 struct f71882fg_data *data = dev_get_drvdata(dev);
bc37ae71 1221 int nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e 1222 long val = simple_strtol(buf, NULL, 10) / 1000;
45fb3669 1223 ssize_t ret = count;
ce0bfa5e 1224 u8 reg;
45fb3669
HG
1225
1226 mutex_lock(&data->update_lock);
1227
1228 /* convert abs to relative and check */
ce0bfa5e
HG
1229 data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr));
1230 val = SENSORS_LIMIT(val, data->temp_high[nr] - 15,
1231 data->temp_high[nr]);
45fb3669 1232 val = data->temp_high[nr] - val;
45fb3669
HG
1233
1234 /* convert value to register contents */
bc27490f
HG
1235 reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2));
1236 if (nr & 1)
1237 reg = (reg & 0x0f) | (val << 4);
1238 else
1239 reg = (reg & 0xf0) | val;
1240 f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg);
1241 data->temp_hyst[nr / 2] = reg;
45fb3669 1242
45fb3669
HG
1243 mutex_unlock(&data->update_lock);
1244 return ret;
1245}
1246
1247static ssize_t show_temp_crit(struct device *dev, struct device_attribute
1248 *devattr, char *buf)
1249{
1250 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1251 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1252
1253 return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000);
1254}
1255
1256static ssize_t store_temp_crit(struct device *dev, struct device_attribute
1257 *devattr, const char *buf, size_t count)
1258{
1259 struct f71882fg_data *data = dev_get_drvdata(dev);
bc37ae71 1260 int nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e
HG
1261 long val = simple_strtol(buf, NULL, 10) / 1000;
1262 val = SENSORS_LIMIT(val, 0, 255);
45fb3669
HG
1263
1264 mutex_lock(&data->update_lock);
1265 f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val);
1266 data->temp_ovt[nr] = val;
1267 mutex_unlock(&data->update_lock);
1268
1269 return count;
1270}
1271
1272static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
1273 *devattr, char *buf)
1274{
1275 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1276 int nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e 1277 int temp_crit_hyst;
45fb3669 1278
ce0bfa5e 1279 mutex_lock(&data->update_lock);
bc27490f
HG
1280 if (nr & 1)
1281 temp_crit_hyst = data->temp_hyst[nr / 2] >> 4;
1282 else
1283 temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f;
1284 temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000;
ce0bfa5e
HG
1285 mutex_unlock(&data->update_lock);
1286
1287 return sprintf(buf, "%d\n", temp_crit_hyst);
45fb3669
HG
1288}
1289
1290static ssize_t show_temp_type(struct device *dev, struct device_attribute
1291 *devattr, char *buf)
1292{
1293 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1294 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1295
1296 return sprintf(buf, "%d\n", data->temp_type[nr]);
1297}
1298
1299static ssize_t show_temp_beep(struct device *dev, struct device_attribute
1300 *devattr, char *buf)
1301{
1302 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1303 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669 1304
7567a043 1305 if (data->temp_beep & (1 << nr))
45fb3669
HG
1306 return sprintf(buf, "1\n");
1307 else
1308 return sprintf(buf, "0\n");
1309}
1310
1311static ssize_t store_temp_beep(struct device *dev, struct device_attribute
1312 *devattr, const char *buf, size_t count)
1313{
1314 struct f71882fg_data *data = dev_get_drvdata(dev);
bc37ae71 1315 int nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e 1316 unsigned long val = simple_strtoul(buf, NULL, 10);
45fb3669
HG
1317
1318 mutex_lock(&data->update_lock);
ce0bfa5e 1319 data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);
45fb3669 1320 if (val)
7567a043 1321 data->temp_beep |= 1 << nr;
45fb3669 1322 else
7567a043 1323 data->temp_beep &= ~(1 << nr);
45fb3669
HG
1324
1325 f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep);
1326 mutex_unlock(&data->update_lock);
1327
1328 return count;
1329}
1330
1331static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
1332 *devattr, char *buf)
1333{
1334 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1335 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669 1336
7567a043 1337 if (data->temp_status & (1 << nr))
45fb3669
HG
1338 return sprintf(buf, "1\n");
1339 else
1340 return sprintf(buf, "0\n");
1341}
1342
1343static ssize_t show_temp_fault(struct device *dev, struct device_attribute
1344 *devattr, char *buf)
1345{
1346 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1347 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669 1348
7567a043 1349 if (data->temp_diode_open & (1 << nr))
45fb3669
HG
1350 return sprintf(buf, "1\n");
1351 else
1352 return sprintf(buf, "0\n");
1353}
1354
9ab796eb
MD
1355static ssize_t show_pwm(struct device *dev,
1356 struct device_attribute *devattr, char *buf)
1357{
1358 struct f71882fg_data *data = f71882fg_update_device(dev);
1359 int val, nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e 1360 mutex_lock(&data->update_lock);
9ab796eb
MD
1361 if (data->pwm_enable & (1 << (2 * nr)))
1362 /* PWM mode */
1363 val = data->pwm[nr];
1364 else {
1365 /* RPM mode */
9ab796eb
MD
1366 val = 255 * fan_from_reg(data->fan_target[nr])
1367 / fan_from_reg(data->fan_full_speed[nr]);
9ab796eb 1368 }
ce0bfa5e 1369 mutex_unlock(&data->update_lock);
9ab796eb
MD
1370 return sprintf(buf, "%d\n", val);
1371}
1372
1373static ssize_t store_pwm(struct device *dev,
1374 struct device_attribute *devattr, const char *buf,
1375 size_t count)
1376{
ce0bfa5e 1377 struct f71882fg_data *data = dev_get_drvdata(dev);
9ab796eb
MD
1378 int nr = to_sensor_dev_attr_2(devattr)->index;
1379 long val = simple_strtol(buf, NULL, 10);
1380 val = SENSORS_LIMIT(val, 0, 255);
1381
1382 mutex_lock(&data->update_lock);
ce0bfa5e 1383 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
ed4f7c20
HG
1384 if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) ||
1385 (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) {
1386 count = -EROFS;
1387 goto leave;
1388 }
9ab796eb
MD
1389 if (data->pwm_enable & (1 << (2 * nr))) {
1390 /* PWM mode */
1391 f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
1392 data->pwm[nr] = val;
1393 } else {
1394 /* RPM mode */
ce0bfa5e
HG
1395 int target, full_speed;
1396 full_speed = f71882fg_read16(data,
1397 F71882FG_REG_FAN_FULL_SPEED(nr));
1398 target = fan_to_reg(val * fan_from_reg(full_speed) / 255);
1399 f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target);
1400 data->fan_target[nr] = target;
1401 data->fan_full_speed[nr] = full_speed;
9ab796eb 1402 }
ed4f7c20 1403leave:
9ab796eb
MD
1404 mutex_unlock(&data->update_lock);
1405
1406 return count;
1407}
1408
1409static ssize_t show_pwm_enable(struct device *dev,
1410 struct device_attribute *devattr, char *buf)
1411{
ed4f7c20 1412 int result = 0;
9ab796eb
MD
1413 struct f71882fg_data *data = f71882fg_update_device(dev);
1414 int nr = to_sensor_dev_attr_2(devattr)->index;
1415
ed4f7c20
HG
1416 switch ((data->pwm_enable >> 2 * nr) & 3) {
1417 case 0:
1418 case 1:
1419 result = 2; /* Normal auto mode */
1420 break;
1421 case 2:
1422 result = 1; /* Manual mode */
1423 break;
1424 case 3:
1425 if (data->type == f8000)
1426 result = 3; /* Thermostat mode */
1427 else
1428 result = 1; /* Manual mode */
1429 break;
1430 }
9ab796eb
MD
1431
1432 return sprintf(buf, "%d\n", result);
1433}
1434
1435static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
1436 *devattr, const char *buf, size_t count)
1437{
1438 struct f71882fg_data *data = dev_get_drvdata(dev);
1439 int nr = to_sensor_dev_attr_2(devattr)->index;
1440 long val = simple_strtol(buf, NULL, 10);
9ab796eb
MD
1441
1442 mutex_lock(&data->update_lock);
ce0bfa5e 1443 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
ed4f7c20
HG
1444 /* Special case for F8000 auto PWM mode / Thermostat mode */
1445 if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) {
1446 switch (val) {
1447 case 2:
1448 data->pwm_enable &= ~(2 << (2 * nr));
1449 break; /* Normal auto mode */
1450 case 3:
1451 data->pwm_enable |= 2 << (2 * nr);
1452 break; /* Thermostat mode */
1453 default:
1454 count = -EINVAL;
1455 goto leave;
1456 }
1457 } else {
1458 switch (val) {
1459 case 1:
1460 data->pwm_enable |= 2 << (2 * nr);
1461 break; /* Manual */
1462 case 2:
1463 data->pwm_enable &= ~(2 << (2 * nr));
1464 break; /* Normal auto mode */
1465 default:
1466 count = -EINVAL;
1467 goto leave;
1468 }
9ab796eb 1469 }
9ab796eb 1470 f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
ed4f7c20 1471leave:
9ab796eb
MD
1472 mutex_unlock(&data->update_lock);
1473
1474 return count;
1475}
1476
1477static ssize_t show_pwm_auto_point_pwm(struct device *dev,
1478 struct device_attribute *devattr,
1479 char *buf)
1480{
1481 int result;
1482 struct f71882fg_data *data = f71882fg_update_device(dev);
1483 int pwm = to_sensor_dev_attr_2(devattr)->index;
1484 int point = to_sensor_dev_attr_2(devattr)->nr;
1485
ce0bfa5e 1486 mutex_lock(&data->update_lock);
9ab796eb
MD
1487 if (data->pwm_enable & (1 << (2 * pwm))) {
1488 /* PWM mode */
1489 result = data->pwm_auto_point_pwm[pwm][point];
1490 } else {
1491 /* RPM mode */
1492 result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]);
1493 }
ce0bfa5e 1494 mutex_unlock(&data->update_lock);
9ab796eb
MD
1495
1496 return sprintf(buf, "%d\n", result);
1497}
1498
1499static ssize_t store_pwm_auto_point_pwm(struct device *dev,
1500 struct device_attribute *devattr,
1501 const char *buf, size_t count)
1502{
ce0bfa5e 1503 struct f71882fg_data *data = dev_get_drvdata(dev);
9ab796eb
MD
1504 int pwm = to_sensor_dev_attr_2(devattr)->index;
1505 int point = to_sensor_dev_attr_2(devattr)->nr;
ce0bfa5e 1506 long val = simple_strtol(buf, NULL, 10);
9ab796eb
MD
1507 val = SENSORS_LIMIT(val, 0, 255);
1508
1509 mutex_lock(&data->update_lock);
ce0bfa5e 1510 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
9ab796eb
MD
1511 if (data->pwm_enable & (1 << (2 * pwm))) {
1512 /* PWM mode */
1513 } else {
1514 /* RPM mode */
1515 if (val < 29) /* Prevent negative numbers */
1516 val = 255;
1517 else
1518 val = (255 - val) * 32 / val;
1519 }
1520 f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val);
1521 data->pwm_auto_point_pwm[pwm][point] = val;
1522 mutex_unlock(&data->update_lock);
1523
1524 return count;
1525}
1526
1527static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
1528 struct device_attribute *devattr,
1529 char *buf)
1530{
1531 int result = 0;
1532 struct f71882fg_data *data = f71882fg_update_device(dev);
1533 int nr = to_sensor_dev_attr_2(devattr)->index;
1534 int point = to_sensor_dev_attr_2(devattr)->nr;
1535
1536 mutex_lock(&data->update_lock);
bc27490f
HG
1537 if (nr & 1)
1538 result = data->pwm_auto_point_hyst[nr / 2] >> 4;
1539 else
1540 result = data->pwm_auto_point_hyst[nr / 2] & 0x0f;
9ab796eb
MD
1541 result = 1000 * (data->pwm_auto_point_temp[nr][point] - result);
1542 mutex_unlock(&data->update_lock);
1543
1544 return sprintf(buf, "%d\n", result);
1545}
1546
1547static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
1548 struct device_attribute *devattr,
1549 const char *buf, size_t count)
1550{
ce0bfa5e 1551 struct f71882fg_data *data = dev_get_drvdata(dev);
9ab796eb
MD
1552 int nr = to_sensor_dev_attr_2(devattr)->index;
1553 int point = to_sensor_dev_attr_2(devattr)->nr;
1554 long val = simple_strtol(buf, NULL, 10) / 1000;
bc27490f 1555 u8 reg;
9ab796eb
MD
1556
1557 mutex_lock(&data->update_lock);
ce0bfa5e
HG
1558 data->pwm_auto_point_temp[nr][point] =
1559 f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point));
9ab796eb
MD
1560 val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15,
1561 data->pwm_auto_point_temp[nr][point]);
1562 val = data->pwm_auto_point_temp[nr][point] - val;
1563
bc27490f
HG
1564 reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2));
1565 if (nr & 1)
1566 reg = (reg & 0x0f) | (val << 4);
1567 else
1568 reg = (reg & 0xf0) | val;
1569
1570 f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg);
1571 data->pwm_auto_point_hyst[nr / 2] = reg;
9ab796eb
MD
1572 mutex_unlock(&data->update_lock);
1573
1574 return count;
1575}
1576
1577static ssize_t show_pwm_interpolate(struct device *dev,
1578 struct device_attribute *devattr, char *buf)
1579{
1580 int result;
1581 struct f71882fg_data *data = f71882fg_update_device(dev);
1582 int nr = to_sensor_dev_attr_2(devattr)->index;
1583
1584 result = (data->pwm_auto_point_mapping[nr] >> 4) & 1;
1585
1586 return sprintf(buf, "%d\n", result);
1587}
1588
1589static ssize_t store_pwm_interpolate(struct device *dev,
1590 struct device_attribute *devattr,
1591 const char *buf, size_t count)
1592{
ce0bfa5e 1593 struct f71882fg_data *data = dev_get_drvdata(dev);
9ab796eb 1594 int nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e
HG
1595 unsigned long val = simple_strtoul(buf, NULL, 10);
1596
9ab796eb 1597 mutex_lock(&data->update_lock);
ce0bfa5e
HG
1598 data->pwm_auto_point_mapping[nr] =
1599 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
9ab796eb
MD
1600 if (val)
1601 val = data->pwm_auto_point_mapping[nr] | (1 << 4);
1602 else
1603 val = data->pwm_auto_point_mapping[nr] & (~(1 << 4));
1604 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1605 data->pwm_auto_point_mapping[nr] = val;
1606 mutex_unlock(&data->update_lock);
1607
1608 return count;
1609}
1610
1611static ssize_t show_pwm_auto_point_channel(struct device *dev,
1612 struct device_attribute *devattr,
1613 char *buf)
1614{
1615 int result;
1616 struct f71882fg_data *data = f71882fg_update_device(dev);
1617 int nr = to_sensor_dev_attr_2(devattr)->index;
1618
1619 result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - 1);
1620
1621 return sprintf(buf, "%d\n", result);
1622}
1623
1624static ssize_t store_pwm_auto_point_channel(struct device *dev,
1625 struct device_attribute *devattr,
1626 const char *buf, size_t count)
1627{
ce0bfa5e 1628 struct f71882fg_data *data = dev_get_drvdata(dev);
9ab796eb
MD
1629 int nr = to_sensor_dev_attr_2(devattr)->index;
1630 long val = simple_strtol(buf, NULL, 10);
1631 switch (val) {
1632 case 1:
1633 val = 1;
1634 break;
1635 case 2:
1636 val = 2;
1637 break;
1638 case 4:
1639 val = 3;
1640 break;
1641 default:
1642 return -EINVAL;
1643 }
1644 mutex_lock(&data->update_lock);
ce0bfa5e
HG
1645 data->pwm_auto_point_mapping[nr] =
1646 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
9ab796eb
MD
1647 val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val;
1648 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1649 data->pwm_auto_point_mapping[nr] = val;
1650 mutex_unlock(&data->update_lock);
1651
1652 return count;
1653}
1654
1655static ssize_t show_pwm_auto_point_temp(struct device *dev,
1656 struct device_attribute *devattr,
1657 char *buf)
1658{
1659 int result;
1660 struct f71882fg_data *data = f71882fg_update_device(dev);
1661 int pwm = to_sensor_dev_attr_2(devattr)->index;
1662 int point = to_sensor_dev_attr_2(devattr)->nr;
1663
1664 result = data->pwm_auto_point_temp[pwm][point];
1665 return sprintf(buf, "%d\n", 1000 * result);
1666}
1667
1668static ssize_t store_pwm_auto_point_temp(struct device *dev,
1669 struct device_attribute *devattr,
1670 const char *buf, size_t count)
1671{
ce0bfa5e 1672 struct f71882fg_data *data = dev_get_drvdata(dev);
9ab796eb
MD
1673 int pwm = to_sensor_dev_attr_2(devattr)->index;
1674 int point = to_sensor_dev_attr_2(devattr)->nr;
1675 long val = simple_strtol(buf, NULL, 10) / 1000;
1676 val = SENSORS_LIMIT(val, 0, 255);
1677
1678 mutex_lock(&data->update_lock);
1679 f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
1680 data->pwm_auto_point_temp[pwm][point] = val;
1681 mutex_unlock(&data->update_lock);
1682
1683 return count;
1684}
1685
45fb3669
HG
1686static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
1687 char *buf)
1688{
498be968
HG
1689 struct f71882fg_data *data = dev_get_drvdata(dev);
1690 return sprintf(buf, "%s\n", f71882fg_names[data->type]);
45fb3669
HG
1691}
1692
c13548c5
HG
1693static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
1694 struct sensor_device_attribute_2 *attr, int count)
1695{
1696 int err, i;
1697
1698 for (i = 0; i < count; i++) {
1699 err = device_create_file(&pdev->dev, &attr[i].dev_attr);
1700 if (err)
1701 return err;
1702 }
1703 return 0;
1704}
45fb3669 1705
c13548c5 1706static int __devinit f71882fg_probe(struct platform_device *pdev)
45fb3669
HG
1707{
1708 struct f71882fg_data *data;
498be968 1709 struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
c13548c5 1710 int err;
45fb3669
HG
1711 u8 start_reg;
1712
c13548c5
HG
1713 data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
1714 if (!data)
45fb3669
HG
1715 return -ENOMEM;
1716
1717 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
498be968 1718 data->type = sio_data->type;
45fb3669
HG
1719 mutex_init(&data->update_lock);
1720 platform_set_drvdata(pdev, data);
1721
3cc74758 1722 start_reg = f71882fg_read8(data, F71882FG_REG_START);
12d66e84
HG
1723 if (start_reg & 0x04) {
1724 dev_warn(&pdev->dev, "Hardware monitor is powered down\n");
1725 err = -ENODEV;
1726 goto exit_free;
1727 }
3cc74758
HG
1728 if (!(start_reg & 0x03)) {
1729 dev_warn(&pdev->dev, "Hardware monitoring not activated\n");
1730 err = -ENODEV;
1731 goto exit_free;
1732 }
1733
1734 /* If it is a 71862 and the fan / pwm part is enabled sanity check
1735 the pwm settings */
1736 if (data->type == f71862fg && (start_reg & 0x02)) {
1737 u8 reg = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
1738 if ((reg & 0x15) != 0x15) {
1739 dev_err(&pdev->dev,
1740 "Invalid (reserved) pwm settings: 0x%02x\n",
1741 (unsigned int)reg);
1742 err = -ENODEV;
1743 goto exit_free;
1744 }
1745 }
1746
45fb3669 1747 /* Register sysfs interface files */
c13548c5
HG
1748 err = device_create_file(&pdev->dev, &dev_attr_name);
1749 if (err)
1750 goto exit_unregister_sysfs;
45fb3669 1751
45fb3669 1752 if (start_reg & 0x01) {
ed4f7c20
HG
1753 switch (data->type) {
1754 case f71882fg:
498be968
HG
1755 err = f71882fg_create_sysfs_files(pdev,
1756 f71882fg_in_temp_attr,
1757 ARRAY_SIZE(f71882fg_in_temp_attr));
1758 if (err)
1759 goto exit_unregister_sysfs;
ed4f7c20
HG
1760 /* fall through! */
1761 case f71862fg:
1762 err = f71882fg_create_sysfs_files(pdev,
1763 f718x2fg_in_temp_attr,
1764 ARRAY_SIZE(f718x2fg_in_temp_attr));
1765 break;
1766 case f8000:
1767 err = f71882fg_create_sysfs_files(pdev,
1768 f8000_in_temp_attr,
1769 ARRAY_SIZE(f8000_in_temp_attr));
1770 break;
498be968 1771 }
ed4f7c20
HG
1772 if (err)
1773 goto exit_unregister_sysfs;
45fb3669
HG
1774 }
1775
1776 if (start_reg & 0x02) {
ed4f7c20
HG
1777 err = f71882fg_create_sysfs_files(pdev, fxxxx_fan_attr,
1778 ARRAY_SIZE(fxxxx_fan_attr));
498be968
HG
1779 if (err)
1780 goto exit_unregister_sysfs;
1781
ed4f7c20
HG
1782 switch (data->type) {
1783 case f71862fg:
498be968
HG
1784 err = f71882fg_create_sysfs_files(pdev,
1785 f71862fg_fan_attr,
1786 ARRAY_SIZE(f71862fg_fan_attr));
ed4f7c20
HG
1787 break;
1788 case f71882fg:
498be968
HG
1789 err = f71882fg_create_sysfs_files(pdev,
1790 f71882fg_fan_attr,
c13548c5 1791 ARRAY_SIZE(f71882fg_fan_attr));
ed4f7c20
HG
1792 break;
1793 case f8000:
1794 err = f71882fg_create_sysfs_files(pdev,
1795 f8000_fan_attr,
1796 ARRAY_SIZE(f8000_fan_attr));
1797 break;
498be968 1798 }
c13548c5
HG
1799 if (err)
1800 goto exit_unregister_sysfs;
45fb3669
HG
1801 }
1802
1beeffe4
TJ
1803 data->hwmon_dev = hwmon_device_register(&pdev->dev);
1804 if (IS_ERR(data->hwmon_dev)) {
1805 err = PTR_ERR(data->hwmon_dev);
c13548c5 1806 data->hwmon_dev = NULL;
45fb3669
HG
1807 goto exit_unregister_sysfs;
1808 }
1809
1810 return 0;
1811
1812exit_unregister_sysfs:
c13548c5 1813 f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
3cc74758
HG
1814 return err; /* f71882fg_remove() also frees our data */
1815exit_free:
1816 kfree(data);
45fb3669
HG
1817 return err;
1818}
1819
c13548c5 1820static int f71882fg_remove(struct platform_device *pdev)
45fb3669
HG
1821{
1822 int i;
1823 struct f71882fg_data *data = platform_get_drvdata(pdev);
1824
1825 platform_set_drvdata(pdev, NULL);
c13548c5
HG
1826 if (data->hwmon_dev)
1827 hwmon_device_unregister(data->hwmon_dev);
45fb3669 1828
ed4f7c20
HG
1829 /* Note we are not looping over all attr arrays we have as the ones
1830 below are supersets of the ones skipped. */
c13548c5 1831 device_remove_file(&pdev->dev, &dev_attr_name);
45fb3669 1832
498be968
HG
1833 for (i = 0; i < ARRAY_SIZE(f718x2fg_in_temp_attr); i++)
1834 device_remove_file(&pdev->dev,
1835 &f718x2fg_in_temp_attr[i].dev_attr);
1836
45fb3669
HG
1837 for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++)
1838 device_remove_file(&pdev->dev,
1839 &f71882fg_in_temp_attr[i].dev_attr);
1840
ed4f7c20
HG
1841 for (i = 0; i < ARRAY_SIZE(fxxxx_fan_attr); i++)
1842 device_remove_file(&pdev->dev, &fxxxx_fan_attr[i].dev_attr);
498be968 1843
45fb3669
HG
1844 for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++)
1845 device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr);
1846
ed4f7c20
HG
1847 for (i = 0; i < ARRAY_SIZE(f8000_fan_attr); i++)
1848 device_remove_file(&pdev->dev, &f8000_fan_attr[i].dev_attr);
1849
45fb3669
HG
1850 kfree(data);
1851
1852 return 0;
1853}
1854
498be968
HG
1855static int __init f71882fg_find(int sioaddr, unsigned short *address,
1856 struct f71882fg_sio_data *sio_data)
45fb3669
HG
1857{
1858 int err = -ENODEV;
1859 u16 devid;
45fb3669
HG
1860
1861 superio_enter(sioaddr);
1862
1863 devid = superio_inw(sioaddr, SIO_REG_MANID);
1864 if (devid != SIO_FINTEK_ID) {
1865 printk(KERN_INFO DRVNAME ": Not a Fintek device\n");
1866 goto exit;
1867 }
1868
67b671bc 1869 devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
498be968
HG
1870 switch (devid) {
1871 case SIO_F71862_ID:
1872 sio_data->type = f71862fg;
1873 break;
1874 case SIO_F71882_ID:
1875 sio_data->type = f71882fg;
1876 break;
ed4f7c20
HG
1877 case SIO_F8000_ID:
1878 sio_data->type = f8000;
1879 break;
498be968 1880 default:
45fb3669
HG
1881 printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n");
1882 goto exit;
1883 }
1884
1885 superio_select(sioaddr, SIO_F71882FG_LD_HWM);
8afb1049 1886 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
45fb3669
HG
1887 printk(KERN_WARNING DRVNAME ": Device not activated\n");
1888 goto exit;
1889 }
1890
1891 *address = superio_inw(sioaddr, SIO_REG_ADDR);
1892 if (*address == 0)
1893 {
1894 printk(KERN_WARNING DRVNAME ": Base address not set\n");
1895 goto exit;
1896 }
1897 *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
1898
45fb3669 1899 err = 0;
498be968
HG
1900 printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n",
1901 f71882fg_names[sio_data->type], (unsigned int)*address,
45fb3669
HG
1902 (int)superio_inb(sioaddr, SIO_REG_DEVREV));
1903exit:
1904 superio_exit(sioaddr);
1905 return err;
1906}
1907
498be968
HG
1908static int __init f71882fg_device_add(unsigned short address,
1909 const struct f71882fg_sio_data *sio_data)
45fb3669
HG
1910{
1911 struct resource res = {
1912 .start = address,
1913 .end = address + REGION_LENGTH - 1,
1914 .flags = IORESOURCE_IO,
1915 };
1916 int err;
1917
1918 f71882fg_pdev = platform_device_alloc(DRVNAME, address);
8afb1049 1919 if (!f71882fg_pdev)
45fb3669
HG
1920 return -ENOMEM;
1921
1922 res.name = f71882fg_pdev->name;
1923 err = platform_device_add_resources(f71882fg_pdev, &res, 1);
8afb1049 1924 if (err) {
45fb3669
HG
1925 printk(KERN_ERR DRVNAME ": Device resource addition failed\n");
1926 goto exit_device_put;
1927 }
1928
498be968
HG
1929 err = platform_device_add_data(f71882fg_pdev, sio_data,
1930 sizeof(struct f71882fg_sio_data));
1931 if (err) {
1932 printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
1933 goto exit_device_put;
1934 }
1935
45fb3669 1936 err = platform_device_add(f71882fg_pdev);
8afb1049 1937 if (err) {
45fb3669
HG
1938 printk(KERN_ERR DRVNAME ": Device addition failed\n");
1939 goto exit_device_put;
1940 }
1941
1942 return 0;
1943
1944exit_device_put:
1945 platform_device_put(f71882fg_pdev);
1946
1947 return err;
1948}
1949
1950static int __init f71882fg_init(void)
1951{
1952 int err = -ENODEV;
1953 unsigned short address;
498be968
HG
1954 struct f71882fg_sio_data sio_data;
1955
1956 memset(&sio_data, 0, sizeof(sio_data));
45fb3669 1957
498be968
HG
1958 if (f71882fg_find(0x2e, &address, &sio_data) &&
1959 f71882fg_find(0x4e, &address, &sio_data))
45fb3669
HG
1960 goto exit;
1961
c13548c5
HG
1962 err = platform_driver_register(&f71882fg_driver);
1963 if (err)
45fb3669
HG
1964 goto exit;
1965
498be968 1966 err = f71882fg_device_add(address, &sio_data);
c13548c5 1967 if (err)
45fb3669
HG
1968 goto exit_driver;
1969
1970 return 0;
1971
1972exit_driver:
1973 platform_driver_unregister(&f71882fg_driver);
1974exit:
1975 return err;
1976}
1977
1978static void __exit f71882fg_exit(void)
1979{
1980 platform_device_unregister(f71882fg_pdev);
1981 platform_driver_unregister(&f71882fg_driver);
1982}
1983
1984MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");
c13548c5 1985MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)");
45fb3669
HG
1986MODULE_LICENSE("GPL");
1987
1988module_init(f71882fg_init);
1989module_exit(f71882fg_exit);