aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/f71882fg.c
diff options
context:
space:
mode:
authorMark van Doesburg <mark.vandoesburg@hetnet.nl>2009-01-07 10:37:27 -0500
committerJean Delvare <khali@linux-fr.org>2009-01-07 10:37:27 -0500
commit9ab796ebe185257013f0ac505ecbe7abf068a608 (patch)
treedd9d6ef57ab173538fb7fe3d889fa2f4b4cf7706 /drivers/hwmon/f71882fg.c
parent77a4a3e2a36aea5896f86653f6b77168d578c962 (diff)
hwmon: (f71882fg) Add PWM support
Add PWM (fan speed control) support to the f71882fg driver. Both manual control and automatic (temperature-based) modes are supported. Additionally, each mode has a PWM-based and an RPM-based variant. By default we use the mode set by the BIOS. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Cc: Mark van Doesburg <mark.vandoesburg@hetnet.nl> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/f71882fg.c')
-rw-r--r--drivers/hwmon/f71882fg.c656
1 files changed, 655 insertions, 1 deletions
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index c6fa8578bdeb..c04108735f3f 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -57,6 +57,8 @@
57#define F71882FG_REG_IN1_HIGH 0x32 57#define F71882FG_REG_IN1_HIGH 0x32
58 58
59#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr))) 59#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr)))
60#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))
61#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))
60#define F71882FG_REG_FAN_STATUS 0x92 62#define F71882FG_REG_FAN_STATUS 0x92
61#define F71882FG_REG_FAN_BEEP 0x93 63#define F71882FG_REG_FAN_BEEP 0x93
62 64
@@ -70,6 +72,17 @@
70#define F71882FG_REG_TEMP_TYPE 0x6B 72#define F71882FG_REG_TEMP_TYPE 0x6B
71#define F71882FG_REG_TEMP_DIODE_OPEN 0x6F 73#define F71882FG_REG_TEMP_DIODE_OPEN 0x6F
72 74
75#define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr)))
76#define F71882FG_REG_PWM_TYPE 0x94
77#define F71882FG_REG_PWM_ENABLE 0x96
78
79#define F71882FG_REG_FAN_HYST0 0x98
80#define F71882FG_REG_FAN_HYST1 0x99
81
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
73#define F71882FG_REG_START 0x01 86#define F71882FG_REG_START 0x01
74 87
75#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ 88#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */
@@ -78,6 +91,12 @@ static unsigned short force_id;
78module_param(force_id, ushort, 0); 91module_param(force_id, ushort, 0);
79MODULE_PARM_DESC(force_id, "Override the detected device ID"); 92MODULE_PARM_DESC(force_id, "Override the detected device ID");
80 93
94static int fan_mode[4] = { 0, 0, 0, 0 };
95module_param_array(fan_mode, int, NULL, 0644);
96MODULE_PARM_DESC(fan_mode, "List of fan control modes (f71882fg only) "
97 "(0=don't change, 1=pwm, 2=rpm)\n"
98 "Note: this needs a write to pwm#_enable to take effect");
99
81static struct platform_device *f71882fg_pdev; 100static struct platform_device *f71882fg_pdev;
82 101
83/* Super-I/O Function prototypes */ 102/* Super-I/O Function prototypes */
@@ -102,6 +121,8 @@ struct f71882fg_data {
102 u8 in_status; 121 u8 in_status;
103 u8 in_beep; 122 u8 in_beep;
104 u16 fan[4]; 123 u16 fan[4];
124 u16 fan_target[4];
125 u16 fan_full_speed[4];
105 u8 fan_status; 126 u8 fan_status;
106 u8 fan_beep; 127 u8 fan_beep;
107 u8 temp[3]; 128 u8 temp[3];
@@ -112,6 +133,12 @@ struct f71882fg_data {
112 u8 temp_status; 133 u8 temp_status;
113 u8 temp_beep; 134 u8 temp_beep;
114 u8 temp_diode_open; 135 u8 temp_diode_open;
136 u8 pwm[4];
137 u8 pwm_enable;
138 u8 pwm_auto_point_hyst[2];
139 u8 pwm_auto_point_mapping[4];
140 u8 pwm_auto_point_pwm[4][5];
141 u8 pwm_auto_point_temp[4][4];
115}; 142};
116 143
117/* Sysfs in */ 144/* Sysfs in */
@@ -130,6 +157,10 @@ static ssize_t show_in_alarm(struct device *dev, struct device_attribute
130/* Sysfs Fan */ 157/* Sysfs Fan */
131static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, 158static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
132 char *buf); 159 char *buf);
160static ssize_t show_fan_full_speed(struct device *dev,
161 struct device_attribute *devattr, char *buf);
162static ssize_t store_fan_full_speed(struct device *dev,
163 struct device_attribute *devattr, const char *buf, size_t count);
133static ssize_t show_fan_beep(struct device *dev, struct device_attribute 164static ssize_t show_fan_beep(struct device *dev, struct device_attribute
134 *devattr, char *buf); 165 *devattr, char *buf);
135static ssize_t store_fan_beep(struct device *dev, struct device_attribute 166static ssize_t store_fan_beep(struct device *dev, struct device_attribute
@@ -163,6 +194,35 @@ static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
163 *devattr, char *buf); 194 *devattr, char *buf);
164static ssize_t show_temp_fault(struct device *dev, struct device_attribute 195static ssize_t show_temp_fault(struct device *dev, struct device_attribute
165 *devattr, char *buf); 196 *devattr, char *buf);
197/* PWM and Auto point control */
198static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
199 char *buf);
200static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
201 const char *buf, size_t count);
202static ssize_t show_pwm_enable(struct device *dev,
203 struct device_attribute *devattr, char *buf);
204static ssize_t store_pwm_enable(struct device *dev,
205 struct device_attribute *devattr, const char *buf, size_t count);
206static ssize_t show_pwm_interpolate(struct device *dev,
207 struct device_attribute *devattr, char *buf);
208static ssize_t store_pwm_interpolate(struct device *dev,
209 struct device_attribute *devattr, const char *buf, size_t count);
210static ssize_t show_pwm_auto_point_channel(struct device *dev,
211 struct device_attribute *devattr, char *buf);
212static ssize_t store_pwm_auto_point_channel(struct device *dev,
213 struct device_attribute *devattr, const char *buf, size_t count);
214static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
215 struct device_attribute *devattr, char *buf);
216static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
217 struct device_attribute *devattr, const char *buf, size_t count);
218static ssize_t show_pwm_auto_point_pwm(struct device *dev,
219 struct device_attribute *devattr, char *buf);
220static ssize_t store_pwm_auto_point_pwm(struct device *dev,
221 struct device_attribute *devattr, const char *buf, size_t count);
222static ssize_t show_pwm_auto_point_temp(struct device *dev,
223 struct device_attribute *devattr, char *buf);
224static ssize_t store_pwm_auto_point_temp(struct device *dev,
225 struct device_attribute *devattr, const char *buf, size_t count);
166/* Sysfs misc */ 226/* Sysfs misc */
167static ssize_t show_name(struct device *dev, struct device_attribute *devattr, 227static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
168 char *buf); 228 char *buf);
@@ -249,21 +309,217 @@ static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = {
249 309
250static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { 310static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
251 SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), 311 SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
312 SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
313 show_fan_full_speed,
314 store_fan_full_speed, 0, 0),
252 SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, 315 SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
253 store_fan_beep, 0, 0), 316 store_fan_beep, 0, 0),
254 SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0), 317 SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),
255 SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1), 318 SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
319 SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
320 show_fan_full_speed,
321 store_fan_full_speed, 0, 1),
256 SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, 322 SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
257 store_fan_beep, 0, 1), 323 store_fan_beep, 0, 1),
258 SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1), 324 SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
259 SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), 325 SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
326 SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
327 show_fan_full_speed,
328 store_fan_full_speed, 0, 2),
260 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, 329 SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
261 store_fan_beep, 0, 2), 330 store_fan_beep, 0, 2),
262 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), 331 SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
263 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), 332 SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
333 SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
334 show_fan_full_speed,
335 store_fan_full_speed, 0, 3),
264 SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, 336 SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
265 store_fan_beep, 0, 3), 337 store_fan_beep, 0, 3),
266 SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3), 338 SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
339
340 SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
341 SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
342 store_pwm_enable, 0, 0),
343 SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,
344 show_pwm_interpolate, store_pwm_interpolate, 0, 0),
345 SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
346 show_pwm_auto_point_channel,
347 store_pwm_auto_point_channel, 0, 0),
348 SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
349 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
350 0, 0),
351 SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
352 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
353 1, 0),
354 SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
355 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
356 2, 0),
357 SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,
358 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
359 3, 0),
360 SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,
361 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
362 4, 0),
363 SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
364 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
365 0, 0),
366 SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
367 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
368 1, 0),
369 SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,
370 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
371 2, 0),
372 SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,
373 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
374 3, 0),
375 SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
376 show_pwm_auto_point_temp_hyst,
377 store_pwm_auto_point_temp_hyst,
378 0, 0),
379 SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
380 show_pwm_auto_point_temp_hyst, NULL, 1, 0),
381 SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO,
382 show_pwm_auto_point_temp_hyst, NULL, 2, 0),
383 SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
384 show_pwm_auto_point_temp_hyst, NULL, 3, 0),
385
386 SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
387 SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
388 store_pwm_enable, 0, 1),
389 SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
390 show_pwm_interpolate, store_pwm_interpolate, 0, 1),
391 SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
392 show_pwm_auto_point_channel,
393 store_pwm_auto_point_channel, 0, 1),
394 SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
395 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
396 0, 1),
397 SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
398 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
399 1, 1),
400 SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
401 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
402 2, 1),
403 SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,
404 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
405 3, 1),
406 SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,
407 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
408 4, 1),
409 SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
410 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
411 0, 1),
412 SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
413 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
414 1, 1),
415 SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR,
416 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
417 2, 1),
418 SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,
419 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
420 3, 1),
421 SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
422 show_pwm_auto_point_temp_hyst,
423 store_pwm_auto_point_temp_hyst,
424 0, 1),
425 SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
426 show_pwm_auto_point_temp_hyst, NULL, 1, 1),
427 SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO,
428 show_pwm_auto_point_temp_hyst, NULL, 2, 1),
429 SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
430 show_pwm_auto_point_temp_hyst, NULL, 3, 1),
431
432 SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
433 SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
434 store_pwm_enable, 0, 2),
435 SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
436 show_pwm_interpolate, store_pwm_interpolate, 0, 2),
437 SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
438 show_pwm_auto_point_channel,
439 store_pwm_auto_point_channel, 0, 2),
440 SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
441 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
442 0, 2),
443 SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
444 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
445 1, 2),
446 SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
447 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
448 2, 2),
449 SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR,
450 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
451 3, 2),
452 SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,
453 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
454 4, 2),
455 SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
456 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
457 0, 2),
458 SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
459 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
460 1, 2),
461 SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR,
462 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
463 2, 2),
464 SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR,
465 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
466 3, 2),
467 SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
468 show_pwm_auto_point_temp_hyst,
469 store_pwm_auto_point_temp_hyst,
470 0, 2),
471 SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
472 show_pwm_auto_point_temp_hyst, NULL, 1, 2),
473 SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO,
474 show_pwm_auto_point_temp_hyst, NULL, 2, 2),
475 SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
476 show_pwm_auto_point_temp_hyst, NULL, 3, 2),
477
478 SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
479 SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
480 store_pwm_enable, 0, 3),
481 SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
482 show_pwm_interpolate, store_pwm_interpolate, 0, 3),
483 SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
484 show_pwm_auto_point_channel,
485 store_pwm_auto_point_channel, 0, 3),
486 SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,
487 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
488 0, 3),
489 SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,
490 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
491 1, 3),
492 SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,
493 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
494 2, 3),
495 SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR,
496 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
497 3, 3),
498 SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR,
499 show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
500 4, 3),
501 SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,
502 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
503 0, 3),
504 SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,
505 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
506 1, 3),
507 SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,
508 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
509 2, 3),
510 SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,
511 show_pwm_auto_point_temp, store_pwm_auto_point_temp,
512 3, 3),
513 SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
514 show_pwm_auto_point_temp_hyst,
515 store_pwm_auto_point_temp_hyst,
516 0, 3),
517 SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO,
518 show_pwm_auto_point_temp_hyst, NULL, 1, 3),
519 SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO,
520 show_pwm_auto_point_temp_hyst, NULL, 2, 3),
521 SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,
522 show_pwm_auto_point_temp_hyst, NULL, 3, 3),
267}; 523};
268 524
269 525
@@ -307,6 +563,11 @@ static inline u16 fan_from_reg(u16 reg)
307 return reg ? (1500000 / reg) : 0; 563 return reg ? (1500000 / reg) : 0;
308} 564}
309 565
566static inline u16 fan_to_reg(u16 fan)
567{
568 return fan ? (1500000 / fan) : 0;
569}
570
310static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg) 571static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg)
311{ 572{
312 u8 val; 573 u8 val;
@@ -335,6 +596,14 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)
335 outb(val, data->addr + DATA_REG_OFFSET); 596 outb(val, data->addr + DATA_REG_OFFSET);
336} 597}
337 598
599static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)
600{
601 outb(reg++, data->addr + ADDR_REG_OFFSET);
602 outb(val >> 8, data->addr + DATA_REG_OFFSET);
603 outb(reg, data->addr + ADDR_REG_OFFSET);
604 outb(val & 255, data->addr + DATA_REG_OFFSET);
605}
606
338static struct f71882fg_data *f71882fg_update_device(struct device *dev) 607static struct f71882fg_data *f71882fg_update_device(struct device *dev)
339{ 608{
340 struct f71882fg_data *data = dev_get_drvdata(dev); 609 struct f71882fg_data *data = dev_get_drvdata(dev);
@@ -381,6 +650,32 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
381 650
382 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); 651 data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
383 652
653 data->pwm_enable = f71882fg_read8(data,
654 F71882FG_REG_PWM_ENABLE);
655 data->pwm_auto_point_hyst[0] = f71882fg_read8(data,
656 F71882FG_REG_FAN_HYST0);
657 data->pwm_auto_point_hyst[1] = f71882fg_read8(data,
658 F71882FG_REG_FAN_HYST1);
659 for (nr = 0; nr < 4; nr++) {
660 int point;
661
662 data->pwm_auto_point_mapping[nr] =
663 f71882fg_read8(data,
664 F71882FG_REG_POINT_MAPPING(nr));
665
666 for (point = 0; point < 5; point++) {
667 data->pwm_auto_point_pwm[nr][point] =
668 f71882fg_read8(data,
669 F71882FG_REG_POINT_PWM
670 (nr, point));
671 }
672 for (point = 0; point < 4; point++) {
673 data->pwm_auto_point_temp[nr][point] =
674 f71882fg_read8(data,
675 F71882FG_REG_POINT_TEMP
676 (nr, point));
677 }
678 }
384 data->last_limits = jiffies; 679 data->last_limits = jiffies;
385 } 680 }
386 681
@@ -396,9 +691,17 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
396 691
397 data->fan_status = f71882fg_read8(data, 692 data->fan_status = f71882fg_read8(data,
398 F71882FG_REG_FAN_STATUS); 693 F71882FG_REG_FAN_STATUS);
399 for (nr = 0; nr < 4; nr++) 694 for (nr = 0; nr < 4; nr++) {
400 data->fan[nr] = f71882fg_read16(data, 695 data->fan[nr] = f71882fg_read16(data,
401 F71882FG_REG_FAN(nr)); 696 F71882FG_REG_FAN(nr));
697 data->fan_target[nr] =
698 f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr));
699 data->fan_full_speed[nr] =
700 f71882fg_read16(data,
701 F71882FG_REG_FAN_FULL_SPEED(nr));
702 data->pwm[nr] =
703 f71882fg_read8(data, F71882FG_REG_PWM(nr));
704 }
402 705
403 data->in_status = f71882fg_read8(data, 706 data->in_status = f71882fg_read8(data,
404 F71882FG_REG_IN_STATUS); 707 F71882FG_REG_IN_STATUS);
@@ -429,6 +732,40 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
429 return sprintf(buf, "%d\n", speed); 732 return sprintf(buf, "%d\n", speed);
430} 733}
431 734
735static ssize_t show_fan_full_speed(struct device *dev,
736 struct device_attribute *devattr, char *buf)
737{
738 struct f71882fg_data *data = f71882fg_update_device(dev);
739 int nr = to_sensor_dev_attr_2(devattr)->index;
740 int speed = fan_from_reg(data->fan_full_speed[nr]);
741 return sprintf(buf, "%d\n", speed);
742}
743
744static ssize_t store_fan_full_speed(struct device *dev,
745 struct device_attribute *devattr,
746 const char *buf, size_t count)
747{
748 struct f71882fg_data *data = dev_get_drvdata(dev);
749 int nr = to_sensor_dev_attr_2(devattr)->index;
750 long val = simple_strtol(buf, NULL, 10);
751
752 val = SENSORS_LIMIT(val, 23, 1500000);
753 val = fan_to_reg(val);
754
755 mutex_lock(&data->update_lock);
756 if (data->pwm_enable & (1 << (2 * nr)))
757 /* PWM mode */
758 count = -EINVAL;
759 else {
760 /* RPM mode */
761 f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val);
762 data->fan_full_speed[nr] = val;
763 }
764 mutex_unlock(&data->update_lock);
765
766 return count;
767}
768
432static ssize_t show_fan_beep(struct device *dev, struct device_attribute 769static ssize_t show_fan_beep(struct device *dev, struct device_attribute
433 *devattr, char *buf) 770 *devattr, char *buf)
434{ 771{
@@ -736,6 +1073,323 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute
736 return sprintf(buf, "0\n"); 1073 return sprintf(buf, "0\n");
737} 1074}
738 1075
1076static ssize_t show_pwm(struct device *dev,
1077 struct device_attribute *devattr, char *buf)
1078{
1079 struct f71882fg_data *data = f71882fg_update_device(dev);
1080 int val, nr = to_sensor_dev_attr_2(devattr)->index;
1081 if (data->pwm_enable & (1 << (2 * nr)))
1082 /* PWM mode */
1083 val = data->pwm[nr];
1084 else {
1085 /* RPM mode */
1086 mutex_lock(&data->update_lock);
1087 val = 255 * fan_from_reg(data->fan_target[nr])
1088 / fan_from_reg(data->fan_full_speed[nr]);
1089 mutex_unlock(&data->update_lock);
1090 }
1091 return sprintf(buf, "%d\n", val);
1092}
1093
1094static ssize_t store_pwm(struct device *dev,
1095 struct device_attribute *devattr, const char *buf,
1096 size_t count)
1097{
1098 /* struct f71882fg_data *data = dev_get_drvdata(dev); */
1099 struct f71882fg_data *data = f71882fg_update_device(dev);
1100 int nr = to_sensor_dev_attr_2(devattr)->index;
1101 long val = simple_strtol(buf, NULL, 10);
1102 val = SENSORS_LIMIT(val, 0, 255);
1103
1104 mutex_lock(&data->update_lock);
1105 if (data->pwm_enable & (1 << (2 * nr))) {
1106 /* PWM mode */
1107 f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
1108 data->pwm[nr] = val;
1109 } else {
1110 /* RPM mode */
1111 int target = val * fan_from_reg(data->fan_full_speed[nr]) / 255;
1112 f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr),
1113 fan_to_reg(target));
1114 data->fan_target[nr] = fan_to_reg(target);
1115 }
1116 mutex_unlock(&data->update_lock);
1117
1118 return count;
1119}
1120
1121static ssize_t show_pwm_enable(struct device *dev,
1122 struct device_attribute *devattr, char *buf)
1123{
1124 int result;
1125 struct f71882fg_data *data = f71882fg_update_device(dev);
1126 int nr = to_sensor_dev_attr_2(devattr)->index;
1127
1128 if (data->pwm_enable & (2 << (2 * nr)))
1129 result = 1;
1130 else
1131 result = 2;
1132
1133 return sprintf(buf, "%d\n", result);
1134}
1135
1136static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
1137 *devattr, const char *buf, size_t count)
1138{
1139 struct f71882fg_data *data = dev_get_drvdata(dev);
1140 int nr = to_sensor_dev_attr_2(devattr)->index;
1141 long val = simple_strtol(buf, NULL, 10);
1142 if (val < 1 || val > 2)
1143 return -EINVAL;
1144
1145 mutex_lock(&data->update_lock);
1146 switch (val) {
1147 case 1:
1148 data->pwm_enable |= 2 << (2 * nr);
1149 break; /* Manual */
1150 case 2:
1151 data->pwm_enable &= ~(2 << (2 * nr));
1152 break; /* Temperature ctrl */
1153 }
1154 switch (fan_mode[nr]) {
1155 case 1:
1156 data->pwm_enable |= 1 << (2 * nr);
1157 break; /* Duty cycle mode */
1158 case 2:
1159 data->pwm_enable &= ~(1 << (2 * nr));
1160 break; /* RPM mode */
1161 }
1162 f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
1163 mutex_unlock(&data->update_lock);
1164
1165 return count;
1166}
1167
1168static ssize_t show_pwm_auto_point_pwm(struct device *dev,
1169 struct device_attribute *devattr,
1170 char *buf)
1171{
1172 int result;
1173 struct f71882fg_data *data = f71882fg_update_device(dev);
1174 int pwm = to_sensor_dev_attr_2(devattr)->index;
1175 int point = to_sensor_dev_attr_2(devattr)->nr;
1176
1177 if (data->pwm_enable & (1 << (2 * pwm))) {
1178 /* PWM mode */
1179 result = data->pwm_auto_point_pwm[pwm][point];
1180 } else {
1181 /* RPM mode */
1182 result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]);
1183 }
1184
1185 return sprintf(buf, "%d\n", result);
1186}
1187
1188static ssize_t store_pwm_auto_point_pwm(struct device *dev,
1189 struct device_attribute *devattr,
1190 const char *buf, size_t count)
1191{
1192 /* struct f71882fg_data *data = dev_get_drvdata(dev); */
1193 struct f71882fg_data *data = f71882fg_update_device(dev);
1194 int pwm = to_sensor_dev_attr_2(devattr)->index;
1195 int point = to_sensor_dev_attr_2(devattr)->nr;
1196 int val = simple_strtoul(buf, NULL, 10);
1197 val = SENSORS_LIMIT(val, 0, 255);
1198
1199 mutex_lock(&data->update_lock);
1200 if (data->pwm_enable & (1 << (2 * pwm))) {
1201 /* PWM mode */
1202 } else {
1203 /* RPM mode */
1204 if (val < 29) /* Prevent negative numbers */
1205 val = 255;
1206 else
1207 val = (255 - val) * 32 / val;
1208 }
1209 f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val);
1210 data->pwm_auto_point_pwm[pwm][point] = val;
1211 mutex_unlock(&data->update_lock);
1212
1213 return count;
1214}
1215
1216static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
1217 struct device_attribute *devattr,
1218 char *buf)
1219{
1220 int result = 0;
1221 struct f71882fg_data *data = f71882fg_update_device(dev);
1222 int nr = to_sensor_dev_attr_2(devattr)->index;
1223 int point = to_sensor_dev_attr_2(devattr)->nr;
1224
1225 mutex_lock(&data->update_lock);
1226 switch (nr) {
1227 case 0:
1228 result = data->pwm_auto_point_hyst[0] & 0x0f;
1229 break;
1230 case 1:
1231 result = data->pwm_auto_point_hyst[0] >> 4;
1232 break;
1233 case 2:
1234 result = data->pwm_auto_point_hyst[1] & 0x0f;
1235 break;
1236 case 3:
1237 result = data->pwm_auto_point_hyst[1] >> 4;
1238 break;
1239 }
1240 result = 1000 * (data->pwm_auto_point_temp[nr][point] - result);
1241 mutex_unlock(&data->update_lock);
1242
1243 return sprintf(buf, "%d\n", result);
1244}
1245
1246static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
1247 struct device_attribute *devattr,
1248 const char *buf, size_t count)
1249{
1250 struct f71882fg_data *data = f71882fg_update_device(dev);
1251 int nr = to_sensor_dev_attr_2(devattr)->index;
1252 int point = to_sensor_dev_attr_2(devattr)->nr;
1253 long val = simple_strtol(buf, NULL, 10) / 1000;
1254
1255 mutex_lock(&data->update_lock);
1256 val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15,
1257 data->pwm_auto_point_temp[nr][point]);
1258 val = data->pwm_auto_point_temp[nr][point] - val;
1259
1260 switch (nr) {
1261 case 0:
1262 val = (data->pwm_auto_point_hyst[0] & 0xf0) | val;
1263 break;
1264 case 1:
1265 val = (data->pwm_auto_point_hyst[0] & 0x0f) | (val << 4);
1266 break;
1267 case 2:
1268 val = (data->pwm_auto_point_hyst[1] & 0xf0) | val;
1269 break;
1270 case 3:
1271 val = (data->pwm_auto_point_hyst[1] & 0x0f) | (val << 4);
1272 break;
1273 }
1274 if (nr == 0 || nr == 1) {
1275 f71882fg_write8(data, F71882FG_REG_FAN_HYST0, val);
1276 data->pwm_auto_point_hyst[0] = val;
1277 } else {
1278 f71882fg_write8(data, F71882FG_REG_FAN_HYST1, val);
1279 data->pwm_auto_point_hyst[1] = val;
1280 }
1281 mutex_unlock(&data->update_lock);
1282
1283 return count;
1284}
1285
1286static ssize_t show_pwm_interpolate(struct device *dev,
1287 struct device_attribute *devattr, char *buf)
1288{
1289 int result;
1290 struct f71882fg_data *data = f71882fg_update_device(dev);
1291 int nr = to_sensor_dev_attr_2(devattr)->index;
1292
1293 result = (data->pwm_auto_point_mapping[nr] >> 4) & 1;
1294
1295 return sprintf(buf, "%d\n", result);
1296}
1297
1298static ssize_t store_pwm_interpolate(struct device *dev,
1299 struct device_attribute *devattr,
1300 const char *buf, size_t count)
1301{
1302 /* struct f71882fg_data *data = dev_get_drvdata(dev); */
1303 struct f71882fg_data *data = f71882fg_update_device(dev);
1304 int nr = to_sensor_dev_attr_2(devattr)->index;
1305 int val = simple_strtoul(buf, NULL, 10);
1306 mutex_lock(&data->update_lock);
1307 if (val)
1308 val = data->pwm_auto_point_mapping[nr] | (1 << 4);
1309 else
1310 val = data->pwm_auto_point_mapping[nr] & (~(1 << 4));
1311 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1312 data->pwm_auto_point_mapping[nr] = val;
1313 mutex_unlock(&data->update_lock);
1314
1315 return count;
1316}
1317
1318static ssize_t show_pwm_auto_point_channel(struct device *dev,
1319 struct device_attribute *devattr,
1320 char *buf)
1321{
1322 int result;
1323 struct f71882fg_data *data = f71882fg_update_device(dev);
1324 int nr = to_sensor_dev_attr_2(devattr)->index;
1325
1326 result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - 1);
1327
1328 return sprintf(buf, "%d\n", result);
1329}
1330
1331static ssize_t store_pwm_auto_point_channel(struct device *dev,
1332 struct device_attribute *devattr,
1333 const char *buf, size_t count)
1334{
1335 /* struct f71882fg_data *data = dev_get_drvdata(dev); */
1336 struct f71882fg_data *data = f71882fg_update_device(dev);
1337 int nr = to_sensor_dev_attr_2(devattr)->index;
1338 long val = simple_strtol(buf, NULL, 10);
1339 switch (val) {
1340 case 1:
1341 val = 1;
1342 break;
1343 case 2:
1344 val = 2;
1345 break;
1346 case 4:
1347 val = 3;
1348 break;
1349 default:
1350 return -EINVAL;
1351 }
1352 mutex_lock(&data->update_lock);
1353 val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val;
1354 f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
1355 data->pwm_auto_point_mapping[nr] = val;
1356 mutex_unlock(&data->update_lock);
1357
1358 return count;
1359}
1360
1361static ssize_t show_pwm_auto_point_temp(struct device *dev,
1362 struct device_attribute *devattr,
1363 char *buf)
1364{
1365 int result;
1366 struct f71882fg_data *data = f71882fg_update_device(dev);
1367 int pwm = to_sensor_dev_attr_2(devattr)->index;
1368 int point = to_sensor_dev_attr_2(devattr)->nr;
1369
1370 result = data->pwm_auto_point_temp[pwm][point];
1371 return sprintf(buf, "%d\n", 1000 * result);
1372}
1373
1374static ssize_t store_pwm_auto_point_temp(struct device *dev,
1375 struct device_attribute *devattr,
1376 const char *buf, size_t count)
1377{
1378 /* struct f71882fg_data *data = dev_get_drvdata(dev); */
1379 struct f71882fg_data *data = f71882fg_update_device(dev);
1380 int pwm = to_sensor_dev_attr_2(devattr)->index;
1381 int point = to_sensor_dev_attr_2(devattr)->nr;
1382 long val = simple_strtol(buf, NULL, 10) / 1000;
1383 val = SENSORS_LIMIT(val, 0, 255);
1384
1385 mutex_lock(&data->update_lock);
1386 f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
1387 data->pwm_auto_point_temp[pwm][point] = val;
1388 mutex_unlock(&data->update_lock);
1389
1390 return count;
1391}
1392
739static ssize_t show_name(struct device *dev, struct device_attribute *devattr, 1393static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
740 char *buf) 1394 char *buf)
741{ 1395{