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