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