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