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