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