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