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