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