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