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