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