hwmon/f71882fg: Add support for f71869f and f71869e
[deliverable/linux.git] / drivers / hwmon / f71882fg.c
CommitLineData
45fb3669
HG
1/***************************************************************************
2 * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> *
44c4dc52 3 * Copyright (C) 2007-2011 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
22d3b412
JP
21#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
45fb3669
HG
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/slab.h>
26#include <linux/jiffies.h>
27#include <linux/platform_device.h>
28#include <linux/hwmon.h>
29#include <linux/hwmon-sysfs.h>
30#include <linux/err.h>
31#include <linux/mutex.h>
77a4a3e2 32#include <linux/io.h>
b9acb64a 33#include <linux/acpi.h>
45fb3669
HG
34
35#define DRVNAME "f71882fg"
36
09475d32 37#define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */
77a4a3e2 38#define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */
45fb3669 39#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
14a4019d 40#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */
45fb3669
HG
41
42#define SIO_REG_LDSEL 0x07 /* Logical device select */
43#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
44#define SIO_REG_DEVREV 0x22 /* Device revision */
45#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
46#define SIO_REG_ENABLE 0x30 /* Logical device enable */
47#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
48
49#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */
09475d32 50#define SIO_F71858_ID 0x0507 /* Chipset ID */
498be968 51#define SIO_F71862_ID 0x0601 /* Chipset ID */
c11bb993 52#define SIO_F71869_ID 0x0814 /* Chipset ID */
45fb3669 53#define SIO_F71882_ID 0x0541 /* Chipset ID */
7669896f 54#define SIO_F71889_ID 0x0723 /* Chipset ID */
3cad4022 55#define SIO_F71889E_ID 0x0909 /* Chipset ID */
ed4f7c20 56#define SIO_F8000_ID 0x0581 /* Chipset ID */
45fb3669
HG
57
58#define REGION_LENGTH 8
59#define ADDR_REG_OFFSET 5
60#define DATA_REG_OFFSET 6
61
3cad4022
HG
62#define F71882FG_REG_IN_STATUS 0x12 /* f7188x only */
63#define F71882FG_REG_IN_BEEP 0x13 /* f7188x only */
45fb3669 64#define F71882FG_REG_IN(nr) (0x20 + (nr))
3cad4022 65#define F71882FG_REG_IN1_HIGH 0x32 /* f7188x only */
45fb3669
HG
66
67#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr)))
9ab796eb
MD
68#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))
69#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))
45fb3669
HG
70#define F71882FG_REG_FAN_STATUS 0x92
71#define F71882FG_REG_FAN_BEEP 0x93
72
7567a043
HG
73#define F71882FG_REG_TEMP(nr) (0x70 + 2 * (nr))
74#define F71882FG_REG_TEMP_OVT(nr) (0x80 + 2 * (nr))
75#define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr))
45fb3669
HG
76#define F71882FG_REG_TEMP_STATUS 0x62
77#define F71882FG_REG_TEMP_BEEP 0x63
09475d32 78#define F71882FG_REG_TEMP_CONFIG 0x69
bc27490f 79#define F71882FG_REG_TEMP_HYST(nr) (0x6C + (nr))
45fb3669
HG
80#define F71882FG_REG_TEMP_TYPE 0x6B
81#define F71882FG_REG_TEMP_DIODE_OPEN 0x6F
82
9ab796eb
MD
83#define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr)))
84#define F71882FG_REG_PWM_TYPE 0x94
85#define F71882FG_REG_PWM_ENABLE 0x96
86
bc27490f 87#define F71882FG_REG_FAN_HYST(nr) (0x98 + (nr))
9ab796eb 88
98f7ba19
HG
89#define F71882FG_REG_FAN_FAULT_T 0x9F
90#define F71882FG_FAN_NEG_TEMP_EN 0x20
3cad4022 91#define F71882FG_FAN_PROG_SEL 0x80
98f7ba19 92
9ab796eb
MD
93#define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm)))
94#define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm)))
95#define F71882FG_REG_POINT_MAPPING(nr) (0xAF + 16 * (nr))
96
45fb3669
HG
97#define F71882FG_REG_START 0x01
98
0bae6400
HG
99#define F71882FG_MAX_INS 9
100
45fb3669
HG
101#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */
102
67b671bc
JD
103static unsigned short force_id;
104module_param(force_id, ushort, 0);
105MODULE_PARM_DESC(force_id, "Override the detected device ID");
106
c11bb993 107enum chips { f71858fg, f71862fg, f71869, f71882fg, f71889fg, f71889ed, f8000 };
498be968
HG
108
109static const char *f71882fg_names[] = {
09475d32 110 "f71858fg",
498be968 111 "f71862fg",
c11bb993 112 "f71869", /* Both f71869f and f71869e, reg. compatible and same id */
498be968 113 "f71882fg",
7669896f 114 "f71889fg",
3cad4022 115 "f71889ed",
ed4f7c20 116 "f8000",
498be968
HG
117};
118
c11bb993 119static const char f71882fg_has_in[7][F71882FG_MAX_INS] = {
0bae6400
HG
120 { 1, 1, 1, 0, 0, 0, 0, 0, 0 }, /* f71858fg */
121 { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71862fg */
c11bb993 122 { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71869 */
0bae6400
HG
123 { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71882fg */
124 { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71889fg */
3cad4022 125 { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71889ed */
0bae6400
HG
126 { 1, 1, 1, 0, 0, 0, 0, 0, 0 }, /* f8000 */
127};
128
c11bb993 129static const char f71882fg_has_in1_alarm[7] = {
0bae6400
HG
130 0, /* f71858fg */
131 0, /* f71862fg */
c11bb993 132 0, /* f71869 */
0bae6400
HG
133 1, /* f71882fg */
134 1, /* f71889fg */
3cad4022 135 1, /* f71889ed */
0bae6400
HG
136 0, /* f8000 */
137};
138
c11bb993 139static const char f71882fg_has_beep[7] = {
78aa4f72
HG
140 0, /* f71858fg */
141 1, /* f71862fg */
c11bb993 142 1, /* f71869 */
78aa4f72
HG
143 1, /* f71882fg */
144 1, /* f71889fg */
3cad4022 145 1, /* f71889ed */
78aa4f72
HG
146 0, /* f8000 */
147};
148
77a4a3e2 149static struct platform_device *f71882fg_pdev;
45fb3669
HG
150
151/* Super-I/O Function prototypes */
152static inline int superio_inb(int base, int reg);
153static inline int superio_inw(int base, int reg);
cadb8657 154static inline int superio_enter(int base);
45fb3669
HG
155static inline void superio_select(int base, int ld);
156static inline void superio_exit(int base);
157
498be968
HG
158struct f71882fg_sio_data {
159 enum chips type;
160};
161
45fb3669
HG
162struct f71882fg_data {
163 unsigned short addr;
498be968 164 enum chips type;
1beeffe4 165 struct device *hwmon_dev;
45fb3669
HG
166
167 struct mutex update_lock;
09475d32 168 int temp_start; /* temp numbering start (0 or 1) */
45fb3669 169 char valid; /* !=0 if following fields are valid */
98f7ba19 170 char auto_point_temp_signed;
45fb3669
HG
171 unsigned long last_updated; /* In jiffies */
172 unsigned long last_limits; /* In jiffies */
173
174 /* Register Values */
0bae6400 175 u8 in[F71882FG_MAX_INS];
45fb3669
HG
176 u8 in1_max;
177 u8 in_status;
178 u8 in_beep;
179 u16 fan[4];
9ab796eb
MD
180 u16 fan_target[4];
181 u16 fan_full_speed[4];
45fb3669
HG
182 u8 fan_status;
183 u8 fan_beep;
7567a043
HG
184 /* Note: all models have only 3 temperature channels, but on some
185 they are addressed as 0-2 and on others as 1-3, so for coding
186 convenience we reserve space for 4 channels */
09475d32 187 u16 temp[4];
7567a043
HG
188 u8 temp_ovt[4];
189 u8 temp_high[4];
bc27490f 190 u8 temp_hyst[2]; /* 2 hysts stored per reg */
7567a043 191 u8 temp_type[4];
45fb3669
HG
192 u8 temp_status;
193 u8 temp_beep;
194 u8 temp_diode_open;
09475d32 195 u8 temp_config;
9ab796eb
MD
196 u8 pwm[4];
197 u8 pwm_enable;
198 u8 pwm_auto_point_hyst[2];
199 u8 pwm_auto_point_mapping[4];
200 u8 pwm_auto_point_pwm[4][5];
7669896f 201 s8 pwm_auto_point_temp[4][4];
45fb3669
HG
202};
203
77a4a3e2 204/* Sysfs in */
45fb3669
HG
205static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
206 char *buf);
207static ssize_t show_in_max(struct device *dev, struct device_attribute
208 *devattr, char *buf);
209static ssize_t store_in_max(struct device *dev, struct device_attribute
210 *devattr, const char *buf, size_t count);
211static ssize_t show_in_beep(struct device *dev, struct device_attribute
212 *devattr, char *buf);
213static ssize_t store_in_beep(struct device *dev, struct device_attribute
214 *devattr, const char *buf, size_t count);
215static ssize_t show_in_alarm(struct device *dev, struct device_attribute
216 *devattr, char *buf);
217/* Sysfs Fan */
218static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
219 char *buf);
9ab796eb
MD
220static ssize_t show_fan_full_speed(struct device *dev,
221 struct device_attribute *devattr, char *buf);
222static ssize_t store_fan_full_speed(struct device *dev,
223 struct device_attribute *devattr, const char *buf, size_t count);
45fb3669
HG
224static ssize_t show_fan_beep(struct device *dev, struct device_attribute
225 *devattr, char *buf);
226static ssize_t store_fan_beep(struct device *dev, struct device_attribute
227 *devattr, const char *buf, size_t count);
228static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
229 *devattr, char *buf);
230/* Sysfs Temp */
231static ssize_t show_temp(struct device *dev, struct device_attribute
232 *devattr, char *buf);
233static ssize_t show_temp_max(struct device *dev, struct device_attribute
234 *devattr, char *buf);
235static ssize_t store_temp_max(struct device *dev, struct device_attribute
236 *devattr, const char *buf, size_t count);
237static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
238 *devattr, char *buf);
239static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
240 *devattr, const char *buf, size_t count);
241static ssize_t show_temp_crit(struct device *dev, struct device_attribute
242 *devattr, char *buf);
243static ssize_t store_temp_crit(struct device *dev, struct device_attribute
244 *devattr, const char *buf, size_t count);
245static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
246 *devattr, char *buf);
247static ssize_t show_temp_type(struct device *dev, struct device_attribute
248 *devattr, char *buf);
249static ssize_t show_temp_beep(struct device *dev, struct device_attribute
250 *devattr, char *buf);
251static ssize_t store_temp_beep(struct device *dev, struct device_attribute
252 *devattr, const char *buf, size_t count);
253static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
254 *devattr, char *buf);
255static ssize_t show_temp_fault(struct device *dev, struct device_attribute
256 *devattr, char *buf);
9ab796eb
MD
257/* PWM and Auto point control */
258static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
259 char *buf);
260static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
261 const char *buf, size_t count);
262static ssize_t show_pwm_enable(struct device *dev,
263 struct device_attribute *devattr, char *buf);
264static ssize_t store_pwm_enable(struct device *dev,
265 struct device_attribute *devattr, const char *buf, size_t count);
266static ssize_t show_pwm_interpolate(struct device *dev,
267 struct device_attribute *devattr, char *buf);
268static ssize_t store_pwm_interpolate(struct device *dev,
269 struct device_attribute *devattr, const char *buf, size_t count);
270static ssize_t show_pwm_auto_point_channel(struct device *dev,
271 struct device_attribute *devattr, char *buf);
272static ssize_t store_pwm_auto_point_channel(struct device *dev,
273 struct device_attribute *devattr, const char *buf, size_t count);
274static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
275 struct device_attribute *devattr, char *buf);
276static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
277 struct device_attribute *devattr, const char *buf, size_t count);
278static ssize_t show_pwm_auto_point_pwm(struct device *dev,
279 struct device_attribute *devattr, char *buf);
280static ssize_t store_pwm_auto_point_pwm(struct device *dev,
281 struct device_attribute *devattr, const char *buf, size_t count);
282static ssize_t show_pwm_auto_point_temp(struct device *dev,
283 struct device_attribute *devattr, char *buf);
284static ssize_t store_pwm_auto_point_temp(struct device *dev,
285 struct device_attribute *devattr, const char *buf, size_t count);
45fb3669
HG
286/* Sysfs misc */
287static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
288 char *buf);
289
290static int __devinit f71882fg_probe(struct platform_device * pdev);
c13548c5 291static int f71882fg_remove(struct platform_device *pdev);
45fb3669
HG
292
293static struct platform_driver f71882fg_driver = {
294 .driver = {
295 .owner = THIS_MODULE,
296 .name = DRVNAME,
297 },
298 .probe = f71882fg_probe,
cd659fd0 299 .remove = f71882fg_remove,
45fb3669
HG
300};
301
c13548c5 302static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
45fb3669 303
0bae6400
HG
304/* Temp attr for the f71858fg, the f71858fg is special as it has its
305 temperature indexes start at 0 (the others start at 1) */
306static struct sensor_device_attribute_2 f71858fg_temp_attr[] = {
09475d32
HG
307 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
308 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
309 store_temp_max, 0, 0),
310 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
311 store_temp_max_hyst, 0, 0),
312 SENSOR_ATTR_2(temp1_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 0),
313 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
314 store_temp_crit, 0, 0),
315 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
316 0, 0),
317 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
318 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
319 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
320 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
321 store_temp_max, 0, 1),
322 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
323 store_temp_max_hyst, 0, 1),
324 SENSOR_ATTR_2(temp2_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
325 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
326 store_temp_crit, 0, 1),
327 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
328 0, 1),
329 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
09475d32
HG
330 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
331 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
332 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
333 store_temp_max, 0, 2),
334 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
335 store_temp_max_hyst, 0, 2),
336 SENSOR_ATTR_2(temp3_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
337 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
338 store_temp_crit, 0, 2),
339 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
340 0, 2),
341 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
342 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
343};
344
0bae6400 345/* Temp attr for the standard models */
78aa4f72 346static struct sensor_device_attribute_2 fxxxx_temp_attr[3][9] = { {
7567a043 347 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1),
bc37ae71 348 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
7567a043 349 store_temp_max, 0, 1),
bc37ae71 350 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
7567a043 351 store_temp_max_hyst, 0, 1),
754a5907
HG
352 /* Should really be temp1_max_alarm, but older versions did not handle
353 the max and crit alarms separately and lm_sensors v2 depends on the
354 presence of temp#_alarm files. The same goes for temp2/3 _alarm. */
355 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
bc37ae71 356 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
7567a043 357 store_temp_crit, 0, 1),
bc37ae71 358 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
7567a043 359 0, 1),
754a5907 360 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
7567a043 361 SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1),
7567a043 362 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
60d2b378 363}, {
7567a043 364 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2),
bc37ae71 365 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
7567a043 366 store_temp_max, 0, 2),
bc37ae71 367 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
7567a043 368 store_temp_max_hyst, 0, 2),
754a5907
HG
369 /* Should be temp2_max_alarm, see temp1_alarm note */
370 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
bc37ae71 371 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
7567a043 372 store_temp_crit, 0, 2),
bc37ae71 373 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
7567a043 374 0, 2),
754a5907 375 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
7567a043 376 SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2),
7567a043 377 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
60d2b378 378}, {
7567a043 379 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3),
bc37ae71 380 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
7567a043 381 store_temp_max, 0, 3),
bc37ae71 382 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
7567a043 383 store_temp_max_hyst, 0, 3),
754a5907
HG
384 /* Should be temp3_max_alarm, see temp1_alarm note */
385 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3),
bc37ae71 386 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
7567a043 387 store_temp_crit, 0, 3),
bc37ae71 388 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
7567a043 389 0, 3),
754a5907 390 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7),
7567a043 391 SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3),
7567a043 392 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),
60d2b378 393} };
45fb3669 394
78aa4f72
HG
395/* Temp attr for models which can beep on temp alarm */
396static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
397 SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
398 store_temp_beep, 0, 1),
399 SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
400 store_temp_beep, 0, 5),
401}, {
402 SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
403 store_temp_beep, 0, 2),
404 SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
405 store_temp_beep, 0, 6),
406}, {
407 SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
408 store_temp_beep, 0, 3),
409 SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
410 store_temp_beep, 0, 7),
411} };
412
0bae6400 413/* Temp attr for the f8000
ed4f7c20
HG
414 Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
415 is used as hysteresis value to clear alarms
66344aa6 416 Also like the f71858fg its temperature indexes start at 0
ed4f7c20 417 */
0bae6400 418static struct sensor_device_attribute_2 f8000_temp_attr[] = {
ed4f7c20
HG
419 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
420 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit,
421 store_temp_crit, 0, 0),
422 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
423 store_temp_max, 0, 0),
424 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
b6858bca 425 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0),
ed4f7c20
HG
426 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
427 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit,
428 store_temp_crit, 0, 1),
429 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
430 store_temp_max, 0, 1),
431 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
b6858bca 432 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
ed4f7c20
HG
433 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
434 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit,
435 store_temp_crit, 0, 2),
436 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
437 store_temp_max, 0, 2),
438 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
b6858bca 439 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
ed4f7c20
HG
440};
441
0bae6400
HG
442/* in attr for all models */
443static struct sensor_device_attribute_2 fxxxx_in_attr[] = {
444 SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
445 SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
446 SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
447 SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
448 SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
449 SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
450 SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
451 SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
452 SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
453};
454
455/* For models with in1 alarm capability */
456static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = {
457 SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
458 0, 1),
459 SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
460 0, 1),
461 SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
462};
463
ed4f7c20 464/* Fan / PWM attr common to all models */
b69b0399 465static struct sensor_device_attribute_2 fxxxx_fan_attr[4][6] = { {
bc37ae71 466 SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
9ab796eb
MD
467 SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
468 show_fan_full_speed,
469 store_fan_full_speed, 0, 0),
bc37ae71 470 SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),
9ab796eb
MD
471 SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
472 SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
473 store_pwm_enable, 0, 0),
474 SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,
475 show_pwm_interpolate, store_pwm_interpolate, 0, 0),
b69b0399
HG
476}, {
477 SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
478 SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
479 show_fan_full_speed,
480 store_fan_full_speed, 0, 1),
481 SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
498be968
HG
482 SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
483 SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
484 store_pwm_enable, 0, 1),
485 SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
486 show_pwm_interpolate, store_pwm_interpolate, 0, 1),
b69b0399
HG
487}, {
488 SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
489 SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
490 show_fan_full_speed,
491 store_fan_full_speed, 0, 2),
492 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
3fc7838a
HG
493 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
494 SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
495 store_pwm_enable, 0, 2),
498be968
HG
496 SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
497 show_pwm_interpolate, store_pwm_interpolate, 0, 2),
b69b0399
HG
498}, {
499 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
500 SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
501 show_fan_full_speed,
502 store_fan_full_speed, 0, 3),
503 SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
504 SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
505 SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
506 store_pwm_enable, 0, 3),
507 SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
508 show_pwm_interpolate, store_pwm_interpolate, 0, 3),
509} };
498be968 510
66344aa6
HG
511/* Attr for models which can beep on Fan alarm */
512static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = {
ed4f7c20
HG
513 SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
514 store_fan_beep, 0, 0),
515 SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
516 store_fan_beep, 0, 1),
517 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
518 store_fan_beep, 0, 2),
b69b0399
HG
519 SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
520 store_fan_beep, 0, 3),
66344aa6 521};
ed4f7c20 522
66344aa6 523/* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
3cad4022 524 standard models */
66344aa6
HG
525static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
526 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
527 show_pwm_auto_point_channel,
528 store_pwm_auto_point_channel, 0, 0),
498be968
HG
529 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
530 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
531 1, 0),
532 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
533 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
534 4, 0),
535 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
536 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
537 0, 0),
538 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
539 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
540 3, 0),
541 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
542 show_pwm_auto_point_temp_hyst,
543 store_pwm_auto_point_temp_hyst,
544 0, 0),
545 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
546 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
547
66344aa6
HG
548 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
549 show_pwm_auto_point_channel,
550 store_pwm_auto_point_channel, 0, 1),
498be968
HG
551 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
552 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
553 1, 1),
554 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
555 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
556 4, 1),
557 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
558 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
559 0, 1),
560 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
561 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
562 3, 1),
563 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
564 show_pwm_auto_point_temp_hyst,
565 store_pwm_auto_point_temp_hyst,
566 0, 1),
567 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
568 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
4901062f 569
66344aa6
HG
570 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
571 show_pwm_auto_point_channel,
572 store_pwm_auto_point_channel, 0, 2),
4901062f
HG
573 SENSOR_ATTR_2(pwm3_auto_point1_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_point2_pwm, S_IRUGO|S_IWUSR,
577 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
578 4, 2),
579 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
580 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
581 0, 2),
582 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
583 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
584 3, 2),
585 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
586 show_pwm_auto_point_temp_hyst,
587 store_pwm_auto_point_temp_hyst,
588 0, 2),
589 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
590 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
498be968
HG
591};
592
c11bb993
HG
593/* PWM attr for the f71869, almost identical to the f71862fg, but the
594 pwm setting when the temperature is above the pwmX_auto_point1_temp can be
595 programmed instead of being hardcoded to 0xff */
596static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
597 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
598 show_pwm_auto_point_channel,
599 store_pwm_auto_point_channel, 0, 0),
600 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
601 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
602 0, 0),
603 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
604 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
605 1, 0),
606 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
607 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
608 4, 0),
609 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
610 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
611 0, 0),
612 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
613 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
614 3, 0),
615 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
616 show_pwm_auto_point_temp_hyst,
617 store_pwm_auto_point_temp_hyst,
618 0, 0),
619 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
620 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
621
622 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
623 show_pwm_auto_point_channel,
624 store_pwm_auto_point_channel, 0, 1),
625 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
626 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
627 0, 1),
628 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
629 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
630 1, 1),
631 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
632 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
633 4, 1),
634 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
635 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
636 0, 1),
637 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
638 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
639 3, 1),
640 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
641 show_pwm_auto_point_temp_hyst,
642 store_pwm_auto_point_temp_hyst,
643 0, 1),
644 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
645 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
646
647 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
648 show_pwm_auto_point_channel,
649 store_pwm_auto_point_channel, 0, 2),
650 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
651 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
652 0, 2),
653 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
654 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
655 1, 2),
656 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
657 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
658 4, 2),
659 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
660 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
661 0, 2),
662 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
663 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
664 3, 2),
665 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
666 show_pwm_auto_point_temp_hyst,
667 store_pwm_auto_point_temp_hyst,
668 0, 2),
669 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
670 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
671};
672
3cad4022 673/* PWM attr for the standard models */
b69b0399 674static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {
66344aa6
HG
675 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
676 show_pwm_auto_point_channel,
677 store_pwm_auto_point_channel, 0, 0),
9ab796eb
MD
678 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
679 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
680 0, 0),
681 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
682 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
683 1, 0),
684 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
685 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
686 2, 0),
687 SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,
688 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
689 3, 0),
690 SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,
691 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
692 4, 0),
693 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
694 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
695 0, 0),
696 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
697 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
698 1, 0),
699 SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,
700 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
701 2, 0),
702 SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,
703 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
704 3, 0),
705 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
706 show_pwm_auto_point_temp_hyst,
707 store_pwm_auto_point_temp_hyst,
708 0, 0),
709 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
710 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
711 SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO,
712 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
713 SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
714 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
b69b0399 715}, {
66344aa6
HG
716 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
717 show_pwm_auto_point_channel,
718 store_pwm_auto_point_channel, 0, 1),
9ab796eb
MD
719 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
720 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
721 0, 1),
722 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
723 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
724 1, 1),
725 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
726 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
727 2, 1),
728 SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,
729 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
730 3, 1),
731 SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,
732 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
733 4, 1),
734 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
735 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
736 0, 1),
737 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
738 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
739 1, 1),
740 SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR,
741 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
742 2, 1),
743 SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,
744 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
745 3, 1),
746 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
747 show_pwm_auto_point_temp_hyst,
748 store_pwm_auto_point_temp_hyst,
749 0, 1),
750 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
751 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
752 SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO,
753 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
754 SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
755 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
b69b0399 756}, {
66344aa6
HG
757 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
758 show_pwm_auto_point_channel,
759 store_pwm_auto_point_channel, 0, 2),
9ab796eb
MD
760 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
761 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
762 0, 2),
763 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
764 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
765 1, 2),
766 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
767 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
768 2, 2),
769 SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR,
770 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
771 3, 2),
772 SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,
773 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
774 4, 2),
775 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
776 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
777 0, 2),
778 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
779 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
780 1, 2),
781 SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR,
782 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
783 2, 2),
784 SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR,
785 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
786 3, 2),
787 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
788 show_pwm_auto_point_temp_hyst,
789 store_pwm_auto_point_temp_hyst,
790 0, 2),
791 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
792 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
793 SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO,
794 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
795 SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
796 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
b69b0399 797}, {
9ab796eb
MD
798 SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
799 show_pwm_auto_point_channel,
800 store_pwm_auto_point_channel, 0, 3),
801 SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,
802 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
803 0, 3),
804 SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,
805 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
806 1, 3),
807 SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,
808 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
809 2, 3),
810 SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR,
811 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
812 3, 3),
813 SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR,
814 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
815 4, 3),
816 SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,
817 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
818 0, 3),
819 SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,
820 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
821 1, 3),
822 SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,
823 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
824 2, 3),
825 SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,
826 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
827 3, 3),
828 SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
829 show_pwm_auto_point_temp_hyst,
830 store_pwm_auto_point_temp_hyst,
831 0, 3),
832 SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO,
833 show_pwm_auto_point_temp_hyst, NULL, 1, 3),
834 SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO,
835 show_pwm_auto_point_temp_hyst, NULL, 2, 3),
836 SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,
837 show_pwm_auto_point_temp_hyst, NULL, 3, 3),
b69b0399 838} };
45fb3669 839
66344aa6 840/* Fan attr specific to the f8000 (4th fan input can only measure speed) */
ed4f7c20
HG
841static struct sensor_device_attribute_2 f8000_fan_attr[] = {
842 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
66344aa6 843};
ed4f7c20 844
66344aa6
HG
845/* PWM attr for the f8000, zones mapped to temp instead of to pwm!
846 Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
847 F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
848static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
849 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
850 show_pwm_auto_point_channel,
851 store_pwm_auto_point_channel, 0, 0),
ed4f7c20
HG
852 SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR,
853 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
854 0, 2),
855 SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR,
856 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
857 1, 2),
858 SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR,
859 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
860 2, 2),
861 SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR,
862 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
863 3, 2),
864 SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR,
865 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
866 4, 2),
867 SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR,
868 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
869 0, 2),
870 SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR,
871 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
872 1, 2),
873 SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR,
874 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
875 2, 2),
876 SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR,
877 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
878 3, 2),
879 SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
880 show_pwm_auto_point_temp_hyst,
881 store_pwm_auto_point_temp_hyst,
882 0, 2),
883 SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO,
884 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
885 SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO,
886 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
887 SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
888 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
889
66344aa6
HG
890 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
891 show_pwm_auto_point_channel,
892 store_pwm_auto_point_channel, 0, 1),
ed4f7c20
HG
893 SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR,
894 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
895 0, 0),
896 SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR,
897 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
898 1, 0),
899 SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR,
900 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
901 2, 0),
902 SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR,
903 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
904 3, 0),
905 SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR,
906 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
907 4, 0),
908 SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR,
909 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
910 0, 0),
911 SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR,
912 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
913 1, 0),
914 SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR,
915 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
916 2, 0),
917 SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR,
918 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
919 3, 0),
920 SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
921 show_pwm_auto_point_temp_hyst,
922 store_pwm_auto_point_temp_hyst,
923 0, 0),
924 SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO,
925 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
926 SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO,
927 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
928 SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
929 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
930
66344aa6
HG
931 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
932 show_pwm_auto_point_channel,
933 store_pwm_auto_point_channel, 0, 2),
ed4f7c20
HG
934 SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR,
935 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
936 0, 1),
937 SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR,
938 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
939 1, 1),
940 SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR,
941 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
942 2, 1),
943 SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR,
944 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
945 3, 1),
946 SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR,
947 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
948 4, 1),
949 SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR,
950 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
951 0, 1),
952 SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR,
953 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
954 1, 1),
955 SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR,
956 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
957 2, 1),
958 SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR,
959 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
960 3, 1),
961 SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
962 show_pwm_auto_point_temp_hyst,
963 store_pwm_auto_point_temp_hyst,
964 0, 1),
965 SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO,
966 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
967 SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO,
968 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
969 SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
970 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
971};
45fb3669
HG
972
973/* Super I/O functions */
974static inline int superio_inb(int base, int reg)
975{
976 outb(reg, base);
977 return inb(base + 1);
978}
979
980static int superio_inw(int base, int reg)
981{
982 int val;
bd328acd
GS
983 val = superio_inb(base, reg) << 8;
984 val |= superio_inb(base, reg + 1);
45fb3669
HG
985 return val;
986}
987
cadb8657 988static inline int superio_enter(int base)
45fb3669 989{
cadb8657
GS
990 /* Don't step on other drivers' I/O space by accident */
991 if (!request_muxed_region(base, 2, DRVNAME)) {
22d3b412 992 pr_err("I/O address 0x%04x already in use\n", base);
cadb8657
GS
993 return -EBUSY;
994 }
995
45fb3669 996 /* according to the datasheet the key must be send twice! */
162bb59e
GS
997 outb(SIO_UNLOCK_KEY, base);
998 outb(SIO_UNLOCK_KEY, base);
cadb8657
GS
999
1000 return 0;
45fb3669
HG
1001}
1002
162bb59e 1003static inline void superio_select(int base, int ld)
45fb3669
HG
1004{
1005 outb(SIO_REG_LDSEL, base);
1006 outb(ld, base + 1);
1007}
1008
1009static inline void superio_exit(int base)
1010{
1011 outb(SIO_LOCK_KEY, base);
cadb8657 1012 release_region(base, 2);
45fb3669
HG
1013}
1014
2f650631 1015static inline int fan_from_reg(u16 reg)
45fb3669
HG
1016{
1017 return reg ? (1500000 / reg) : 0;
1018}
1019
2f650631 1020static inline u16 fan_to_reg(int fan)
9ab796eb
MD
1021{
1022 return fan ? (1500000 / fan) : 0;
1023}
1024
45fb3669
HG
1025static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg)
1026{
1027 u8 val;
1028
1029 outb(reg, data->addr + ADDR_REG_OFFSET);
1030 val = inb(data->addr + DATA_REG_OFFSET);
1031
1032 return val;
1033}
1034
1035static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg)
1036{
1037 u16 val;
1038
bd328acd
GS
1039 val = f71882fg_read8(data, reg) << 8;
1040 val |= f71882fg_read8(data, reg + 1);
45fb3669
HG
1041
1042 return val;
1043}
1044
1045static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)
1046{
1047 outb(reg, data->addr + ADDR_REG_OFFSET);
1048 outb(val, data->addr + DATA_REG_OFFSET);
1049}
1050
9ab796eb
MD
1051static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)
1052{
bd328acd
GS
1053 f71882fg_write8(data, reg, val >> 8);
1054 f71882fg_write8(data, reg + 1, val & 0xff);
9ab796eb
MD
1055}
1056
09475d32
HG
1057static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr)
1058{
1059 if (data->type == f71858fg)
1060 return f71882fg_read16(data, F71882FG_REG_TEMP(nr));
1061 else
1062 return f71882fg_read8(data, F71882FG_REG_TEMP(nr));
1063}
1064
77a4a3e2 1065static struct f71882fg_data *f71882fg_update_device(struct device *dev)
45fb3669
HG
1066{
1067 struct f71882fg_data *data = dev_get_drvdata(dev);
44c4dc52 1068 int nr, reg;
ed4f7c20 1069 int nr_fans = (data->type == f71882fg) ? 4 : 3;
45fb3669
HG
1070
1071 mutex_lock(&data->update_lock);
1072
1073 /* Update once every 60 seconds */
162bb59e 1074 if (time_after(jiffies, data->last_limits + 60 * HZ) ||
45fb3669 1075 !data->valid) {
0bae6400 1076 if (f71882fg_has_in1_alarm[data->type]) {
498be968
HG
1077 data->in1_max =
1078 f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
1079 data->in_beep =
1080 f71882fg_read8(data, F71882FG_REG_IN_BEEP);
1081 }
45fb3669
HG
1082
1083 /* Get High & boundary temps*/
09475d32 1084 for (nr = data->temp_start; nr < 3 + data->temp_start; nr++) {
45fb3669
HG
1085 data->temp_ovt[nr] = f71882fg_read8(data,
1086 F71882FG_REG_TEMP_OVT(nr));
1087 data->temp_high[nr] = f71882fg_read8(data,
1088 F71882FG_REG_TEMP_HIGH(nr));
1089 }
1090
ed4f7c20 1091 if (data->type != f8000) {
ed4f7c20
HG
1092 data->temp_hyst[0] = f71882fg_read8(data,
1093 F71882FG_REG_TEMP_HYST(0));
1094 data->temp_hyst[1] = f71882fg_read8(data,
1095 F71882FG_REG_TEMP_HYST(1));
09475d32 1096 }
78aa4f72
HG
1097 /* All but the f71858fg / f8000 have this register */
1098 if ((data->type != f71858fg) && (data->type != f8000)) {
1099 reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
1100 data->temp_type[1] = (reg & 0x02) ? 2 : 4;
1101 data->temp_type[2] = (reg & 0x04) ? 2 : 4;
1102 data->temp_type[3] = (reg & 0x08) ? 2 : 4;
1103 }
09475d32 1104
78aa4f72 1105 if (f71882fg_has_beep[data->type]) {
09475d32
HG
1106 data->fan_beep = f71882fg_read8(data,
1107 F71882FG_REG_FAN_BEEP);
1108 data->temp_beep = f71882fg_read8(data,
1109 F71882FG_REG_TEMP_BEEP);
ed4f7c20 1110 }
45fb3669 1111
9ab796eb
MD
1112 data->pwm_enable = f71882fg_read8(data,
1113 F71882FG_REG_PWM_ENABLE);
bc27490f
HG
1114 data->pwm_auto_point_hyst[0] =
1115 f71882fg_read8(data, F71882FG_REG_FAN_HYST(0));
1116 data->pwm_auto_point_hyst[1] =
1117 f71882fg_read8(data, F71882FG_REG_FAN_HYST(1));
1118
498be968 1119 for (nr = 0; nr < nr_fans; nr++) {
9ab796eb
MD
1120 data->pwm_auto_point_mapping[nr] =
1121 f71882fg_read8(data,
1122 F71882FG_REG_POINT_MAPPING(nr));
1123
c11bb993 1124 if (data->type != f71862fg && data->type != f71869) {
498be968
HG
1125 int point;
1126 for (point = 0; point < 5; point++) {
1127 data->pwm_auto_point_pwm[nr][point] =
1128 f71882fg_read8(data,
1129 F71882FG_REG_POINT_PWM
1130 (nr, point));
1131 }
1132 for (point = 0; point < 4; point++) {
1133 data->pwm_auto_point_temp[nr][point] =
1134 f71882fg_read8(data,
1135 F71882FG_REG_POINT_TEMP
1136 (nr, point));
1137 }
1138 } else {
c11bb993
HG
1139 if (data->type == f71869) {
1140 data->pwm_auto_point_pwm[nr][0] =
1141 f71882fg_read8(data,
1142 F71882FG_REG_POINT_PWM
1143 (nr, 0));
1144 }
498be968
HG
1145 data->pwm_auto_point_pwm[nr][1] =
1146 f71882fg_read8(data,
1147 F71882FG_REG_POINT_PWM
1148 (nr, 1));
1149 data->pwm_auto_point_pwm[nr][4] =
1150 f71882fg_read8(data,
1151 F71882FG_REG_POINT_PWM
1152 (nr, 4));
1153 data->pwm_auto_point_temp[nr][0] =
1154 f71882fg_read8(data,
1155 F71882FG_REG_POINT_TEMP
1156 (nr, 0));
1157 data->pwm_auto_point_temp[nr][3] =
1158 f71882fg_read8(data,
1159 F71882FG_REG_POINT_TEMP
1160 (nr, 3));
9ab796eb
MD
1161 }
1162 }
45fb3669
HG
1163 data->last_limits = jiffies;
1164 }
1165
1166 /* Update every second */
8afb1049 1167 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
45fb3669
HG
1168 data->temp_status = f71882fg_read8(data,
1169 F71882FG_REG_TEMP_STATUS);
1170 data->temp_diode_open = f71882fg_read8(data,
1171 F71882FG_REG_TEMP_DIODE_OPEN);
09475d32
HG
1172 for (nr = data->temp_start; nr < 3 + data->temp_start; nr++)
1173 data->temp[nr] = f71882fg_read_temp(data, nr);
45fb3669
HG
1174
1175 data->fan_status = f71882fg_read8(data,
1176 F71882FG_REG_FAN_STATUS);
498be968 1177 for (nr = 0; nr < nr_fans; nr++) {
45fb3669
HG
1178 data->fan[nr] = f71882fg_read16(data,
1179 F71882FG_REG_FAN(nr));
9ab796eb
MD
1180 data->fan_target[nr] =
1181 f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr));
1182 data->fan_full_speed[nr] =
1183 f71882fg_read16(data,
1184 F71882FG_REG_FAN_FULL_SPEED(nr));
1185 data->pwm[nr] =
1186 f71882fg_read8(data, F71882FG_REG_PWM(nr));
1187 }
ed4f7c20
HG
1188 /* The f8000 can monitor 1 more fan, but has no pwm for it */
1189 if (data->type == f8000)
1190 data->fan[3] = f71882fg_read16(data,
1191 F71882FG_REG_FAN(3));
0bae6400
HG
1192
1193 if (f71882fg_has_in1_alarm[data->type])
498be968 1194 data->in_status = f71882fg_read8(data,
45fb3669 1195 F71882FG_REG_IN_STATUS);
0bae6400
HG
1196 for (nr = 0; nr < F71882FG_MAX_INS; nr++)
1197 if (f71882fg_has_in[data->type][nr])
1198 data->in[nr] = f71882fg_read8(data,
1199 F71882FG_REG_IN(nr));
45fb3669
HG
1200
1201 data->last_updated = jiffies;
1202 data->valid = 1;
1203 }
1204
1205 mutex_unlock(&data->update_lock);
1206
1207 return data;
1208}
1209
1210/* Sysfs Interface */
1211static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
1212 char *buf)
1213{
1214 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1215 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1216 int speed = fan_from_reg(data->fan[nr]);
1217
1218 if (speed == FAN_MIN_DETECT)
1219 speed = 0;
1220
1221 return sprintf(buf, "%d\n", speed);
1222}
1223
9ab796eb
MD
1224static ssize_t show_fan_full_speed(struct device *dev,
1225 struct device_attribute *devattr, char *buf)
1226{
1227 struct f71882fg_data *data = f71882fg_update_device(dev);
1228 int nr = to_sensor_dev_attr_2(devattr)->index;
1229 int speed = fan_from_reg(data->fan_full_speed[nr]);
1230 return sprintf(buf, "%d\n", speed);
1231}
1232
1233static ssize_t store_fan_full_speed(struct device *dev,
1234 struct device_attribute *devattr,
1235 const char *buf, size_t count)
1236{
1237 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca
GS
1238 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1239 long val;
1240
1241 err = strict_strtol(buf, 10, &val);
1242 if (err)
1243 return err;
9ab796eb
MD
1244
1245 val = SENSORS_LIMIT(val, 23, 1500000);
1246 val = fan_to_reg(val);
1247
1248 mutex_lock(&data->update_lock);
4c82c38a
HG
1249 f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val);
1250 data->fan_full_speed[nr] = val;
9ab796eb
MD
1251 mutex_unlock(&data->update_lock);
1252
1253 return count;
1254}
1255
45fb3669
HG
1256static ssize_t show_fan_beep(struct device *dev, struct device_attribute
1257 *devattr, char *buf)
1258{
1259 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1260 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1261
1262 if (data->fan_beep & (1 << nr))
1263 return sprintf(buf, "1\n");
1264 else
1265 return sprintf(buf, "0\n");
1266}
1267
1268static ssize_t store_fan_beep(struct device *dev, struct device_attribute
1269 *devattr, const char *buf, size_t count)
1270{
1271 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca
GS
1272 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1273 unsigned long val;
1274
1275 err = strict_strtoul(buf, 10, &val);
1276 if (err)
1277 return err;
45fb3669
HG
1278
1279 mutex_lock(&data->update_lock);
ce0bfa5e 1280 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
45fb3669
HG
1281 if (val)
1282 data->fan_beep |= 1 << nr;
1283 else
1284 data->fan_beep &= ~(1 << nr);
1285
1286 f71882fg_write8(data, F71882FG_REG_FAN_BEEP, data->fan_beep);
1287 mutex_unlock(&data->update_lock);
1288
1289 return count;
1290}
1291
1292static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
1293 *devattr, char *buf)
1294{
1295 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1296 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1297
1298 if (data->fan_status & (1 << nr))
1299 return sprintf(buf, "1\n");
1300 else
1301 return sprintf(buf, "0\n");
1302}
1303
1304static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
1305 char *buf)
1306{
1307 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1308 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1309
1310 return sprintf(buf, "%d\n", data->in[nr] * 8);
1311}
1312
1313static ssize_t show_in_max(struct device *dev, struct device_attribute
1314 *devattr, char *buf)
1315{
1316 struct f71882fg_data *data = f71882fg_update_device(dev);
1317
1318 return sprintf(buf, "%d\n", data->in1_max * 8);
1319}
1320
1321static ssize_t store_in_max(struct device *dev, struct device_attribute
1322 *devattr, const char *buf, size_t count)
1323{
1324 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca
GS
1325 int err;
1326 long val;
1327
1328 err = strict_strtol(buf, 10, &val);
1329 if (err)
1330 return err;
1331
1332 val /= 8;
ce0bfa5e 1333 val = SENSORS_LIMIT(val, 0, 255);
45fb3669
HG
1334
1335 mutex_lock(&data->update_lock);
1336 f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
1337 data->in1_max = val;
1338 mutex_unlock(&data->update_lock);
1339
1340 return count;
1341}
1342
1343static ssize_t show_in_beep(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
HG
1348
1349 if (data->in_beep & (1 << nr))
1350 return sprintf(buf, "1\n");
1351 else
1352 return sprintf(buf, "0\n");
1353}
1354
1355static ssize_t store_in_beep(struct device *dev, struct device_attribute
1356 *devattr, const char *buf, size_t count)
1357{
1358 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca
GS
1359 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1360 unsigned long val;
1361
1362 err = strict_strtoul(buf, 10, &val);
1363 if (err)
1364 return err;
45fb3669
HG
1365
1366 mutex_lock(&data->update_lock);
ce0bfa5e 1367 data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
45fb3669
HG
1368 if (val)
1369 data->in_beep |= 1 << nr;
1370 else
1371 data->in_beep &= ~(1 << nr);
1372
1373 f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
1374 mutex_unlock(&data->update_lock);
1375
1376 return count;
1377}
1378
1379static ssize_t show_in_alarm(struct device *dev, struct device_attribute
1380 *devattr, char *buf)
1381{
1382 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1383 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1384
1385 if (data->in_status & (1 << nr))
1386 return sprintf(buf, "1\n");
1387 else
1388 return sprintf(buf, "0\n");
1389}
1390
1391static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
1392 char *buf)
1393{
1394 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1395 int nr = to_sensor_dev_attr_2(devattr)->index;
09475d32
HG
1396 int sign, temp;
1397
1398 if (data->type == f71858fg) {
1399 /* TEMP_TABLE_SEL 1 or 3 ? */
1400 if (data->temp_config & 1) {
1401 sign = data->temp[nr] & 0x0001;
1402 temp = (data->temp[nr] >> 5) & 0x7ff;
1403 } else {
1404 sign = data->temp[nr] & 0x8000;
1405 temp = (data->temp[nr] >> 5) & 0x3ff;
1406 }
1407 temp *= 125;
1408 if (sign)
1409 temp -= 128000;
1410 } else
1411 temp = data->temp[nr] * 1000;
45fb3669 1412
09475d32 1413 return sprintf(buf, "%d\n", temp);
45fb3669
HG
1414}
1415
1416static ssize_t show_temp_max(struct device *dev, struct device_attribute
1417 *devattr, char *buf)
1418{
1419 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1420 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1421
1422 return sprintf(buf, "%d\n", data->temp_high[nr] * 1000);
1423}
1424
1425static ssize_t store_temp_max(struct device *dev, struct device_attribute
1426 *devattr, const char *buf, size_t count)
1427{
1428 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca
GS
1429 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1430 long val;
1431
1432 err = strict_strtol(buf, 10, &val);
1433 if (err)
1434 return err;
1435
1436 val /= 1000;
ce0bfa5e 1437 val = SENSORS_LIMIT(val, 0, 255);
45fb3669
HG
1438
1439 mutex_lock(&data->update_lock);
1440 f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val);
1441 data->temp_high[nr] = val;
1442 mutex_unlock(&data->update_lock);
1443
1444 return count;
1445}
1446
1447static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
1448 *devattr, char *buf)
1449{
1450 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1451 int nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e 1452 int temp_max_hyst;
45fb3669 1453
ce0bfa5e 1454 mutex_lock(&data->update_lock);
bc27490f
HG
1455 if (nr & 1)
1456 temp_max_hyst = data->temp_hyst[nr / 2] >> 4;
1457 else
1458 temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f;
1459 temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000;
ce0bfa5e
HG
1460 mutex_unlock(&data->update_lock);
1461
1462 return sprintf(buf, "%d\n", temp_max_hyst);
45fb3669
HG
1463}
1464
1465static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
1466 *devattr, const char *buf, size_t count)
1467{
1468 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca 1469 int err, nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669 1470 ssize_t ret = count;
ce0bfa5e 1471 u8 reg;
e8a4eaca
GS
1472 long val;
1473
1474 err = strict_strtol(buf, 10, &val);
1475 if (err)
1476 return err;
1477
1478 val /= 1000;
45fb3669
HG
1479
1480 mutex_lock(&data->update_lock);
1481
1482 /* convert abs to relative and check */
ce0bfa5e
HG
1483 data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr));
1484 val = SENSORS_LIMIT(val, data->temp_high[nr] - 15,
1485 data->temp_high[nr]);
45fb3669 1486 val = data->temp_high[nr] - val;
45fb3669
HG
1487
1488 /* convert value to register contents */
bc27490f
HG
1489 reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2));
1490 if (nr & 1)
1491 reg = (reg & 0x0f) | (val << 4);
1492 else
1493 reg = (reg & 0xf0) | val;
1494 f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg);
1495 data->temp_hyst[nr / 2] = reg;
45fb3669 1496
45fb3669
HG
1497 mutex_unlock(&data->update_lock);
1498 return ret;
1499}
1500
1501static ssize_t show_temp_crit(struct device *dev, struct device_attribute
1502 *devattr, char *buf)
1503{
1504 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1505 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1506
1507 return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000);
1508}
1509
1510static ssize_t store_temp_crit(struct device *dev, struct device_attribute
1511 *devattr, const char *buf, size_t count)
1512{
1513 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca
GS
1514 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1515 long val;
1516
1517 err = strict_strtol(buf, 10, &val);
1518 if (err)
1519 return err;
1520
1521 val /= 1000;
ce0bfa5e 1522 val = SENSORS_LIMIT(val, 0, 255);
45fb3669
HG
1523
1524 mutex_lock(&data->update_lock);
1525 f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val);
1526 data->temp_ovt[nr] = val;
1527 mutex_unlock(&data->update_lock);
1528
1529 return count;
1530}
1531
1532static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
1533 *devattr, char *buf)
1534{
1535 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1536 int nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e 1537 int temp_crit_hyst;
45fb3669 1538
ce0bfa5e 1539 mutex_lock(&data->update_lock);
bc27490f
HG
1540 if (nr & 1)
1541 temp_crit_hyst = data->temp_hyst[nr / 2] >> 4;
1542 else
1543 temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f;
1544 temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000;
ce0bfa5e
HG
1545 mutex_unlock(&data->update_lock);
1546
1547 return sprintf(buf, "%d\n", temp_crit_hyst);
45fb3669
HG
1548}
1549
1550static ssize_t show_temp_type(struct device *dev, struct device_attribute
1551 *devattr, char *buf)
1552{
1553 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1554 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669
HG
1555
1556 return sprintf(buf, "%d\n", data->temp_type[nr]);
1557}
1558
1559static ssize_t show_temp_beep(struct device *dev, struct device_attribute
1560 *devattr, char *buf)
1561{
1562 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1563 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669 1564
7567a043 1565 if (data->temp_beep & (1 << nr))
45fb3669
HG
1566 return sprintf(buf, "1\n");
1567 else
1568 return sprintf(buf, "0\n");
1569}
1570
1571static ssize_t store_temp_beep(struct device *dev, struct device_attribute
1572 *devattr, const char *buf, size_t count)
1573{
1574 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca
GS
1575 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1576 unsigned long val;
1577
1578 err = strict_strtoul(buf, 10, &val);
1579 if (err)
1580 return err;
45fb3669
HG
1581
1582 mutex_lock(&data->update_lock);
ce0bfa5e 1583 data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);
45fb3669 1584 if (val)
7567a043 1585 data->temp_beep |= 1 << nr;
45fb3669 1586 else
7567a043 1587 data->temp_beep &= ~(1 << nr);
45fb3669
HG
1588
1589 f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep);
1590 mutex_unlock(&data->update_lock);
1591
1592 return count;
1593}
1594
1595static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
1596 *devattr, char *buf)
1597{
1598 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1599 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669 1600
7567a043 1601 if (data->temp_status & (1 << nr))
45fb3669
HG
1602 return sprintf(buf, "1\n");
1603 else
1604 return sprintf(buf, "0\n");
1605}
1606
1607static ssize_t show_temp_fault(struct device *dev, struct device_attribute
1608 *devattr, char *buf)
1609{
1610 struct f71882fg_data *data = f71882fg_update_device(dev);
bc37ae71 1611 int nr = to_sensor_dev_attr_2(devattr)->index;
45fb3669 1612
7567a043 1613 if (data->temp_diode_open & (1 << nr))
45fb3669
HG
1614 return sprintf(buf, "1\n");
1615 else
1616 return sprintf(buf, "0\n");
1617}
1618
9ab796eb
MD
1619static ssize_t show_pwm(struct device *dev,
1620 struct device_attribute *devattr, char *buf)
1621{
1622 struct f71882fg_data *data = f71882fg_update_device(dev);
1623 int val, nr = to_sensor_dev_attr_2(devattr)->index;
ce0bfa5e 1624 mutex_lock(&data->update_lock);
9ab796eb
MD
1625 if (data->pwm_enable & (1 << (2 * nr)))
1626 /* PWM mode */
1627 val = data->pwm[nr];
1628 else {
1629 /* RPM mode */
9ab796eb
MD
1630 val = 255 * fan_from_reg(data->fan_target[nr])
1631 / fan_from_reg(data->fan_full_speed[nr]);
9ab796eb 1632 }
ce0bfa5e 1633 mutex_unlock(&data->update_lock);
9ab796eb
MD
1634 return sprintf(buf, "%d\n", val);
1635}
1636
1637static ssize_t store_pwm(struct device *dev,
1638 struct device_attribute *devattr, const char *buf,
1639 size_t count)
1640{
ce0bfa5e 1641 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca
GS
1642 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1643 long val;
1644
1645 err = strict_strtol(buf, 10, &val);
1646 if (err)
1647 return err;
1648
9ab796eb
MD
1649 val = SENSORS_LIMIT(val, 0, 255);
1650
1651 mutex_lock(&data->update_lock);
ce0bfa5e 1652 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
ed4f7c20
HG
1653 if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) ||
1654 (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) {
1655 count = -EROFS;
1656 goto leave;
1657 }
9ab796eb
MD
1658 if (data->pwm_enable & (1 << (2 * nr))) {
1659 /* PWM mode */
1660 f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
1661 data->pwm[nr] = val;
1662 } else {
1663 /* RPM mode */
ce0bfa5e
HG
1664 int target, full_speed;
1665 full_speed = f71882fg_read16(data,
1666 F71882FG_REG_FAN_FULL_SPEED(nr));
1667 target = fan_to_reg(val * fan_from_reg(full_speed) / 255);
1668 f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target);
1669 data->fan_target[nr] = target;
1670 data->fan_full_speed[nr] = full_speed;
9ab796eb 1671 }
ed4f7c20 1672leave:
9ab796eb
MD
1673 mutex_unlock(&data->update_lock);
1674
1675 return count;
1676}
1677
1678static ssize_t show_pwm_enable(struct device *dev,
1679 struct device_attribute *devattr, char *buf)
1680{
ed4f7c20 1681 int result = 0;
9ab796eb
MD
1682 struct f71882fg_data *data = f71882fg_update_device(dev);
1683 int nr = to_sensor_dev_attr_2(devattr)->index;
1684
ed4f7c20
HG
1685 switch ((data->pwm_enable >> 2 * nr) & 3) {
1686 case 0:
1687 case 1:
1688 result = 2; /* Normal auto mode */
1689 break;
1690 case 2:
1691 result = 1; /* Manual mode */
1692 break;
1693 case 3:
1694 if (data->type == f8000)
1695 result = 3; /* Thermostat mode */
1696 else
1697 result = 1; /* Manual mode */
1698 break;
1699 }
9ab796eb
MD
1700
1701 return sprintf(buf, "%d\n", result);
1702}
1703
1704static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
1705 *devattr, const char *buf, size_t count)
1706{
1707 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca
GS
1708 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1709 long val;
1710
1711 err = strict_strtol(buf, 10, &val);
1712 if (err)
1713 return err;
9ab796eb 1714
3fc7838a
HG
1715 /* Special case for F8000 pwm channel 3 which only does auto mode */
1716 if (data->type == f8000 && nr == 2 && val != 2)
1717 return -EINVAL;
1718
9ab796eb 1719 mutex_lock(&data->update_lock);
ce0bfa5e 1720 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
ed4f7c20
HG
1721 /* Special case for F8000 auto PWM mode / Thermostat mode */
1722 if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) {
1723 switch (val) {
1724 case 2:
1725 data->pwm_enable &= ~(2 << (2 * nr));
1726 break; /* Normal auto mode */
1727 case 3:
1728 data->pwm_enable |= 2 << (2 * nr);
1729 break; /* Thermostat mode */
1730 default:
1731 count = -EINVAL;
1732 goto leave;
1733 }
1734 } else {
1735 switch (val) {
1736 case 1:
09475d32
HG
1737 /* The f71858fg does not support manual RPM mode */
1738 if (data->type == f71858fg &&
1739 ((data->pwm_enable >> (2 * nr)) & 1)) {
1740 count = -EINVAL;
1741 goto leave;
1742 }
ed4f7c20
HG
1743 data->pwm_enable |= 2 << (2 * nr);
1744 break; /* Manual */
1745 case 2:
1746 data->pwm_enable &= ~(2 << (2 * nr));
1747 break; /* Normal auto mode */
1748 default:
1749 count = -EINVAL;
1750 goto leave;
1751 }
9ab796eb 1752 }
9ab796eb 1753 f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
ed4f7c20 1754leave:
9ab796eb
MD
1755 mutex_unlock(&data->update_lock);
1756
1757 return count;
1758}
1759
1760static ssize_t show_pwm_auto_point_pwm(struct device *dev,
1761 struct device_attribute *devattr,
1762 char *buf)
1763{
1764 int result;
1765 struct f71882fg_data *data = f71882fg_update_device(dev);
1766 int pwm = to_sensor_dev_attr_2(devattr)->index;
1767 int point = to_sensor_dev_attr_2(devattr)->nr;
1768
ce0bfa5e 1769 mutex_lock(&data->update_lock);
9ab796eb
MD
1770 if (data->pwm_enable & (1 << (2 * pwm))) {
1771 /* PWM mode */
1772 result = data->pwm_auto_point_pwm[pwm][point];
1773 } else {
1774 /* RPM mode */
1775 result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]);
1776 }
ce0bfa5e 1777 mutex_unlock(&data->update_lock);
9ab796eb
MD
1778
1779 return sprintf(buf, "%d\n", result);
1780}
1781
1782static ssize_t store_pwm_auto_point_pwm(struct device *dev,
1783 struct device_attribute *devattr,
1784 const char *buf, size_t count)
1785{
ce0bfa5e 1786 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca 1787 int err, pwm = to_sensor_dev_attr_2(devattr)->index;
9ab796eb 1788 int point = to_sensor_dev_attr_2(devattr)->nr;
e8a4eaca
GS
1789 long val;
1790
1791 err = strict_strtol(buf, 10, &val);
1792 if (err)
1793 return err;
1794
9ab796eb
MD
1795 val = SENSORS_LIMIT(val, 0, 255);
1796
1797 mutex_lock(&data->update_lock);
ce0bfa5e 1798 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
9ab796eb
MD
1799 if (data->pwm_enable & (1 << (2 * pwm))) {
1800 /* PWM mode */
1801 } else {
1802 /* RPM mode */
1803 if (val < 29) /* Prevent negative numbers */
1804 val = 255;
1805 else
1806 val = (255 - val) * 32 / val;
1807 }
1808 f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val);
1809 data->pwm_auto_point_pwm[pwm][point] = val;
1810 mutex_unlock(&data->update_lock);
1811
1812 return count;
1813}
1814
1815static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
1816 struct device_attribute *devattr,
1817 char *buf)
1818{
1819 int result = 0;
1820 struct f71882fg_data *data = f71882fg_update_device(dev);
1821 int nr = to_sensor_dev_attr_2(devattr)->index;
1822 int point = to_sensor_dev_attr_2(devattr)->nr;
1823
1824 mutex_lock(&data->update_lock);
bc27490f
HG
1825 if (nr & 1)
1826 result = data->pwm_auto_point_hyst[nr / 2] >> 4;
1827 else
1828 result = data->pwm_auto_point_hyst[nr / 2] & 0x0f;
9ab796eb
MD
1829 result = 1000 * (data->pwm_auto_point_temp[nr][point] - result);
1830 mutex_unlock(&data->update_lock);
1831
1832 return sprintf(buf, "%d\n", result);
1833}
1834
1835static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
1836 struct device_attribute *devattr,
1837 const char *buf, size_t count)
1838{
ce0bfa5e 1839 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca 1840 int err, nr = to_sensor_dev_attr_2(devattr)->index;
9ab796eb 1841 int point = to_sensor_dev_attr_2(devattr)->nr;
bc27490f 1842 u8 reg;
e8a4eaca
GS
1843 long val;
1844
1845 err = strict_strtol(buf, 10, &val);
1846 if (err)
1847 return err;
1848
1849 val /= 1000;
9ab796eb
MD
1850
1851 mutex_lock(&data->update_lock);
ce0bfa5e
HG
1852 data->pwm_auto_point_temp[nr][point] =
1853 f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point));
9ab796eb
MD
1854 val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15,
1855 data->pwm_auto_point_temp[nr][point]);
1856 val = data->pwm_auto_point_temp[nr][point] - val;
1857
bc27490f
HG
1858 reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2));
1859 if (nr & 1)
1860 reg = (reg & 0x0f) | (val << 4);
1861 else
1862 reg = (reg & 0xf0) | val;
1863
1864 f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg);
1865 data->pwm_auto_point_hyst[nr / 2] = reg;
9ab796eb
MD
1866 mutex_unlock(&data->update_lock);
1867
1868 return count;
1869}
1870
1871static ssize_t show_pwm_interpolate(struct device *dev,
1872 struct device_attribute *devattr, char *buf)
1873{
1874 int result;
1875 struct f71882fg_data *data = f71882fg_update_device(dev);
1876 int nr = to_sensor_dev_attr_2(devattr)->index;
1877
1878 result = (data->pwm_auto_point_mapping[nr] >> 4) & 1;
1879
1880 return sprintf(buf, "%d\n", result);
1881}
1882
1883static ssize_t store_pwm_interpolate(struct device *dev,
1884 struct device_attribute *devattr,
1885 const char *buf, size_t count)
1886{
ce0bfa5e 1887 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca
GS
1888 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1889 unsigned long val;
1890
1891 err = strict_strtoul(buf, 10, &val);
1892 if (err)
1893 return err;
ce0bfa5e 1894
9ab796eb 1895 mutex_lock(&data->update_lock);
ce0bfa5e
HG
1896 data->pwm_auto_point_mapping[nr] =
1897 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
9ab796eb
MD
1898 if (val)
1899 val = data->pwm_auto_point_mapping[nr] | (1 << 4);
1900 else
1901 val = data->pwm_auto_point_mapping[nr] & (~(1 << 4));
1902 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1903 data->pwm_auto_point_mapping[nr] = val;
1904 mutex_unlock(&data->update_lock);
1905
1906 return count;
1907}
1908
1909static ssize_t show_pwm_auto_point_channel(struct device *dev,
1910 struct device_attribute *devattr,
1911 char *buf)
1912{
1913 int result;
1914 struct f71882fg_data *data = f71882fg_update_device(dev);
1915 int nr = to_sensor_dev_attr_2(devattr)->index;
1916
09475d32
HG
1917 result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) -
1918 data->temp_start);
9ab796eb
MD
1919
1920 return sprintf(buf, "%d\n", result);
1921}
1922
1923static ssize_t store_pwm_auto_point_channel(struct device *dev,
1924 struct device_attribute *devattr,
1925 const char *buf, size_t count)
1926{
ce0bfa5e 1927 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca
GS
1928 int err, nr = to_sensor_dev_attr_2(devattr)->index;
1929 long val;
1930
1931 err = strict_strtol(buf, 10, &val);
1932 if (err)
1933 return err;
30453018 1934
9ab796eb
MD
1935 switch (val) {
1936 case 1:
30453018 1937 val = 0;
9ab796eb
MD
1938 break;
1939 case 2:
30453018 1940 val = 1;
9ab796eb
MD
1941 break;
1942 case 4:
30453018 1943 val = 2;
9ab796eb
MD
1944 break;
1945 default:
1946 return -EINVAL;
1947 }
09475d32 1948 val += data->temp_start;
9ab796eb 1949 mutex_lock(&data->update_lock);
ce0bfa5e
HG
1950 data->pwm_auto_point_mapping[nr] =
1951 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
9ab796eb
MD
1952 val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val;
1953 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1954 data->pwm_auto_point_mapping[nr] = val;
1955 mutex_unlock(&data->update_lock);
1956
1957 return count;
1958}
1959
1960static ssize_t show_pwm_auto_point_temp(struct device *dev,
1961 struct device_attribute *devattr,
1962 char *buf)
1963{
1964 int result;
1965 struct f71882fg_data *data = f71882fg_update_device(dev);
1966 int pwm = to_sensor_dev_attr_2(devattr)->index;
1967 int point = to_sensor_dev_attr_2(devattr)->nr;
1968
1969 result = data->pwm_auto_point_temp[pwm][point];
1970 return sprintf(buf, "%d\n", 1000 * result);
1971}
1972
1973static ssize_t store_pwm_auto_point_temp(struct device *dev,
1974 struct device_attribute *devattr,
1975 const char *buf, size_t count)
1976{
ce0bfa5e 1977 struct f71882fg_data *data = dev_get_drvdata(dev);
e8a4eaca 1978 int err, pwm = to_sensor_dev_attr_2(devattr)->index;
9ab796eb 1979 int point = to_sensor_dev_attr_2(devattr)->nr;
e8a4eaca
GS
1980 long val;
1981
1982 err = strict_strtol(buf, 10, &val);
1983 if (err)
1984 return err;
1985
1986 val /= 1000;
7669896f 1987
98f7ba19 1988 if (data->auto_point_temp_signed)
7669896f
HG
1989 val = SENSORS_LIMIT(val, -128, 127);
1990 else
1991 val = SENSORS_LIMIT(val, 0, 127);
9ab796eb
MD
1992
1993 mutex_lock(&data->update_lock);
1994 f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
1995 data->pwm_auto_point_temp[pwm][point] = val;
1996 mutex_unlock(&data->update_lock);
1997
1998 return count;
1999}
2000
45fb3669
HG
2001static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
2002 char *buf)
2003{
498be968
HG
2004 struct f71882fg_data *data = dev_get_drvdata(dev);
2005 return sprintf(buf, "%s\n", f71882fg_names[data->type]);
45fb3669
HG
2006}
2007
c13548c5
HG
2008static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
2009 struct sensor_device_attribute_2 *attr, int count)
2010{
2011 int err, i;
2012
2013 for (i = 0; i < count; i++) {
2014 err = device_create_file(&pdev->dev, &attr[i].dev_attr);
2015 if (err)
2016 return err;
2017 }
2018 return 0;
2019}
45fb3669 2020
fc16c56e
HG
2021static void f71882fg_remove_sysfs_files(struct platform_device *pdev,
2022 struct sensor_device_attribute_2 *attr, int count)
2023{
2024 int i;
2025
2026 for (i = 0; i < count; i++)
2027 device_remove_file(&pdev->dev, &attr[i].dev_attr);
2028}
2029
c13548c5 2030static int __devinit f71882fg_probe(struct platform_device *pdev)
45fb3669
HG
2031{
2032 struct f71882fg_data *data;
498be968 2033 struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
28ba8587 2034 int err, i, nr_fans = (sio_data->type == f71882fg) ? 4 : 3;
60d2b378 2035 int nr_temps = 3;
98f7ba19 2036 u8 start_reg, reg;
45fb3669 2037
c13548c5
HG
2038 data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
2039 if (!data)
45fb3669
HG
2040 return -ENOMEM;
2041
2042 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
498be968 2043 data->type = sio_data->type;
09475d32
HG
2044 data->temp_start =
2045 (data->type == f71858fg || data->type == f8000) ? 0 : 1;
45fb3669
HG
2046 mutex_init(&data->update_lock);
2047 platform_set_drvdata(pdev, data);
2048
3cc74758 2049 start_reg = f71882fg_read8(data, F71882FG_REG_START);
12d66e84
HG
2050 if (start_reg & 0x04) {
2051 dev_warn(&pdev->dev, "Hardware monitor is powered down\n");
2052 err = -ENODEV;
2053 goto exit_free;
2054 }
3cc74758
HG
2055 if (!(start_reg & 0x03)) {
2056 dev_warn(&pdev->dev, "Hardware monitoring not activated\n");
2057 err = -ENODEV;
2058 goto exit_free;
2059 }
2060
45fb3669 2061 /* Register sysfs interface files */
c13548c5
HG
2062 err = device_create_file(&pdev->dev, &dev_attr_name);
2063 if (err)
2064 goto exit_unregister_sysfs;
45fb3669 2065
45fb3669 2066 if (start_reg & 0x01) {
ed4f7c20 2067 switch (data->type) {
09475d32
HG
2068 case f71858fg:
2069 data->temp_config =
2070 f71882fg_read8(data, F71882FG_REG_TEMP_CONFIG);
2071 if (data->temp_config & 0x10)
2072 /* The f71858fg temperature alarms behave as
2073 the f8000 alarms in this mode */
2074 err = f71882fg_create_sysfs_files(pdev,
0bae6400
HG
2075 f8000_temp_attr,
2076 ARRAY_SIZE(f8000_temp_attr));
09475d32
HG
2077 else
2078 err = f71882fg_create_sysfs_files(pdev,
0bae6400
HG
2079 f71858fg_temp_attr,
2080 ARRAY_SIZE(f71858fg_temp_attr));
ed4f7c20
HG
2081 break;
2082 case f8000:
2083 err = f71882fg_create_sysfs_files(pdev,
0bae6400
HG
2084 f8000_temp_attr,
2085 ARRAY_SIZE(f8000_temp_attr));
ed4f7c20 2086 break;
0bae6400
HG
2087 default:
2088 err = f71882fg_create_sysfs_files(pdev,
60d2b378
HG
2089 &fxxxx_temp_attr[0][0],
2090 ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
498be968 2091 }
ed4f7c20
HG
2092 if (err)
2093 goto exit_unregister_sysfs;
0bae6400 2094
78aa4f72
HG
2095 if (f71882fg_has_beep[data->type]) {
2096 err = f71882fg_create_sysfs_files(pdev,
2097 &fxxxx_temp_beep_attr[0][0],
2098 ARRAY_SIZE(fxxxx_temp_beep_attr[0])
2099 * nr_temps);
2100 if (err)
2101 goto exit_unregister_sysfs;
2102 }
2103
0bae6400
HG
2104 for (i = 0; i < F71882FG_MAX_INS; i++) {
2105 if (f71882fg_has_in[data->type][i]) {
2106 err = device_create_file(&pdev->dev,
2107 &fxxxx_in_attr[i].dev_attr);
2108 if (err)
2109 goto exit_unregister_sysfs;
2110 }
2111 }
2112 if (f71882fg_has_in1_alarm[data->type]) {
2113 err = f71882fg_create_sysfs_files(pdev,
2114 fxxxx_in1_alarm_attr,
2115 ARRAY_SIZE(fxxxx_in1_alarm_attr));
2116 if (err)
2117 goto exit_unregister_sysfs;
2118 }
45fb3669
HG
2119 }
2120
2121 if (start_reg & 0x02) {
98f7ba19 2122 switch (data->type) {
c11bb993
HG
2123 case f71869:
2124 /* The f71869 always has signed auto point temps */
2125 data->auto_point_temp_signed = 1;
2126 /* Fall through to select correct fan/pwm reg bank! */
98f7ba19 2127 case f71889fg:
3cad4022 2128 case f71889ed:
98f7ba19
HG
2129 reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T);
2130 if (reg & F71882FG_FAN_NEG_TEMP_EN)
2131 data->auto_point_temp_signed = 1;
3cad4022
HG
2132 /* Ensure banked pwm registers point to right bank */
2133 reg &= ~F71882FG_FAN_PROG_SEL;
2134 f71882fg_write8(data, F71882FG_REG_FAN_FAULT_T, reg);
98f7ba19
HG
2135 break;
2136 default:
2137 break;
2138 }
2139
996cadb2
HG
2140 data->pwm_enable =
2141 f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
2142
2143 /* Sanity check the pwm settings */
2144 switch (data->type) {
09475d32
HG
2145 case f71858fg:
2146 err = 0;
2147 for (i = 0; i < nr_fans; i++)
2148 if (((data->pwm_enable >> (i * 2)) & 3) == 3)
2149 err = 1;
2150 break;
996cadb2
HG
2151 case f71862fg:
2152 err = (data->pwm_enable & 0x15) != 0x15;
2153 break;
c11bb993 2154 case f71869:
996cadb2 2155 case f71882fg:
7669896f 2156 case f71889fg:
3cad4022 2157 case f71889ed:
996cadb2
HG
2158 err = 0;
2159 break;
2160 case f8000:
2161 err = data->pwm_enable & 0x20;
2162 break;
2163 }
2164 if (err) {
2165 dev_err(&pdev->dev,
2166 "Invalid (reserved) pwm settings: 0x%02x\n",
2167 (unsigned int)data->pwm_enable);
2168 err = -ENODEV;
2169 goto exit_unregister_sysfs;
2170 }
2171
b69b0399
HG
2172 err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
2173 ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
498be968
HG
2174 if (err)
2175 goto exit_unregister_sysfs;
2176
78aa4f72 2177 if (f71882fg_has_beep[data->type]) {
498be968 2178 err = f71882fg_create_sysfs_files(pdev,
b69b0399 2179 fxxxx_fan_beep_attr, nr_fans);
66344aa6
HG
2180 if (err)
2181 goto exit_unregister_sysfs;
b69b0399
HG
2182 }
2183
e48a7f1a 2184 switch (data->type) {
c11bb993 2185 case f71869:
e48a7f1a 2186 case f71889fg:
3cad4022 2187 case f71889ed:
e48a7f1a
HG
2188 for (i = 0; i < nr_fans; i++) {
2189 data->pwm_auto_point_mapping[i] =
2190 f71882fg_read8(data,
2191 F71882FG_REG_POINT_MAPPING(i));
3cad4022
HG
2192 if ((data->pwm_auto_point_mapping[i] & 0x80) ||
2193 (data->pwm_auto_point_mapping[i] & 3) == 0)
e48a7f1a
HG
2194 break;
2195 }
2196 if (i != nr_fans) {
2197 dev_warn(&pdev->dev,
2198 "Auto pwm controlled by raw digital "
2199 "data, disabling pwm auto_point "
2200 "sysfs attributes\n");
2201 goto no_pwm_auto_point;
2202 }
2203 break;
2204 default:
2205 break;
2206 }
2207
b69b0399
HG
2208 switch (data->type) {
2209 case f71862fg:
66344aa6
HG
2210 err = f71882fg_create_sysfs_files(pdev,
2211 f71862fg_auto_pwm_attr,
2212 ARRAY_SIZE(f71862fg_auto_pwm_attr));
ed4f7c20 2213 break;
c11bb993
HG
2214 case f71869:
2215 err = f71882fg_create_sysfs_files(pdev,
2216 f71869_auto_pwm_attr,
2217 ARRAY_SIZE(f71869_auto_pwm_attr));
2218 break;
ed4f7c20
HG
2219 case f8000:
2220 err = f71882fg_create_sysfs_files(pdev,
2221 f8000_fan_attr,
2222 ARRAY_SIZE(f8000_fan_attr));
66344aa6
HG
2223 if (err)
2224 goto exit_unregister_sysfs;
2225 err = f71882fg_create_sysfs_files(pdev,
2226 f8000_auto_pwm_attr,
2227 ARRAY_SIZE(f8000_auto_pwm_attr));
ed4f7c20 2228 break;
e48a7f1a 2229 default:
b69b0399
HG
2230 err = f71882fg_create_sysfs_files(pdev,
2231 &fxxxx_auto_pwm_attr[0][0],
2232 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
498be968 2233 }
c13548c5
HG
2234 if (err)
2235 goto exit_unregister_sysfs;
28ba8587 2236
e48a7f1a 2237no_pwm_auto_point:
28ba8587
HG
2238 for (i = 0; i < nr_fans; i++)
2239 dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1,
2240 (data->pwm_enable & (1 << 2 * i)) ?
2241 "duty-cycle" : "RPM");
45fb3669
HG
2242 }
2243
1beeffe4
TJ
2244 data->hwmon_dev = hwmon_device_register(&pdev->dev);
2245 if (IS_ERR(data->hwmon_dev)) {
2246 err = PTR_ERR(data->hwmon_dev);
c13548c5 2247 data->hwmon_dev = NULL;
45fb3669
HG
2248 goto exit_unregister_sysfs;
2249 }
2250
2251 return 0;
2252
2253exit_unregister_sysfs:
c13548c5 2254 f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
3cc74758
HG
2255 return err; /* f71882fg_remove() also frees our data */
2256exit_free:
2257 kfree(data);
45fb3669
HG
2258 return err;
2259}
2260
c13548c5 2261static int f71882fg_remove(struct platform_device *pdev)
45fb3669 2262{
45fb3669 2263 struct f71882fg_data *data = platform_get_drvdata(pdev);
0bae6400 2264 int i, nr_fans = (data->type == f71882fg) ? 4 : 3;
60d2b378 2265 int nr_temps = 3;
fc16c56e 2266 u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);
45fb3669 2267
c13548c5
HG
2268 if (data->hwmon_dev)
2269 hwmon_device_unregister(data->hwmon_dev);
45fb3669 2270
c13548c5 2271 device_remove_file(&pdev->dev, &dev_attr_name);
45fb3669 2272
fc16c56e
HG
2273 if (start_reg & 0x01) {
2274 switch (data->type) {
2275 case f71858fg:
2276 if (data->temp_config & 0x10)
2277 f71882fg_remove_sysfs_files(pdev,
0bae6400
HG
2278 f8000_temp_attr,
2279 ARRAY_SIZE(f8000_temp_attr));
fc16c56e
HG
2280 else
2281 f71882fg_remove_sysfs_files(pdev,
0bae6400
HG
2282 f71858fg_temp_attr,
2283 ARRAY_SIZE(f71858fg_temp_attr));
fc16c56e
HG
2284 break;
2285 case f8000:
2286 f71882fg_remove_sysfs_files(pdev,
0bae6400
HG
2287 f8000_temp_attr,
2288 ARRAY_SIZE(f8000_temp_attr));
fc16c56e 2289 break;
0bae6400
HG
2290 default:
2291 f71882fg_remove_sysfs_files(pdev,
60d2b378
HG
2292 &fxxxx_temp_attr[0][0],
2293 ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
0bae6400 2294 }
78aa4f72
HG
2295 if (f71882fg_has_beep[data->type]) {
2296 f71882fg_remove_sysfs_files(pdev,
2297 &fxxxx_temp_beep_attr[0][0],
2298 ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps);
2299 }
2300
0bae6400
HG
2301 for (i = 0; i < F71882FG_MAX_INS; i++) {
2302 if (f71882fg_has_in[data->type][i]) {
2303 device_remove_file(&pdev->dev,
2304 &fxxxx_in_attr[i].dev_attr);
2305 }
2306 }
2307 if (f71882fg_has_in1_alarm[data->type]) {
2308 f71882fg_remove_sysfs_files(pdev,
2309 fxxxx_in1_alarm_attr,
2310 ARRAY_SIZE(fxxxx_in1_alarm_attr));
fc16c56e
HG
2311 }
2312 }
498be968 2313
fc16c56e
HG
2314 if (start_reg & 0x02) {
2315 f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
2316 ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
45fb3669 2317
78aa4f72 2318 if (f71882fg_has_beep[data->type]) {
fc16c56e
HG
2319 f71882fg_remove_sysfs_files(pdev,
2320 fxxxx_fan_beep_attr, nr_fans);
78aa4f72 2321 }
66344aa6 2322
fc16c56e
HG
2323 switch (data->type) {
2324 case f71862fg:
2325 f71882fg_remove_sysfs_files(pdev,
2326 f71862fg_auto_pwm_attr,
2327 ARRAY_SIZE(f71862fg_auto_pwm_attr));
2328 break;
c11bb993
HG
2329 case f71869:
2330 f71882fg_remove_sysfs_files(pdev,
2331 f71869_auto_pwm_attr,
2332 ARRAY_SIZE(f71869_auto_pwm_attr));
2333 break;
fc16c56e
HG
2334 case f8000:
2335 f71882fg_remove_sysfs_files(pdev,
2336 f8000_fan_attr,
2337 ARRAY_SIZE(f8000_fan_attr));
2338 f71882fg_remove_sysfs_files(pdev,
2339 f8000_auto_pwm_attr,
2340 ARRAY_SIZE(f8000_auto_pwm_attr));
2341 break;
3cad4022 2342 default:
fc16c56e
HG
2343 f71882fg_remove_sysfs_files(pdev,
2344 &fxxxx_auto_pwm_attr[0][0],
2345 ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
2346 }
2347 }
ed4f7c20 2348
d9ebaa45 2349 platform_set_drvdata(pdev, NULL);
45fb3669
HG
2350 kfree(data);
2351
2352 return 0;
2353}
2354
498be968
HG
2355static int __init f71882fg_find(int sioaddr, unsigned short *address,
2356 struct f71882fg_sio_data *sio_data)
45fb3669 2357{
45fb3669 2358 u16 devid;
cadb8657
GS
2359 int err = superio_enter(sioaddr);
2360 if (err)
2361 return err;
45fb3669
HG
2362
2363 devid = superio_inw(sioaddr, SIO_REG_MANID);
2364 if (devid != SIO_FINTEK_ID) {
22d3b412 2365 pr_debug("Not a Fintek device\n");
cadb8657 2366 err = -ENODEV;
45fb3669
HG
2367 goto exit;
2368 }
2369
67b671bc 2370 devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
498be968 2371 switch (devid) {
09475d32
HG
2372 case SIO_F71858_ID:
2373 sio_data->type = f71858fg;
2374 break;
498be968
HG
2375 case SIO_F71862_ID:
2376 sio_data->type = f71862fg;
2377 break;
c11bb993
HG
2378 case SIO_F71869_ID:
2379 sio_data->type = f71869;
2380 break;
498be968
HG
2381 case SIO_F71882_ID:
2382 sio_data->type = f71882fg;
2383 break;
7669896f
HG
2384 case SIO_F71889_ID:
2385 sio_data->type = f71889fg;
2386 break;
3cad4022
HG
2387 case SIO_F71889E_ID:
2388 sio_data->type = f71889ed;
2389 break;
ed4f7c20
HG
2390 case SIO_F8000_ID:
2391 sio_data->type = f8000;
2392 break;
498be968 2393 default:
22d3b412
JP
2394 pr_info("Unsupported Fintek device: %04x\n",
2395 (unsigned int)devid);
cadb8657 2396 err = -ENODEV;
45fb3669
HG
2397 goto exit;
2398 }
2399
09475d32
HG
2400 if (sio_data->type == f71858fg)
2401 superio_select(sioaddr, SIO_F71858FG_LD_HWM);
2402 else
2403 superio_select(sioaddr, SIO_F71882FG_LD_HWM);
2404
8afb1049 2405 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
22d3b412 2406 pr_warn("Device not activated\n");
cadb8657 2407 err = -ENODEV;
45fb3669
HG
2408 goto exit;
2409 }
2410
2411 *address = superio_inw(sioaddr, SIO_REG_ADDR);
162bb59e 2412 if (*address == 0) {
22d3b412 2413 pr_warn("Base address not set\n");
cadb8657 2414 err = -ENODEV;
45fb3669
HG
2415 goto exit;
2416 }
2417 *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
2418
45fb3669 2419 err = 0;
22d3b412 2420 pr_info("Found %s chip at %#x, revision %d\n",
498be968 2421 f71882fg_names[sio_data->type], (unsigned int)*address,
45fb3669
HG
2422 (int)superio_inb(sioaddr, SIO_REG_DEVREV));
2423exit:
2424 superio_exit(sioaddr);
2425 return err;
2426}
2427
498be968
HG
2428static int __init f71882fg_device_add(unsigned short address,
2429 const struct f71882fg_sio_data *sio_data)
45fb3669
HG
2430{
2431 struct resource res = {
2432 .start = address,
2433 .end = address + REGION_LENGTH - 1,
2434 .flags = IORESOURCE_IO,
2435 };
2436 int err;
2437
2438 f71882fg_pdev = platform_device_alloc(DRVNAME, address);
8afb1049 2439 if (!f71882fg_pdev)
45fb3669
HG
2440 return -ENOMEM;
2441
2442 res.name = f71882fg_pdev->name;
b9acb64a
JD
2443 err = acpi_check_resource_conflict(&res);
2444 if (err)
18632f84 2445 goto exit_device_put;
b9acb64a 2446
45fb3669 2447 err = platform_device_add_resources(f71882fg_pdev, &res, 1);
8afb1049 2448 if (err) {
22d3b412 2449 pr_err("Device resource addition failed\n");
45fb3669
HG
2450 goto exit_device_put;
2451 }
2452
498be968
HG
2453 err = platform_device_add_data(f71882fg_pdev, sio_data,
2454 sizeof(struct f71882fg_sio_data));
2455 if (err) {
22d3b412 2456 pr_err("Platform data allocation failed\n");
498be968
HG
2457 goto exit_device_put;
2458 }
2459
45fb3669 2460 err = platform_device_add(f71882fg_pdev);
8afb1049 2461 if (err) {
22d3b412 2462 pr_err("Device addition failed\n");
45fb3669
HG
2463 goto exit_device_put;
2464 }
2465
2466 return 0;
2467
2468exit_device_put:
2469 platform_device_put(f71882fg_pdev);
2470
2471 return err;
2472}
2473
2474static int __init f71882fg_init(void)
2475{
2476 int err = -ENODEV;
2477 unsigned short address;
498be968
HG
2478 struct f71882fg_sio_data sio_data;
2479
2480 memset(&sio_data, 0, sizeof(sio_data));
45fb3669 2481
498be968
HG
2482 if (f71882fg_find(0x2e, &address, &sio_data) &&
2483 f71882fg_find(0x4e, &address, &sio_data))
45fb3669
HG
2484 goto exit;
2485
c13548c5
HG
2486 err = platform_driver_register(&f71882fg_driver);
2487 if (err)
45fb3669
HG
2488 goto exit;
2489
498be968 2490 err = f71882fg_device_add(address, &sio_data);
c13548c5 2491 if (err)
45fb3669
HG
2492 goto exit_driver;
2493
2494 return 0;
2495
2496exit_driver:
2497 platform_driver_unregister(&f71882fg_driver);
2498exit:
2499 return err;
2500}
2501
2502static void __exit f71882fg_exit(void)
2503{
2504 platform_device_unregister(f71882fg_pdev);
2505 platform_driver_unregister(&f71882fg_driver);
2506}
2507
2508MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");
c13548c5 2509MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)");
45fb3669
HG
2510MODULE_LICENSE("GPL");
2511
2512module_init(f71882fg_init);
2513module_exit(f71882fg_exit);
This page took 0.715651 seconds and 5 git commands to generate.