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