blob: a833797e96d3d13facc23360cc9bf8502972d4dc [file] [log] [blame]
Hans de Goede45fb3662007-07-13 14:34:19 +02001/***************************************************************************
2 * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> *
Hans de Goedec13548c2009-01-07 16:37:27 +01003 * Copyright (C) 2007,2008 by Hans de Goede <hdegoede@redhat.com> *
Hans de Goede45fb3662007-07-13 14:34:19 +02004 * *
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>
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +010030#include <linux/io.h>
Hans de Goede45fb3662007-07-13 14:34:19 +020031
32#define DRVNAME "f71882fg"
33
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +010034#define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */
Hans de Goede45fb3662007-07-13 14:34:19 +020035#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
36#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */
37
38#define SIO_REG_LDSEL 0x07 /* Logical device select */
39#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
40#define SIO_REG_DEVREV 0x22 /* Device revision */
41#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
42#define SIO_REG_ENABLE 0x30 /* Logical device enable */
43#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
44
45#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */
Hans de Goede498be962009-01-07 16:37:28 +010046#define SIO_F71862_ID 0x0601 /* Chipset ID */
Hans de Goede45fb3662007-07-13 14:34:19 +020047#define SIO_F71882_ID 0x0541 /* Chipset ID */
Hans de Goedeed4f7c22009-01-07 16:37:30 +010048#define SIO_F8000_ID 0x0581 /* Chipset ID */
Hans de Goede45fb3662007-07-13 14:34:19 +020049
50#define REGION_LENGTH 8
51#define ADDR_REG_OFFSET 5
52#define DATA_REG_OFFSET 6
53
54#define F71882FG_REG_PECI 0x0A
55
Hans de Goede498be962009-01-07 16:37:28 +010056#define F71882FG_REG_IN_STATUS 0x12 /* f71882fg only */
57#define F71882FG_REG_IN_BEEP 0x13 /* f71882fg only */
Hans de Goede45fb3662007-07-13 14:34:19 +020058#define F71882FG_REG_IN(nr) (0x20 + (nr))
Hans de Goede498be962009-01-07 16:37:28 +010059#define F71882FG_REG_IN1_HIGH 0x32 /* f71882fg only */
Hans de Goede45fb3662007-07-13 14:34:19 +020060
61#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr)))
Mark van Doesburg9ab796e2009-01-07 16:37:27 +010062#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))
63#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))
Hans de Goede45fb3662007-07-13 14:34:19 +020064#define F71882FG_REG_FAN_STATUS 0x92
65#define F71882FG_REG_FAN_BEEP 0x93
66
Hans de Goede7567a042009-01-07 16:37:28 +010067#define F71882FG_REG_TEMP(nr) (0x70 + 2 * (nr))
68#define F71882FG_REG_TEMP_OVT(nr) (0x80 + 2 * (nr))
69#define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr))
Hans de Goede45fb3662007-07-13 14:34:19 +020070#define F71882FG_REG_TEMP_STATUS 0x62
71#define F71882FG_REG_TEMP_BEEP 0x63
Hans de Goedebc274902009-01-07 16:37:29 +010072#define F71882FG_REG_TEMP_HYST(nr) (0x6C + (nr))
Hans de Goede45fb3662007-07-13 14:34:19 +020073#define F71882FG_REG_TEMP_TYPE 0x6B
74#define F71882FG_REG_TEMP_DIODE_OPEN 0x6F
75
Mark van Doesburg9ab796e2009-01-07 16:37:27 +010076#define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr)))
77#define F71882FG_REG_PWM_TYPE 0x94
78#define F71882FG_REG_PWM_ENABLE 0x96
79
Hans de Goedebc274902009-01-07 16:37:29 +010080#define F71882FG_REG_FAN_HYST(nr) (0x98 + (nr))
Mark van Doesburg9ab796e2009-01-07 16:37:27 +010081
82#define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm)))
83#define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm)))
84#define F71882FG_REG_POINT_MAPPING(nr) (0xAF + 16 * (nr))
85
Hans de Goede45fb3662007-07-13 14:34:19 +020086#define F71882FG_REG_START 0x01
87
88#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */
89
Jean Delvare67b671b2007-12-06 23:13:42 +010090static unsigned short force_id;
91module_param(force_id, ushort, 0);
92MODULE_PARM_DESC(force_id, "Override the detected device ID");
93
Hans de Goedeed4f7c22009-01-07 16:37:30 +010094enum chips { f71862fg, f71882fg, f8000 };
Hans de Goede498be962009-01-07 16:37:28 +010095
96static const char *f71882fg_names[] = {
97 "f71862fg",
98 "f71882fg",
Hans de Goedeed4f7c22009-01-07 16:37:30 +010099 "f8000",
Hans de Goede498be962009-01-07 16:37:28 +0100100};
101
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +0100102static struct platform_device *f71882fg_pdev;
Hans de Goede45fb3662007-07-13 14:34:19 +0200103
104/* Super-I/O Function prototypes */
105static inline int superio_inb(int base, int reg);
106static inline int superio_inw(int base, int reg);
107static inline void superio_enter(int base);
108static inline void superio_select(int base, int ld);
109static inline void superio_exit(int base);
110
Hans de Goede498be962009-01-07 16:37:28 +0100111struct f71882fg_sio_data {
112 enum chips type;
113};
114
Hans de Goede45fb3662007-07-13 14:34:19 +0200115struct f71882fg_data {
116 unsigned short addr;
Hans de Goede498be962009-01-07 16:37:28 +0100117 enum chips type;
Tony Jones1beeffe2007-08-20 13:46:20 -0700118 struct device *hwmon_dev;
Hans de Goede45fb3662007-07-13 14:34:19 +0200119
120 struct mutex update_lock;
121 char valid; /* !=0 if following fields are valid */
122 unsigned long last_updated; /* In jiffies */
123 unsigned long last_limits; /* In jiffies */
124
125 /* Register Values */
126 u8 in[9];
127 u8 in1_max;
128 u8 in_status;
129 u8 in_beep;
130 u16 fan[4];
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100131 u16 fan_target[4];
132 u16 fan_full_speed[4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200133 u8 fan_status;
134 u8 fan_beep;
Hans de Goede7567a042009-01-07 16:37:28 +0100135 /* Note: all models have only 3 temperature channels, but on some
136 they are addressed as 0-2 and on others as 1-3, so for coding
137 convenience we reserve space for 4 channels */
138 u8 temp[4];
139 u8 temp_ovt[4];
140 u8 temp_high[4];
Hans de Goedebc274902009-01-07 16:37:29 +0100141 u8 temp_hyst[2]; /* 2 hysts stored per reg */
Hans de Goede7567a042009-01-07 16:37:28 +0100142 u8 temp_type[4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200143 u8 temp_status;
144 u8 temp_beep;
145 u8 temp_diode_open;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100146 u8 pwm[4];
147 u8 pwm_enable;
148 u8 pwm_auto_point_hyst[2];
149 u8 pwm_auto_point_mapping[4];
150 u8 pwm_auto_point_pwm[4][5];
151 u8 pwm_auto_point_temp[4][4];
Hans de Goede45fb3662007-07-13 14:34:19 +0200152};
153
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +0100154/* Sysfs in */
Hans de Goede45fb3662007-07-13 14:34:19 +0200155static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
156 char *buf);
157static ssize_t show_in_max(struct device *dev, struct device_attribute
158 *devattr, char *buf);
159static ssize_t store_in_max(struct device *dev, struct device_attribute
160 *devattr, const char *buf, size_t count);
161static ssize_t show_in_beep(struct device *dev, struct device_attribute
162 *devattr, char *buf);
163static ssize_t store_in_beep(struct device *dev, struct device_attribute
164 *devattr, const char *buf, size_t count);
165static ssize_t show_in_alarm(struct device *dev, struct device_attribute
166 *devattr, char *buf);
167/* Sysfs Fan */
168static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
169 char *buf);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100170static ssize_t show_fan_full_speed(struct device *dev,
171 struct device_attribute *devattr, char *buf);
172static ssize_t store_fan_full_speed(struct device *dev,
173 struct device_attribute *devattr, const char *buf, size_t count);
Hans de Goede45fb3662007-07-13 14:34:19 +0200174static ssize_t show_fan_beep(struct device *dev, struct device_attribute
175 *devattr, char *buf);
176static ssize_t store_fan_beep(struct device *dev, struct device_attribute
177 *devattr, const char *buf, size_t count);
178static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
179 *devattr, char *buf);
180/* Sysfs Temp */
181static ssize_t show_temp(struct device *dev, struct device_attribute
182 *devattr, char *buf);
183static ssize_t show_temp_max(struct device *dev, struct device_attribute
184 *devattr, char *buf);
185static ssize_t store_temp_max(struct device *dev, struct device_attribute
186 *devattr, const char *buf, size_t count);
187static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
188 *devattr, char *buf);
189static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
190 *devattr, const char *buf, size_t count);
191static ssize_t show_temp_crit(struct device *dev, struct device_attribute
192 *devattr, char *buf);
193static ssize_t store_temp_crit(struct device *dev, struct device_attribute
194 *devattr, const char *buf, size_t count);
195static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
196 *devattr, char *buf);
197static ssize_t show_temp_type(struct device *dev, struct device_attribute
198 *devattr, char *buf);
199static ssize_t show_temp_beep(struct device *dev, struct device_attribute
200 *devattr, char *buf);
201static ssize_t store_temp_beep(struct device *dev, struct device_attribute
202 *devattr, const char *buf, size_t count);
203static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
204 *devattr, char *buf);
205static ssize_t show_temp_fault(struct device *dev, struct device_attribute
206 *devattr, char *buf);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100207/* PWM and Auto point control */
208static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
209 char *buf);
210static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
211 const char *buf, size_t count);
212static ssize_t show_pwm_enable(struct device *dev,
213 struct device_attribute *devattr, char *buf);
214static ssize_t store_pwm_enable(struct device *dev,
215 struct device_attribute *devattr, const char *buf, size_t count);
216static ssize_t show_pwm_interpolate(struct device *dev,
217 struct device_attribute *devattr, char *buf);
218static ssize_t store_pwm_interpolate(struct device *dev,
219 struct device_attribute *devattr, const char *buf, size_t count);
220static ssize_t show_pwm_auto_point_channel(struct device *dev,
221 struct device_attribute *devattr, char *buf);
222static ssize_t store_pwm_auto_point_channel(struct device *dev,
223 struct device_attribute *devattr, const char *buf, size_t count);
224static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
225 struct device_attribute *devattr, char *buf);
226static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
227 struct device_attribute *devattr, const char *buf, size_t count);
228static ssize_t show_pwm_auto_point_pwm(struct device *dev,
229 struct device_attribute *devattr, char *buf);
230static ssize_t store_pwm_auto_point_pwm(struct device *dev,
231 struct device_attribute *devattr, const char *buf, size_t count);
232static ssize_t show_pwm_auto_point_temp(struct device *dev,
233 struct device_attribute *devattr, char *buf);
234static ssize_t store_pwm_auto_point_temp(struct device *dev,
235 struct device_attribute *devattr, const char *buf, size_t count);
Hans de Goede45fb3662007-07-13 14:34:19 +0200236/* Sysfs misc */
237static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
238 char *buf);
239
240static int __devinit f71882fg_probe(struct platform_device * pdev);
Hans de Goedec13548c2009-01-07 16:37:27 +0100241static int f71882fg_remove(struct platform_device *pdev);
Hans de Goede45fb3662007-07-13 14:34:19 +0200242
243static struct platform_driver f71882fg_driver = {
244 .driver = {
245 .owner = THIS_MODULE,
246 .name = DRVNAME,
247 },
248 .probe = f71882fg_probe,
249 .remove = __devexit_p(f71882fg_remove),
250};
251
Hans de Goedec13548c2009-01-07 16:37:27 +0100252static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
Hans de Goede45fb3662007-07-13 14:34:19 +0200253
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100254/* Temp and in attr common to both the f71862fg and f71882fg */
Hans de Goede498be962009-01-07 16:37:28 +0100255static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = {
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100256 SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
257 SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100258 SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
259 SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
260 SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
261 SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
262 SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
263 SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
264 SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
Hans de Goede7567a042009-01-07 16:37:28 +0100265 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1),
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100266 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100267 store_temp_max, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100268 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100269 store_temp_max_hyst, 0, 1),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100270 /* Should really be temp1_max_alarm, but older versions did not handle
271 the max and crit alarms separately and lm_sensors v2 depends on the
272 presence of temp#_alarm files. The same goes for temp2/3 _alarm. */
273 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
274 SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
275 store_temp_beep, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100276 SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100277 store_temp_crit, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100278 SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100279 0, 1),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100280 SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
281 SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
282 store_temp_beep, 0, 5),
Hans de Goede7567a042009-01-07 16:37:28 +0100283 SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1),
Hans de Goede7567a042009-01-07 16:37:28 +0100284 SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
285 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2),
286 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100287 store_temp_max, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100288 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100289 store_temp_max_hyst, 0, 2),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100290 /* Should be temp2_max_alarm, see temp1_alarm note */
291 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
292 SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
293 store_temp_beep, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100294 SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100295 store_temp_crit, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100296 SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100297 0, 2),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100298 SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
299 SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
300 store_temp_beep, 0, 6),
Hans de Goede7567a042009-01-07 16:37:28 +0100301 SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2),
Hans de Goede7567a042009-01-07 16:37:28 +0100302 SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
303 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3),
304 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
305 store_temp_max, 0, 3),
306 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
307 store_temp_max_hyst, 0, 3),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100308 /* Should be temp3_max_alarm, see temp1_alarm note */
309 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3),
310 SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
311 store_temp_beep, 0, 3),
Hans de Goede7567a042009-01-07 16:37:28 +0100312 SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
313 store_temp_crit, 0, 3),
314 SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
315 0, 3),
Hans de Goede754a5907b2009-01-07 16:37:29 +0100316 SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7),
317 SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
318 store_temp_beep, 0, 7),
Hans de Goede7567a042009-01-07 16:37:28 +0100319 SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3),
Hans de Goede7567a042009-01-07 16:37:28 +0100320 SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),
Hans de Goede45fb3662007-07-13 14:34:19 +0200321};
322
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100323/* Temp and in attr found only on the f71882fg */
Hans de Goede498be962009-01-07 16:37:28 +0100324static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = {
325 SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
326 0, 1),
327 SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
328 0, 1),
329 SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
330};
331
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100332/* Temp and in attr for the f8000
333 Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
334 is used as hysteresis value to clear alarms
335 */
336static struct sensor_device_attribute_2 f8000_in_temp_attr[] = {
337 SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
338 SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
339 SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
340 SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
341 SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit,
342 store_temp_crit, 0, 0),
343 SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
344 store_temp_max, 0, 0),
345 SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
346 SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
347 SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit,
348 store_temp_crit, 0, 1),
349 SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
350 store_temp_max, 0, 1),
351 SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
352 SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1),
353 SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
354 SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit,
355 store_temp_crit, 0, 2),
356 SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
357 store_temp_max, 0, 2),
358 SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
359};
360
361/* Fan / PWM attr common to all models */
362static struct sensor_device_attribute_2 fxxxx_fan_attr[] = {
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100363 SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100364 SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
365 show_fan_full_speed,
366 store_fan_full_speed, 0, 0),
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100367 SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),
368 SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100369 SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
370 show_fan_full_speed,
371 store_fan_full_speed, 0, 1),
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100372 SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
373 SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100374 SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
375 show_fan_full_speed,
376 store_fan_full_speed, 0, 2),
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100377 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100378
379 SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
380 SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
381 store_pwm_enable, 0, 0),
382 SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,
383 show_pwm_interpolate, store_pwm_interpolate, 0, 0),
384 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
385 show_pwm_auto_point_channel,
386 store_pwm_auto_point_channel, 0, 0),
Hans de Goede498be962009-01-07 16:37:28 +0100387
388 SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
389 SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
390 store_pwm_enable, 0, 1),
391 SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
392 show_pwm_interpolate, store_pwm_interpolate, 0, 1),
393 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
394 show_pwm_auto_point_channel,
395 store_pwm_auto_point_channel, 0, 1),
396
Hans de Goede498be962009-01-07 16:37:28 +0100397 SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
398 show_pwm_interpolate, store_pwm_interpolate, 0, 2),
399 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
400 show_pwm_auto_point_channel,
401 store_pwm_auto_point_channel, 0, 2),
402};
403
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100404/* Fan / PWM attr for the f71862fg, less pwms and less zones per pwm than the
405 f71882fg */
Hans de Goede498be962009-01-07 16:37:28 +0100406static struct sensor_device_attribute_2 f71862fg_fan_attr[] = {
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100407 SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
408 store_fan_beep, 0, 0),
409 SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
410 store_fan_beep, 0, 1),
411 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
412 store_fan_beep, 0, 2),
413
Hans de Goede498be962009-01-07 16:37:28 +0100414 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
415 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
416 1, 0),
417 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
418 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
419 4, 0),
420 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
421 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
422 0, 0),
423 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
424 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
425 3, 0),
426 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
427 show_pwm_auto_point_temp_hyst,
428 store_pwm_auto_point_temp_hyst,
429 0, 0),
430 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
431 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
432
433 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
434 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
435 1, 1),
436 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
437 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
438 4, 1),
439 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
440 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
441 0, 1),
442 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
443 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
444 3, 1),
445 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
446 show_pwm_auto_point_temp_hyst,
447 store_pwm_auto_point_temp_hyst,
448 0, 1),
449 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
450 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
451};
452
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100453/* Fan / PWM attr for the f71882fg */
Hans de Goede498be962009-01-07 16:37:28 +0100454static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100455 SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
456 store_fan_beep, 0, 0),
457 SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
458 store_fan_beep, 0, 1),
459 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
460 store_fan_beep, 0, 2),
Hans de Goede498be962009-01-07 16:37:28 +0100461 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
462 SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
463 show_fan_full_speed,
464 store_fan_full_speed, 0, 3),
465 SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
466 store_fan_beep, 0, 3),
467 SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
468
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100469 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
470 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
471 0, 0),
472 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
473 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
474 1, 0),
475 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
476 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
477 2, 0),
478 SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,
479 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
480 3, 0),
481 SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,
482 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
483 4, 0),
484 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
485 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
486 0, 0),
487 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
488 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
489 1, 0),
490 SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,
491 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
492 2, 0),
493 SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,
494 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
495 3, 0),
496 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
497 show_pwm_auto_point_temp_hyst,
498 store_pwm_auto_point_temp_hyst,
499 0, 0),
500 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
501 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
502 SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO,
503 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
504 SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
505 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
506
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100507 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
508 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
509 0, 1),
510 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
511 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
512 1, 1),
513 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
514 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
515 2, 1),
516 SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,
517 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
518 3, 1),
519 SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,
520 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
521 4, 1),
522 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
523 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
524 0, 1),
525 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
526 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
527 1, 1),
528 SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR,
529 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
530 2, 1),
531 SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,
532 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
533 3, 1),
534 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
535 show_pwm_auto_point_temp_hyst,
536 store_pwm_auto_point_temp_hyst,
537 0, 1),
538 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
539 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
540 SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO,
541 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
542 SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
543 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
544
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100545 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
546 SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
547 store_pwm_enable, 0, 2),
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100548 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
549 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
550 0, 2),
551 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
552 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
553 1, 2),
554 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
555 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
556 2, 2),
557 SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR,
558 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
559 3, 2),
560 SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,
561 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
562 4, 2),
563 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
564 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
565 0, 2),
566 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
567 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
568 1, 2),
569 SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR,
570 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
571 2, 2),
572 SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR,
573 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
574 3, 2),
575 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
576 show_pwm_auto_point_temp_hyst,
577 store_pwm_auto_point_temp_hyst,
578 0, 2),
579 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
580 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
581 SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO,
582 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
583 SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
584 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
585
586 SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
587 SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
588 store_pwm_enable, 0, 3),
589 SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
590 show_pwm_interpolate, store_pwm_interpolate, 0, 3),
591 SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
592 show_pwm_auto_point_channel,
593 store_pwm_auto_point_channel, 0, 3),
594 SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,
595 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
596 0, 3),
597 SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,
598 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
599 1, 3),
600 SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,
601 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
602 2, 3),
603 SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR,
604 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
605 3, 3),
606 SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR,
607 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
608 4, 3),
609 SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,
610 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
611 0, 3),
612 SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,
613 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
614 1, 3),
615 SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,
616 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
617 2, 3),
618 SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,
619 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
620 3, 3),
621 SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
622 show_pwm_auto_point_temp_hyst,
623 store_pwm_auto_point_temp_hyst,
624 0, 3),
625 SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO,
626 show_pwm_auto_point_temp_hyst, NULL, 1, 3),
627 SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO,
628 show_pwm_auto_point_temp_hyst, NULL, 2, 3),
629 SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,
630 show_pwm_auto_point_temp_hyst, NULL, 3, 3),
Hans de Goede45fb3662007-07-13 14:34:19 +0200631};
632
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100633/* Fan / PWM attr for the f8000, zones mapped to temp instead of to pwm!
634 Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
635 F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
636static struct sensor_device_attribute_2 f8000_fan_attr[] = {
637 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
638
639 SENSOR_ATTR_2(pwm3, S_IRUGO, show_pwm, NULL, 0, 2),
640
641 SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR,
642 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
643 0, 2),
644 SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR,
645 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
646 1, 2),
647 SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR,
648 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
649 2, 2),
650 SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR,
651 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
652 3, 2),
653 SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR,
654 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
655 4, 2),
656 SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR,
657 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
658 0, 2),
659 SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR,
660 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
661 1, 2),
662 SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR,
663 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
664 2, 2),
665 SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR,
666 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
667 3, 2),
668 SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
669 show_pwm_auto_point_temp_hyst,
670 store_pwm_auto_point_temp_hyst,
671 0, 2),
672 SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO,
673 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
674 SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO,
675 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
676 SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
677 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
678
679 SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR,
680 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
681 0, 0),
682 SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR,
683 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
684 1, 0),
685 SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR,
686 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
687 2, 0),
688 SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR,
689 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
690 3, 0),
691 SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR,
692 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
693 4, 0),
694 SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR,
695 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
696 0, 0),
697 SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR,
698 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
699 1, 0),
700 SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR,
701 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
702 2, 0),
703 SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR,
704 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
705 3, 0),
706 SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
707 show_pwm_auto_point_temp_hyst,
708 store_pwm_auto_point_temp_hyst,
709 0, 0),
710 SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO,
711 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
712 SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO,
713 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
714 SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
715 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
716
717 SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR,
718 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
719 0, 1),
720 SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR,
721 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
722 1, 1),
723 SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR,
724 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
725 2, 1),
726 SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR,
727 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
728 3, 1),
729 SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR,
730 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
731 4, 1),
732 SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR,
733 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
734 0, 1),
735 SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR,
736 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
737 1, 1),
738 SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR,
739 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
740 2, 1),
741 SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR,
742 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
743 3, 1),
744 SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
745 show_pwm_auto_point_temp_hyst,
746 store_pwm_auto_point_temp_hyst,
747 0, 1),
748 SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO,
749 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
750 SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO,
751 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
752 SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
753 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
754};
Hans de Goede45fb3662007-07-13 14:34:19 +0200755
756/* Super I/O functions */
757static inline int superio_inb(int base, int reg)
758{
759 outb(reg, base);
760 return inb(base + 1);
761}
762
763static int superio_inw(int base, int reg)
764{
765 int val;
766 outb(reg++, base);
767 val = inb(base + 1) << 8;
768 outb(reg, base);
769 val |= inb(base + 1);
770 return val;
771}
772
773static inline void superio_enter(int base)
774{
775 /* according to the datasheet the key must be send twice! */
776 outb( SIO_UNLOCK_KEY, base);
777 outb( SIO_UNLOCK_KEY, base);
778}
779
780static inline void superio_select( int base, int ld)
781{
782 outb(SIO_REG_LDSEL, base);
783 outb(ld, base + 1);
784}
785
786static inline void superio_exit(int base)
787{
788 outb(SIO_LOCK_KEY, base);
789}
790
791static inline u16 fan_from_reg(u16 reg)
792{
793 return reg ? (1500000 / reg) : 0;
794}
795
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100796static inline u16 fan_to_reg(u16 fan)
797{
798 return fan ? (1500000 / fan) : 0;
799}
800
Hans de Goede45fb3662007-07-13 14:34:19 +0200801static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg)
802{
803 u8 val;
804
805 outb(reg, data->addr + ADDR_REG_OFFSET);
806 val = inb(data->addr + DATA_REG_OFFSET);
807
808 return val;
809}
810
811static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg)
812{
813 u16 val;
814
815 outb(reg++, data->addr + ADDR_REG_OFFSET);
816 val = inb(data->addr + DATA_REG_OFFSET) << 8;
817 outb(reg, data->addr + ADDR_REG_OFFSET);
818 val |= inb(data->addr + DATA_REG_OFFSET);
819
820 return val;
821}
822
823static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)
824{
825 outb(reg, data->addr + ADDR_REG_OFFSET);
826 outb(val, data->addr + DATA_REG_OFFSET);
827}
828
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100829static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)
830{
831 outb(reg++, data->addr + ADDR_REG_OFFSET);
832 outb(val >> 8, data->addr + DATA_REG_OFFSET);
833 outb(reg, data->addr + ADDR_REG_OFFSET);
834 outb(val & 255, data->addr + DATA_REG_OFFSET);
835}
836
Mark van Doesburg77a4a3e2009-01-07 16:37:27 +0100837static struct f71882fg_data *f71882fg_update_device(struct device *dev)
Hans de Goede45fb3662007-07-13 14:34:19 +0200838{
839 struct f71882fg_data *data = dev_get_drvdata(dev);
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100840 int nr, reg = 0, reg2;
841 int nr_fans = (data->type == f71882fg) ? 4 : 3;
842 int nr_ins = (data->type == f8000) ? 3 : 9;
843 int temp_start = (data->type == f8000) ? 0 : 1;
Hans de Goede45fb3662007-07-13 14:34:19 +0200844
845 mutex_lock(&data->update_lock);
846
847 /* Update once every 60 seconds */
848 if ( time_after(jiffies, data->last_limits + 60 * HZ ) ||
849 !data->valid) {
Hans de Goede498be962009-01-07 16:37:28 +0100850 if (data->type == f71882fg) {
851 data->in1_max =
852 f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
853 data->in_beep =
854 f71882fg_read8(data, F71882FG_REG_IN_BEEP);
855 }
Hans de Goede45fb3662007-07-13 14:34:19 +0200856
857 /* Get High & boundary temps*/
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100858 for (nr = temp_start; nr < 3 + temp_start; nr++) {
Hans de Goede45fb3662007-07-13 14:34:19 +0200859 data->temp_ovt[nr] = f71882fg_read8(data,
860 F71882FG_REG_TEMP_OVT(nr));
861 data->temp_high[nr] = f71882fg_read8(data,
862 F71882FG_REG_TEMP_HIGH(nr));
863 }
864
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100865 if (data->type != f8000) {
866 data->fan_beep = f71882fg_read8(data,
867 F71882FG_REG_FAN_BEEP);
868 data->temp_beep = f71882fg_read8(data,
869 F71882FG_REG_TEMP_BEEP);
870 data->temp_hyst[0] = f71882fg_read8(data,
871 F71882FG_REG_TEMP_HYST(0));
872 data->temp_hyst[1] = f71882fg_read8(data,
873 F71882FG_REG_TEMP_HYST(1));
874 /* Have to hardcode type, because temp1 is special */
875 reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
876 data->temp_type[2] = (reg & 0x04) ? 2 : 4;
877 data->temp_type[3] = (reg & 0x08) ? 2 : 4;
878 }
Hans de Goede45fb3662007-07-13 14:34:19 +0200879 reg2 = f71882fg_read8(data, F71882FG_REG_PECI);
880 if ((reg2 & 0x03) == 0x01)
Hans de Goede7567a042009-01-07 16:37:28 +0100881 data->temp_type[1] = 6 /* PECI */;
Hans de Goede45fb3662007-07-13 14:34:19 +0200882 else if ((reg2 & 0x03) == 0x02)
Hans de Goede7567a042009-01-07 16:37:28 +0100883 data->temp_type[1] = 5 /* AMDSI */;
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100884 else if (data->type != f8000)
Hans de Goede7567a042009-01-07 16:37:28 +0100885 data->temp_type[1] = (reg & 0x02) ? 2 : 4;
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100886 else
887 data->temp_type[1] = 2; /* F8000 only supports BJT */
Hans de Goede45fb3662007-07-13 14:34:19 +0200888
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100889 data->pwm_enable = f71882fg_read8(data,
890 F71882FG_REG_PWM_ENABLE);
Hans de Goedebc274902009-01-07 16:37:29 +0100891 data->pwm_auto_point_hyst[0] =
892 f71882fg_read8(data, F71882FG_REG_FAN_HYST(0));
893 data->pwm_auto_point_hyst[1] =
894 f71882fg_read8(data, F71882FG_REG_FAN_HYST(1));
895
Hans de Goede498be962009-01-07 16:37:28 +0100896 for (nr = 0; nr < nr_fans; nr++) {
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100897 data->pwm_auto_point_mapping[nr] =
898 f71882fg_read8(data,
899 F71882FG_REG_POINT_MAPPING(nr));
900
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100901 if (data->type != f71862fg) {
Hans de Goede498be962009-01-07 16:37:28 +0100902 int point;
903 for (point = 0; point < 5; point++) {
904 data->pwm_auto_point_pwm[nr][point] =
905 f71882fg_read8(data,
906 F71882FG_REG_POINT_PWM
907 (nr, point));
908 }
909 for (point = 0; point < 4; point++) {
910 data->pwm_auto_point_temp[nr][point] =
911 f71882fg_read8(data,
912 F71882FG_REG_POINT_TEMP
913 (nr, point));
914 }
915 } else {
916 data->pwm_auto_point_pwm[nr][1] =
917 f71882fg_read8(data,
918 F71882FG_REG_POINT_PWM
919 (nr, 1));
920 data->pwm_auto_point_pwm[nr][4] =
921 f71882fg_read8(data,
922 F71882FG_REG_POINT_PWM
923 (nr, 4));
924 data->pwm_auto_point_temp[nr][0] =
925 f71882fg_read8(data,
926 F71882FG_REG_POINT_TEMP
927 (nr, 0));
928 data->pwm_auto_point_temp[nr][3] =
929 f71882fg_read8(data,
930 F71882FG_REG_POINT_TEMP
931 (nr, 3));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100932 }
933 }
Hans de Goede45fb3662007-07-13 14:34:19 +0200934 data->last_limits = jiffies;
935 }
936
937 /* Update every second */
Mark M. Hoffman8afb1042007-08-21 23:10:46 -0400938 if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
Hans de Goede45fb3662007-07-13 14:34:19 +0200939 data->temp_status = f71882fg_read8(data,
940 F71882FG_REG_TEMP_STATUS);
941 data->temp_diode_open = f71882fg_read8(data,
942 F71882FG_REG_TEMP_DIODE_OPEN);
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100943 for (nr = temp_start; nr < 3 + temp_start; nr++)
Hans de Goede45fb3662007-07-13 14:34:19 +0200944 data->temp[nr] = f71882fg_read8(data,
945 F71882FG_REG_TEMP(nr));
946
947 data->fan_status = f71882fg_read8(data,
948 F71882FG_REG_FAN_STATUS);
Hans de Goede498be962009-01-07 16:37:28 +0100949 for (nr = 0; nr < nr_fans; nr++) {
Hans de Goede45fb3662007-07-13 14:34:19 +0200950 data->fan[nr] = f71882fg_read16(data,
951 F71882FG_REG_FAN(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100952 data->fan_target[nr] =
953 f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr));
954 data->fan_full_speed[nr] =
955 f71882fg_read16(data,
956 F71882FG_REG_FAN_FULL_SPEED(nr));
957 data->pwm[nr] =
958 f71882fg_read8(data, F71882FG_REG_PWM(nr));
959 }
Hans de Goede45fb3662007-07-13 14:34:19 +0200960
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100961 /* The f8000 can monitor 1 more fan, but has no pwm for it */
962 if (data->type == f8000)
963 data->fan[3] = f71882fg_read16(data,
964 F71882FG_REG_FAN(3));
Hans de Goede498be962009-01-07 16:37:28 +0100965 if (data->type == f71882fg)
966 data->in_status = f71882fg_read8(data,
Hans de Goede45fb3662007-07-13 14:34:19 +0200967 F71882FG_REG_IN_STATUS);
Hans de Goedeed4f7c22009-01-07 16:37:30 +0100968 for (nr = 0; nr < nr_ins; nr++)
Hans de Goede45fb3662007-07-13 14:34:19 +0200969 data->in[nr] = f71882fg_read8(data,
970 F71882FG_REG_IN(nr));
971
972 data->last_updated = jiffies;
973 data->valid = 1;
974 }
975
976 mutex_unlock(&data->update_lock);
977
978 return data;
979}
980
981/* Sysfs Interface */
982static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
983 char *buf)
984{
985 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +0100986 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +0200987 int speed = fan_from_reg(data->fan[nr]);
988
989 if (speed == FAN_MIN_DETECT)
990 speed = 0;
991
992 return sprintf(buf, "%d\n", speed);
993}
994
Mark van Doesburg9ab796e2009-01-07 16:37:27 +0100995static ssize_t show_fan_full_speed(struct device *dev,
996 struct device_attribute *devattr, char *buf)
997{
998 struct f71882fg_data *data = f71882fg_update_device(dev);
999 int nr = to_sensor_dev_attr_2(devattr)->index;
1000 int speed = fan_from_reg(data->fan_full_speed[nr]);
1001 return sprintf(buf, "%d\n", speed);
1002}
1003
1004static ssize_t store_fan_full_speed(struct device *dev,
1005 struct device_attribute *devattr,
1006 const char *buf, size_t count)
1007{
1008 struct f71882fg_data *data = dev_get_drvdata(dev);
1009 int nr = to_sensor_dev_attr_2(devattr)->index;
1010 long val = simple_strtol(buf, NULL, 10);
1011
1012 val = SENSORS_LIMIT(val, 23, 1500000);
1013 val = fan_to_reg(val);
1014
1015 mutex_lock(&data->update_lock);
Hans de Goede4c82c382009-01-07 16:37:30 +01001016 f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val);
1017 data->fan_full_speed[nr] = val;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001018 mutex_unlock(&data->update_lock);
1019
1020 return count;
1021}
1022
Hans de Goede45fb3662007-07-13 14:34:19 +02001023static ssize_t show_fan_beep(struct device *dev, struct device_attribute
1024 *devattr, char *buf)
1025{
1026 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001027 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001028
1029 if (data->fan_beep & (1 << nr))
1030 return sprintf(buf, "1\n");
1031 else
1032 return sprintf(buf, "0\n");
1033}
1034
1035static ssize_t store_fan_beep(struct device *dev, struct device_attribute
1036 *devattr, const char *buf, size_t count)
1037{
1038 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001039 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001040 unsigned long val = simple_strtoul(buf, NULL, 10);
Hans de Goede45fb3662007-07-13 14:34:19 +02001041
1042 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001043 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001044 if (val)
1045 data->fan_beep |= 1 << nr;
1046 else
1047 data->fan_beep &= ~(1 << nr);
1048
1049 f71882fg_write8(data, F71882FG_REG_FAN_BEEP, data->fan_beep);
1050 mutex_unlock(&data->update_lock);
1051
1052 return count;
1053}
1054
1055static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
1056 *devattr, char *buf)
1057{
1058 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001059 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001060
1061 if (data->fan_status & (1 << nr))
1062 return sprintf(buf, "1\n");
1063 else
1064 return sprintf(buf, "0\n");
1065}
1066
1067static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
1068 char *buf)
1069{
1070 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001071 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001072
1073 return sprintf(buf, "%d\n", data->in[nr] * 8);
1074}
1075
1076static ssize_t show_in_max(struct device *dev, struct device_attribute
1077 *devattr, char *buf)
1078{
1079 struct f71882fg_data *data = f71882fg_update_device(dev);
1080
1081 return sprintf(buf, "%d\n", data->in1_max * 8);
1082}
1083
1084static ssize_t store_in_max(struct device *dev, struct device_attribute
1085 *devattr, const char *buf, size_t count)
1086{
1087 struct f71882fg_data *data = dev_get_drvdata(dev);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001088 long val = simple_strtol(buf, NULL, 10) / 8;
1089 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001090
1091 mutex_lock(&data->update_lock);
1092 f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
1093 data->in1_max = val;
1094 mutex_unlock(&data->update_lock);
1095
1096 return count;
1097}
1098
1099static ssize_t show_in_beep(struct device *dev, struct device_attribute
1100 *devattr, char *buf)
1101{
1102 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001103 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001104
1105 if (data->in_beep & (1 << nr))
1106 return sprintf(buf, "1\n");
1107 else
1108 return sprintf(buf, "0\n");
1109}
1110
1111static ssize_t store_in_beep(struct device *dev, struct device_attribute
1112 *devattr, const char *buf, size_t count)
1113{
1114 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001115 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001116 unsigned long val = simple_strtoul(buf, NULL, 10);
Hans de Goede45fb3662007-07-13 14:34:19 +02001117
1118 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001119 data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001120 if (val)
1121 data->in_beep |= 1 << nr;
1122 else
1123 data->in_beep &= ~(1 << nr);
1124
1125 f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep);
1126 mutex_unlock(&data->update_lock);
1127
1128 return count;
1129}
1130
1131static ssize_t show_in_alarm(struct device *dev, struct device_attribute
1132 *devattr, char *buf)
1133{
1134 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001135 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001136
1137 if (data->in_status & (1 << nr))
1138 return sprintf(buf, "1\n");
1139 else
1140 return sprintf(buf, "0\n");
1141}
1142
1143static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
1144 char *buf)
1145{
1146 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001147 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001148
1149 return sprintf(buf, "%d\n", data->temp[nr] * 1000);
1150}
1151
1152static ssize_t show_temp_max(struct device *dev, struct device_attribute
1153 *devattr, char *buf)
1154{
1155 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001156 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001157
1158 return sprintf(buf, "%d\n", data->temp_high[nr] * 1000);
1159}
1160
1161static ssize_t store_temp_max(struct device *dev, struct device_attribute
1162 *devattr, const char *buf, size_t count)
1163{
1164 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001165 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001166 long val = simple_strtol(buf, NULL, 10) / 1000;
1167 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001168
1169 mutex_lock(&data->update_lock);
1170 f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val);
1171 data->temp_high[nr] = val;
1172 mutex_unlock(&data->update_lock);
1173
1174 return count;
1175}
1176
1177static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
1178 *devattr, char *buf)
1179{
1180 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001181 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001182 int temp_max_hyst;
Hans de Goede45fb3662007-07-13 14:34:19 +02001183
Hans de Goedece0bfa52009-01-07 16:37:28 +01001184 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001185 if (nr & 1)
1186 temp_max_hyst = data->temp_hyst[nr / 2] >> 4;
1187 else
1188 temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f;
1189 temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001190 mutex_unlock(&data->update_lock);
1191
1192 return sprintf(buf, "%d\n", temp_max_hyst);
Hans de Goede45fb3662007-07-13 14:34:19 +02001193}
1194
1195static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
1196 *devattr, const char *buf, size_t count)
1197{
1198 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001199 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001200 long val = simple_strtol(buf, NULL, 10) / 1000;
Hans de Goede45fb3662007-07-13 14:34:19 +02001201 ssize_t ret = count;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001202 u8 reg;
Hans de Goede45fb3662007-07-13 14:34:19 +02001203
1204 mutex_lock(&data->update_lock);
1205
1206 /* convert abs to relative and check */
Hans de Goedece0bfa52009-01-07 16:37:28 +01001207 data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr));
1208 val = SENSORS_LIMIT(val, data->temp_high[nr] - 15,
1209 data->temp_high[nr]);
Hans de Goede45fb3662007-07-13 14:34:19 +02001210 val = data->temp_high[nr] - val;
Hans de Goede45fb3662007-07-13 14:34:19 +02001211
1212 /* convert value to register contents */
Hans de Goedebc274902009-01-07 16:37:29 +01001213 reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2));
1214 if (nr & 1)
1215 reg = (reg & 0x0f) | (val << 4);
1216 else
1217 reg = (reg & 0xf0) | val;
1218 f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg);
1219 data->temp_hyst[nr / 2] = reg;
Hans de Goede45fb3662007-07-13 14:34:19 +02001220
Hans de Goede45fb3662007-07-13 14:34:19 +02001221 mutex_unlock(&data->update_lock);
1222 return ret;
1223}
1224
1225static ssize_t show_temp_crit(struct device *dev, struct device_attribute
1226 *devattr, char *buf)
1227{
1228 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001229 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001230
1231 return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000);
1232}
1233
1234static ssize_t store_temp_crit(struct device *dev, struct device_attribute
1235 *devattr, const char *buf, size_t count)
1236{
1237 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001238 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001239 long val = simple_strtol(buf, NULL, 10) / 1000;
1240 val = SENSORS_LIMIT(val, 0, 255);
Hans de Goede45fb3662007-07-13 14:34:19 +02001241
1242 mutex_lock(&data->update_lock);
1243 f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val);
1244 data->temp_ovt[nr] = val;
1245 mutex_unlock(&data->update_lock);
1246
1247 return count;
1248}
1249
1250static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
1251 *devattr, char *buf)
1252{
1253 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001254 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001255 int temp_crit_hyst;
Hans de Goede45fb3662007-07-13 14:34:19 +02001256
Hans de Goedece0bfa52009-01-07 16:37:28 +01001257 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001258 if (nr & 1)
1259 temp_crit_hyst = data->temp_hyst[nr / 2] >> 4;
1260 else
1261 temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f;
1262 temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001263 mutex_unlock(&data->update_lock);
1264
1265 return sprintf(buf, "%d\n", temp_crit_hyst);
Hans de Goede45fb3662007-07-13 14:34:19 +02001266}
1267
1268static ssize_t show_temp_type(struct device *dev, struct device_attribute
1269 *devattr, char *buf)
1270{
1271 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001272 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001273
1274 return sprintf(buf, "%d\n", data->temp_type[nr]);
1275}
1276
1277static ssize_t show_temp_beep(struct device *dev, struct device_attribute
1278 *devattr, char *buf)
1279{
1280 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001281 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001282
Hans de Goede7567a042009-01-07 16:37:28 +01001283 if (data->temp_beep & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001284 return sprintf(buf, "1\n");
1285 else
1286 return sprintf(buf, "0\n");
1287}
1288
1289static ssize_t store_temp_beep(struct device *dev, struct device_attribute
1290 *devattr, const char *buf, size_t count)
1291{
1292 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001293 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001294 unsigned long val = simple_strtoul(buf, NULL, 10);
Hans de Goede45fb3662007-07-13 14:34:19 +02001295
1296 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001297 data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);
Hans de Goede45fb3662007-07-13 14:34:19 +02001298 if (val)
Hans de Goede7567a042009-01-07 16:37:28 +01001299 data->temp_beep |= 1 << nr;
Hans de Goede45fb3662007-07-13 14:34:19 +02001300 else
Hans de Goede7567a042009-01-07 16:37:28 +01001301 data->temp_beep &= ~(1 << nr);
Hans de Goede45fb3662007-07-13 14:34:19 +02001302
1303 f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep);
1304 mutex_unlock(&data->update_lock);
1305
1306 return count;
1307}
1308
1309static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
1310 *devattr, char *buf)
1311{
1312 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001313 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001314
Hans de Goede7567a042009-01-07 16:37:28 +01001315 if (data->temp_status & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001316 return sprintf(buf, "1\n");
1317 else
1318 return sprintf(buf, "0\n");
1319}
1320
1321static ssize_t show_temp_fault(struct device *dev, struct device_attribute
1322 *devattr, char *buf)
1323{
1324 struct f71882fg_data *data = f71882fg_update_device(dev);
Mark van Doesburgbc37ae72009-01-07 16:37:27 +01001325 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goede45fb3662007-07-13 14:34:19 +02001326
Hans de Goede7567a042009-01-07 16:37:28 +01001327 if (data->temp_diode_open & (1 << nr))
Hans de Goede45fb3662007-07-13 14:34:19 +02001328 return sprintf(buf, "1\n");
1329 else
1330 return sprintf(buf, "0\n");
1331}
1332
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001333static ssize_t show_pwm(struct device *dev,
1334 struct device_attribute *devattr, char *buf)
1335{
1336 struct f71882fg_data *data = f71882fg_update_device(dev);
1337 int val, nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001338 mutex_lock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001339 if (data->pwm_enable & (1 << (2 * nr)))
1340 /* PWM mode */
1341 val = data->pwm[nr];
1342 else {
1343 /* RPM mode */
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001344 val = 255 * fan_from_reg(data->fan_target[nr])
1345 / fan_from_reg(data->fan_full_speed[nr]);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001346 }
Hans de Goedece0bfa52009-01-07 16:37:28 +01001347 mutex_unlock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001348 return sprintf(buf, "%d\n", val);
1349}
1350
1351static ssize_t store_pwm(struct device *dev,
1352 struct device_attribute *devattr, const char *buf,
1353 size_t count)
1354{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001355 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001356 int nr = to_sensor_dev_attr_2(devattr)->index;
1357 long val = simple_strtol(buf, NULL, 10);
1358 val = SENSORS_LIMIT(val, 0, 255);
1359
1360 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001361 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001362 if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) ||
1363 (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) {
1364 count = -EROFS;
1365 goto leave;
1366 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001367 if (data->pwm_enable & (1 << (2 * nr))) {
1368 /* PWM mode */
1369 f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
1370 data->pwm[nr] = val;
1371 } else {
1372 /* RPM mode */
Hans de Goedece0bfa52009-01-07 16:37:28 +01001373 int target, full_speed;
1374 full_speed = f71882fg_read16(data,
1375 F71882FG_REG_FAN_FULL_SPEED(nr));
1376 target = fan_to_reg(val * fan_from_reg(full_speed) / 255);
1377 f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target);
1378 data->fan_target[nr] = target;
1379 data->fan_full_speed[nr] = full_speed;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001380 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001381leave:
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001382 mutex_unlock(&data->update_lock);
1383
1384 return count;
1385}
1386
1387static ssize_t show_pwm_enable(struct device *dev,
1388 struct device_attribute *devattr, char *buf)
1389{
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001390 int result = 0;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001391 struct f71882fg_data *data = f71882fg_update_device(dev);
1392 int nr = to_sensor_dev_attr_2(devattr)->index;
1393
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001394 switch ((data->pwm_enable >> 2 * nr) & 3) {
1395 case 0:
1396 case 1:
1397 result = 2; /* Normal auto mode */
1398 break;
1399 case 2:
1400 result = 1; /* Manual mode */
1401 break;
1402 case 3:
1403 if (data->type == f8000)
1404 result = 3; /* Thermostat mode */
1405 else
1406 result = 1; /* Manual mode */
1407 break;
1408 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001409
1410 return sprintf(buf, "%d\n", result);
1411}
1412
1413static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
1414 *devattr, const char *buf, size_t count)
1415{
1416 struct f71882fg_data *data = dev_get_drvdata(dev);
1417 int nr = to_sensor_dev_attr_2(devattr)->index;
1418 long val = simple_strtol(buf, NULL, 10);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001419
1420 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001421 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001422 /* Special case for F8000 auto PWM mode / Thermostat mode */
1423 if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) {
1424 switch (val) {
1425 case 2:
1426 data->pwm_enable &= ~(2 << (2 * nr));
1427 break; /* Normal auto mode */
1428 case 3:
1429 data->pwm_enable |= 2 << (2 * nr);
1430 break; /* Thermostat mode */
1431 default:
1432 count = -EINVAL;
1433 goto leave;
1434 }
1435 } else {
1436 switch (val) {
1437 case 1:
1438 data->pwm_enable |= 2 << (2 * nr);
1439 break; /* Manual */
1440 case 2:
1441 data->pwm_enable &= ~(2 << (2 * nr));
1442 break; /* Normal auto mode */
1443 default:
1444 count = -EINVAL;
1445 goto leave;
1446 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001447 }
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001448 f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001449leave:
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001450 mutex_unlock(&data->update_lock);
1451
1452 return count;
1453}
1454
1455static ssize_t show_pwm_auto_point_pwm(struct device *dev,
1456 struct device_attribute *devattr,
1457 char *buf)
1458{
1459 int result;
1460 struct f71882fg_data *data = f71882fg_update_device(dev);
1461 int pwm = to_sensor_dev_attr_2(devattr)->index;
1462 int point = to_sensor_dev_attr_2(devattr)->nr;
1463
Hans de Goedece0bfa52009-01-07 16:37:28 +01001464 mutex_lock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001465 if (data->pwm_enable & (1 << (2 * pwm))) {
1466 /* PWM mode */
1467 result = data->pwm_auto_point_pwm[pwm][point];
1468 } else {
1469 /* RPM mode */
1470 result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]);
1471 }
Hans de Goedece0bfa52009-01-07 16:37:28 +01001472 mutex_unlock(&data->update_lock);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001473
1474 return sprintf(buf, "%d\n", result);
1475}
1476
1477static ssize_t store_pwm_auto_point_pwm(struct device *dev,
1478 struct device_attribute *devattr,
1479 const char *buf, size_t count)
1480{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001481 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001482 int pwm = to_sensor_dev_attr_2(devattr)->index;
1483 int point = to_sensor_dev_attr_2(devattr)->nr;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001484 long val = simple_strtol(buf, NULL, 10);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001485 val = SENSORS_LIMIT(val, 0, 255);
1486
1487 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001488 data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001489 if (data->pwm_enable & (1 << (2 * pwm))) {
1490 /* PWM mode */
1491 } else {
1492 /* RPM mode */
1493 if (val < 29) /* Prevent negative numbers */
1494 val = 255;
1495 else
1496 val = (255 - val) * 32 / val;
1497 }
1498 f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val);
1499 data->pwm_auto_point_pwm[pwm][point] = val;
1500 mutex_unlock(&data->update_lock);
1501
1502 return count;
1503}
1504
1505static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
1506 struct device_attribute *devattr,
1507 char *buf)
1508{
1509 int result = 0;
1510 struct f71882fg_data *data = f71882fg_update_device(dev);
1511 int nr = to_sensor_dev_attr_2(devattr)->index;
1512 int point = to_sensor_dev_attr_2(devattr)->nr;
1513
1514 mutex_lock(&data->update_lock);
Hans de Goedebc274902009-01-07 16:37:29 +01001515 if (nr & 1)
1516 result = data->pwm_auto_point_hyst[nr / 2] >> 4;
1517 else
1518 result = data->pwm_auto_point_hyst[nr / 2] & 0x0f;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001519 result = 1000 * (data->pwm_auto_point_temp[nr][point] - result);
1520 mutex_unlock(&data->update_lock);
1521
1522 return sprintf(buf, "%d\n", result);
1523}
1524
1525static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
1526 struct device_attribute *devattr,
1527 const char *buf, size_t count)
1528{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001529 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001530 int nr = to_sensor_dev_attr_2(devattr)->index;
1531 int point = to_sensor_dev_attr_2(devattr)->nr;
1532 long val = simple_strtol(buf, NULL, 10) / 1000;
Hans de Goedebc274902009-01-07 16:37:29 +01001533 u8 reg;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001534
1535 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001536 data->pwm_auto_point_temp[nr][point] =
1537 f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001538 val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15,
1539 data->pwm_auto_point_temp[nr][point]);
1540 val = data->pwm_auto_point_temp[nr][point] - val;
1541
Hans de Goedebc274902009-01-07 16:37:29 +01001542 reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2));
1543 if (nr & 1)
1544 reg = (reg & 0x0f) | (val << 4);
1545 else
1546 reg = (reg & 0xf0) | val;
1547
1548 f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg);
1549 data->pwm_auto_point_hyst[nr / 2] = reg;
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001550 mutex_unlock(&data->update_lock);
1551
1552 return count;
1553}
1554
1555static ssize_t show_pwm_interpolate(struct device *dev,
1556 struct device_attribute *devattr, char *buf)
1557{
1558 int result;
1559 struct f71882fg_data *data = f71882fg_update_device(dev);
1560 int nr = to_sensor_dev_attr_2(devattr)->index;
1561
1562 result = (data->pwm_auto_point_mapping[nr] >> 4) & 1;
1563
1564 return sprintf(buf, "%d\n", result);
1565}
1566
1567static ssize_t store_pwm_interpolate(struct device *dev,
1568 struct device_attribute *devattr,
1569 const char *buf, size_t count)
1570{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001571 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001572 int nr = to_sensor_dev_attr_2(devattr)->index;
Hans de Goedece0bfa52009-01-07 16:37:28 +01001573 unsigned long val = simple_strtoul(buf, NULL, 10);
1574
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001575 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001576 data->pwm_auto_point_mapping[nr] =
1577 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001578 if (val)
1579 val = data->pwm_auto_point_mapping[nr] | (1 << 4);
1580 else
1581 val = data->pwm_auto_point_mapping[nr] & (~(1 << 4));
1582 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1583 data->pwm_auto_point_mapping[nr] = val;
1584 mutex_unlock(&data->update_lock);
1585
1586 return count;
1587}
1588
1589static ssize_t show_pwm_auto_point_channel(struct device *dev,
1590 struct device_attribute *devattr,
1591 char *buf)
1592{
1593 int result;
1594 struct f71882fg_data *data = f71882fg_update_device(dev);
1595 int nr = to_sensor_dev_attr_2(devattr)->index;
1596
1597 result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - 1);
1598
1599 return sprintf(buf, "%d\n", result);
1600}
1601
1602static ssize_t store_pwm_auto_point_channel(struct device *dev,
1603 struct device_attribute *devattr,
1604 const char *buf, size_t count)
1605{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001606 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001607 int nr = to_sensor_dev_attr_2(devattr)->index;
1608 long val = simple_strtol(buf, NULL, 10);
1609 switch (val) {
1610 case 1:
1611 val = 1;
1612 break;
1613 case 2:
1614 val = 2;
1615 break;
1616 case 4:
1617 val = 3;
1618 break;
1619 default:
1620 return -EINVAL;
1621 }
1622 mutex_lock(&data->update_lock);
Hans de Goedece0bfa52009-01-07 16:37:28 +01001623 data->pwm_auto_point_mapping[nr] =
1624 f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001625 val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val;
1626 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1627 data->pwm_auto_point_mapping[nr] = val;
1628 mutex_unlock(&data->update_lock);
1629
1630 return count;
1631}
1632
1633static ssize_t show_pwm_auto_point_temp(struct device *dev,
1634 struct device_attribute *devattr,
1635 char *buf)
1636{
1637 int result;
1638 struct f71882fg_data *data = f71882fg_update_device(dev);
1639 int pwm = to_sensor_dev_attr_2(devattr)->index;
1640 int point = to_sensor_dev_attr_2(devattr)->nr;
1641
1642 result = data->pwm_auto_point_temp[pwm][point];
1643 return sprintf(buf, "%d\n", 1000 * result);
1644}
1645
1646static ssize_t store_pwm_auto_point_temp(struct device *dev,
1647 struct device_attribute *devattr,
1648 const char *buf, size_t count)
1649{
Hans de Goedece0bfa52009-01-07 16:37:28 +01001650 struct f71882fg_data *data = dev_get_drvdata(dev);
Mark van Doesburg9ab796e2009-01-07 16:37:27 +01001651 int pwm = to_sensor_dev_attr_2(devattr)->index;
1652 int point = to_sensor_dev_attr_2(devattr)->nr;
1653 long val = simple_strtol(buf, NULL, 10) / 1000;
1654 val = SENSORS_LIMIT(val, 0, 255);
1655
1656 mutex_lock(&data->update_lock);
1657 f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
1658 data->pwm_auto_point_temp[pwm][point] = val;
1659 mutex_unlock(&data->update_lock);
1660
1661 return count;
1662}
1663
Hans de Goede45fb3662007-07-13 14:34:19 +02001664static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
1665 char *buf)
1666{
Hans de Goede498be962009-01-07 16:37:28 +01001667 struct f71882fg_data *data = dev_get_drvdata(dev);
1668 return sprintf(buf, "%s\n", f71882fg_names[data->type]);
Hans de Goede45fb3662007-07-13 14:34:19 +02001669}
1670
Hans de Goedec13548c2009-01-07 16:37:27 +01001671static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
1672 struct sensor_device_attribute_2 *attr, int count)
1673{
1674 int err, i;
Hans de Goede45fb3662007-07-13 14:34:19 +02001675
Hans de Goedec13548c2009-01-07 16:37:27 +01001676 for (i = 0; i < count; i++) {
1677 err = device_create_file(&pdev->dev, &attr[i].dev_attr);
1678 if (err)
1679 return err;
1680 }
1681 return 0;
1682}
1683
1684static int __devinit f71882fg_probe(struct platform_device *pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02001685{
1686 struct f71882fg_data *data;
Hans de Goede498be962009-01-07 16:37:28 +01001687 struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
Hans de Goedec13548c2009-01-07 16:37:27 +01001688 int err;
Hans de Goede45fb3662007-07-13 14:34:19 +02001689 u8 start_reg;
1690
Hans de Goedec13548c2009-01-07 16:37:27 +01001691 data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
1692 if (!data)
Hans de Goede45fb3662007-07-13 14:34:19 +02001693 return -ENOMEM;
1694
1695 data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
Hans de Goede498be962009-01-07 16:37:28 +01001696 data->type = sio_data->type;
Hans de Goede45fb3662007-07-13 14:34:19 +02001697 mutex_init(&data->update_lock);
1698 platform_set_drvdata(pdev, data);
1699
Hans de Goede3cc74752009-01-07 16:37:28 +01001700 start_reg = f71882fg_read8(data, F71882FG_REG_START);
Hans de Goede12d66e82009-01-07 16:37:29 +01001701 if (start_reg & 0x04) {
1702 dev_warn(&pdev->dev, "Hardware monitor is powered down\n");
1703 err = -ENODEV;
1704 goto exit_free;
1705 }
Hans de Goede3cc74752009-01-07 16:37:28 +01001706 if (!(start_reg & 0x03)) {
1707 dev_warn(&pdev->dev, "Hardware monitoring not activated\n");
1708 err = -ENODEV;
1709 goto exit_free;
1710 }
1711
1712 /* If it is a 71862 and the fan / pwm part is enabled sanity check
1713 the pwm settings */
1714 if (data->type == f71862fg && (start_reg & 0x02)) {
1715 u8 reg = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
1716 if ((reg & 0x15) != 0x15) {
1717 dev_err(&pdev->dev,
1718 "Invalid (reserved) pwm settings: 0x%02x\n",
1719 (unsigned int)reg);
1720 err = -ENODEV;
1721 goto exit_free;
1722 }
1723 }
1724
Hans de Goede45fb3662007-07-13 14:34:19 +02001725 /* Register sysfs interface files */
Hans de Goedec13548c2009-01-07 16:37:27 +01001726 err = device_create_file(&pdev->dev, &dev_attr_name);
1727 if (err)
1728 goto exit_unregister_sysfs;
1729
Hans de Goedec13548c2009-01-07 16:37:27 +01001730 if (start_reg & 0x01) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001731 switch (data->type) {
1732 case f71882fg:
Hans de Goede498be962009-01-07 16:37:28 +01001733 err = f71882fg_create_sysfs_files(pdev,
1734 f71882fg_in_temp_attr,
1735 ARRAY_SIZE(f71882fg_in_temp_attr));
1736 if (err)
1737 goto exit_unregister_sysfs;
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001738 /* fall through! */
1739 case f71862fg:
1740 err = f71882fg_create_sysfs_files(pdev,
1741 f718x2fg_in_temp_attr,
1742 ARRAY_SIZE(f718x2fg_in_temp_attr));
1743 break;
1744 case f8000:
1745 err = f71882fg_create_sysfs_files(pdev,
1746 f8000_in_temp_attr,
1747 ARRAY_SIZE(f8000_in_temp_attr));
1748 break;
Hans de Goede498be962009-01-07 16:37:28 +01001749 }
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001750 if (err)
1751 goto exit_unregister_sysfs;
Hans de Goede45fb3662007-07-13 14:34:19 +02001752 }
1753
Hans de Goede45fb3662007-07-13 14:34:19 +02001754 if (start_reg & 0x02) {
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001755 err = f71882fg_create_sysfs_files(pdev, fxxxx_fan_attr,
1756 ARRAY_SIZE(fxxxx_fan_attr));
Hans de Goede498be962009-01-07 16:37:28 +01001757 if (err)
1758 goto exit_unregister_sysfs;
1759
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001760 switch (data->type) {
1761 case f71862fg:
Hans de Goede498be962009-01-07 16:37:28 +01001762 err = f71882fg_create_sysfs_files(pdev,
1763 f71862fg_fan_attr,
1764 ARRAY_SIZE(f71862fg_fan_attr));
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001765 break;
1766 case f71882fg:
Hans de Goede498be962009-01-07 16:37:28 +01001767 err = f71882fg_create_sysfs_files(pdev,
1768 f71882fg_fan_attr,
Hans de Goedec13548c2009-01-07 16:37:27 +01001769 ARRAY_SIZE(f71882fg_fan_attr));
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001770 break;
1771 case f8000:
1772 err = f71882fg_create_sysfs_files(pdev,
1773 f8000_fan_attr,
1774 ARRAY_SIZE(f8000_fan_attr));
1775 break;
Hans de Goede498be962009-01-07 16:37:28 +01001776 }
Hans de Goedec13548c2009-01-07 16:37:27 +01001777 if (err)
1778 goto exit_unregister_sysfs;
Hans de Goede45fb3662007-07-13 14:34:19 +02001779 }
1780
Tony Jones1beeffe2007-08-20 13:46:20 -07001781 data->hwmon_dev = hwmon_device_register(&pdev->dev);
1782 if (IS_ERR(data->hwmon_dev)) {
1783 err = PTR_ERR(data->hwmon_dev);
Hans de Goedec13548c2009-01-07 16:37:27 +01001784 data->hwmon_dev = NULL;
Hans de Goede45fb3662007-07-13 14:34:19 +02001785 goto exit_unregister_sysfs;
1786 }
1787
1788 return 0;
1789
1790exit_unregister_sysfs:
Hans de Goedec13548c2009-01-07 16:37:27 +01001791 f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
Hans de Goede3cc74752009-01-07 16:37:28 +01001792 return err; /* f71882fg_remove() also frees our data */
1793exit_free:
1794 kfree(data);
Hans de Goede45fb3662007-07-13 14:34:19 +02001795 return err;
1796}
1797
Hans de Goedec13548c2009-01-07 16:37:27 +01001798static int f71882fg_remove(struct platform_device *pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02001799{
1800 int i;
1801 struct f71882fg_data *data = platform_get_drvdata(pdev);
1802
1803 platform_set_drvdata(pdev, NULL);
Hans de Goedec13548c2009-01-07 16:37:27 +01001804 if (data->hwmon_dev)
1805 hwmon_device_unregister(data->hwmon_dev);
Hans de Goede45fb3662007-07-13 14:34:19 +02001806
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001807 /* Note we are not looping over all attr arrays we have as the ones
1808 below are supersets of the ones skipped. */
Hans de Goedec13548c2009-01-07 16:37:27 +01001809 device_remove_file(&pdev->dev, &dev_attr_name);
Hans de Goede45fb3662007-07-13 14:34:19 +02001810
Hans de Goede498be962009-01-07 16:37:28 +01001811 for (i = 0; i < ARRAY_SIZE(f718x2fg_in_temp_attr); i++)
1812 device_remove_file(&pdev->dev,
1813 &f718x2fg_in_temp_attr[i].dev_attr);
1814
Hans de Goede45fb3662007-07-13 14:34:19 +02001815 for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++)
1816 device_remove_file(&pdev->dev,
1817 &f71882fg_in_temp_attr[i].dev_attr);
1818
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001819 for (i = 0; i < ARRAY_SIZE(fxxxx_fan_attr); i++)
1820 device_remove_file(&pdev->dev, &fxxxx_fan_attr[i].dev_attr);
Hans de Goede498be962009-01-07 16:37:28 +01001821
Hans de Goede45fb3662007-07-13 14:34:19 +02001822 for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++)
1823 device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr);
1824
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001825 for (i = 0; i < ARRAY_SIZE(f8000_fan_attr); i++)
1826 device_remove_file(&pdev->dev, &f8000_fan_attr[i].dev_attr);
1827
Hans de Goede45fb3662007-07-13 14:34:19 +02001828 kfree(data);
1829
1830 return 0;
1831}
1832
Hans de Goede498be962009-01-07 16:37:28 +01001833static int __init f71882fg_find(int sioaddr, unsigned short *address,
1834 struct f71882fg_sio_data *sio_data)
Hans de Goede45fb3662007-07-13 14:34:19 +02001835{
1836 int err = -ENODEV;
1837 u16 devid;
Hans de Goede45fb3662007-07-13 14:34:19 +02001838
1839 superio_enter(sioaddr);
1840
1841 devid = superio_inw(sioaddr, SIO_REG_MANID);
1842 if (devid != SIO_FINTEK_ID) {
1843 printk(KERN_INFO DRVNAME ": Not a Fintek device\n");
1844 goto exit;
1845 }
1846
Jean Delvare67b671b2007-12-06 23:13:42 +01001847 devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
Hans de Goede498be962009-01-07 16:37:28 +01001848 switch (devid) {
1849 case SIO_F71862_ID:
1850 sio_data->type = f71862fg;
1851 break;
1852 case SIO_F71882_ID:
1853 sio_data->type = f71882fg;
1854 break;
Hans de Goedeed4f7c22009-01-07 16:37:30 +01001855 case SIO_F8000_ID:
1856 sio_data->type = f8000;
1857 break;
Hans de Goede498be962009-01-07 16:37:28 +01001858 default:
Hans de Goede45fb3662007-07-13 14:34:19 +02001859 printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n");
1860 goto exit;
1861 }
1862
1863 superio_select(sioaddr, SIO_F71882FG_LD_HWM);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04001864 if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001865 printk(KERN_WARNING DRVNAME ": Device not activated\n");
1866 goto exit;
1867 }
1868
1869 *address = superio_inw(sioaddr, SIO_REG_ADDR);
1870 if (*address == 0)
1871 {
1872 printk(KERN_WARNING DRVNAME ": Base address not set\n");
1873 goto exit;
1874 }
1875 *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
1876
Hans de Goede45fb3662007-07-13 14:34:19 +02001877 err = 0;
Hans de Goede498be962009-01-07 16:37:28 +01001878 printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n",
1879 f71882fg_names[sio_data->type], (unsigned int)*address,
Hans de Goede45fb3662007-07-13 14:34:19 +02001880 (int)superio_inb(sioaddr, SIO_REG_DEVREV));
1881exit:
1882 superio_exit(sioaddr);
1883 return err;
1884}
1885
Hans de Goede498be962009-01-07 16:37:28 +01001886static int __init f71882fg_device_add(unsigned short address,
1887 const struct f71882fg_sio_data *sio_data)
Hans de Goede45fb3662007-07-13 14:34:19 +02001888{
1889 struct resource res = {
1890 .start = address,
1891 .end = address + REGION_LENGTH - 1,
1892 .flags = IORESOURCE_IO,
1893 };
1894 int err;
1895
1896 f71882fg_pdev = platform_device_alloc(DRVNAME, address);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04001897 if (!f71882fg_pdev)
Hans de Goede45fb3662007-07-13 14:34:19 +02001898 return -ENOMEM;
1899
1900 res.name = f71882fg_pdev->name;
1901 err = platform_device_add_resources(f71882fg_pdev, &res, 1);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04001902 if (err) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001903 printk(KERN_ERR DRVNAME ": Device resource addition failed\n");
1904 goto exit_device_put;
1905 }
1906
Hans de Goede498be962009-01-07 16:37:28 +01001907 err = platform_device_add_data(f71882fg_pdev, sio_data,
1908 sizeof(struct f71882fg_sio_data));
1909 if (err) {
1910 printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
1911 goto exit_device_put;
1912 }
1913
Hans de Goede45fb3662007-07-13 14:34:19 +02001914 err = platform_device_add(f71882fg_pdev);
Mark M. Hoffman8afb1042007-08-21 23:10:46 -04001915 if (err) {
Hans de Goede45fb3662007-07-13 14:34:19 +02001916 printk(KERN_ERR DRVNAME ": Device addition failed\n");
1917 goto exit_device_put;
1918 }
1919
1920 return 0;
1921
1922exit_device_put:
1923 platform_device_put(f71882fg_pdev);
1924
1925 return err;
1926}
1927
1928static int __init f71882fg_init(void)
1929{
1930 int err = -ENODEV;
1931 unsigned short address;
Hans de Goede498be962009-01-07 16:37:28 +01001932 struct f71882fg_sio_data sio_data;
Hans de Goede45fb3662007-07-13 14:34:19 +02001933
Hans de Goede498be962009-01-07 16:37:28 +01001934 memset(&sio_data, 0, sizeof(sio_data));
1935
1936 if (f71882fg_find(0x2e, &address, &sio_data) &&
1937 f71882fg_find(0x4e, &address, &sio_data))
Hans de Goede45fb3662007-07-13 14:34:19 +02001938 goto exit;
1939
Hans de Goedec13548c2009-01-07 16:37:27 +01001940 err = platform_driver_register(&f71882fg_driver);
1941 if (err)
Hans de Goede45fb3662007-07-13 14:34:19 +02001942 goto exit;
1943
Hans de Goede498be962009-01-07 16:37:28 +01001944 err = f71882fg_device_add(address, &sio_data);
Hans de Goedec13548c2009-01-07 16:37:27 +01001945 if (err)
Hans de Goede45fb3662007-07-13 14:34:19 +02001946 goto exit_driver;
1947
1948 return 0;
1949
1950exit_driver:
1951 platform_driver_unregister(&f71882fg_driver);
1952exit:
1953 return err;
1954}
1955
1956static void __exit f71882fg_exit(void)
1957{
1958 platform_device_unregister(f71882fg_pdev);
1959 platform_driver_unregister(&f71882fg_driver);
1960}
1961
1962MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");
Hans de Goedec13548c2009-01-07 16:37:27 +01001963MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)");
Hans de Goede45fb3662007-07-13 14:34:19 +02001964MODULE_LICENSE("GPL");
1965
1966module_init(f71882fg_init);
1967module_exit(f71882fg_exit);