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