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