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