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