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