aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/f71805f.c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2006-12-12 12:18:27 -0500
committerJean Delvare <khali@arrakis.delvare>2006-12-12 12:18:27 -0500
commit315c7113b5580a5f88169b62f597aacd64ef3717 (patch)
tree9d5ea8ddd2e471e7a3e8f0fcb64fbe76e44ca338 /drivers/hwmon/f71805f.c
parente196783d54a75bea05580ce692126532ac54ee24 (diff)
hwmon/f71805f: Add support for "speed mode" fan speed control
In "speed mode", the user specifies a target fan speed (in RPM) and the chip automatically adjusts the PWM duty cycle (or DC output level) to reach this target. Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/f71805f.c')
-rw-r--r--drivers/hwmon/f71805f.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 29a3984af738..975c1cc2acf1 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -111,6 +111,7 @@ superio_exit(int base)
111/* fan nr from 0 to 2 (12-bit values, two registers) */ 111/* fan nr from 0 to 2 (12-bit values, two registers) */
112#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr)) 112#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr))
113#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr)) 113#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr))
114#define F71805F_REG_FAN_TARGET(nr) (0x69 + 16 * (nr))
114#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr)) 115#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr))
115#define F71805F_REG_PWM_FREQ(nr) (0x63 + 16 * (nr)) 116#define F71805F_REG_PWM_FREQ(nr) (0x63 + 16 * (nr))
116#define F71805F_REG_PWM_DUTY(nr) (0x6B + 16 * (nr)) 117#define F71805F_REG_PWM_DUTY(nr) (0x6B + 16 * (nr))
@@ -127,6 +128,7 @@ superio_exit(int base)
127/* individual register bits */ 128/* individual register bits */
128#define FAN_CTRL_SKIP 0x80 129#define FAN_CTRL_SKIP 0x80
129#define FAN_CTRL_DC_MODE 0x10 130#define FAN_CTRL_DC_MODE 0x10
131#define FAN_CTRL_LATCH_FULL 0x08
130#define FAN_CTRL_MODE_MASK 0x03 132#define FAN_CTRL_MODE_MASK 0x03
131#define FAN_CTRL_MODE_SPEED 0x00 133#define FAN_CTRL_MODE_SPEED 0x00
132#define FAN_CTRL_MODE_TEMPERATURE 0x01 134#define FAN_CTRL_MODE_TEMPERATURE 0x01
@@ -153,6 +155,7 @@ struct f71805f_data {
153 u8 in_low[9]; 155 u8 in_low[9];
154 u16 fan[3]; 156 u16 fan[3];
155 u16 fan_low[3]; 157 u16 fan_low[3];
158 u16 fan_target[3];
156 u8 fan_ctrl[3]; 159 u8 fan_ctrl[3];
157 u8 pwm[3]; 160 u8 pwm[3];
158 u8 pwm_freq[3]; 161 u8 pwm_freq[3];
@@ -324,6 +327,8 @@ static struct f71805f_data *f71805f_update_device(struct device *dev)
324 continue; 327 continue;
325 data->fan_low[nr] = f71805f_read16(data, 328 data->fan_low[nr] = f71805f_read16(data,
326 F71805F_REG_FAN_LOW(nr)); 329 F71805F_REG_FAN_LOW(nr));
330 data->fan_target[nr] = f71805f_read16(data,
331 F71805F_REG_FAN_TARGET(nr));
327 data->pwm_freq[nr] = f71805f_read8(data, 332 data->pwm_freq[nr] = f71805f_read8(data,
328 F71805F_REG_PWM_FREQ(nr)); 333 F71805F_REG_PWM_FREQ(nr));
329 } 334 }
@@ -510,6 +515,16 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute
510 return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr])); 515 return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr]));
511} 516}
512 517
518static ssize_t show_fan_target(struct device *dev, struct device_attribute
519 *devattr, char *buf)
520{
521 struct f71805f_data *data = f71805f_update_device(dev);
522 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
523 int nr = attr->index;
524
525 return sprintf(buf, "%ld\n", fan_from_reg(data->fan_target[nr]));
526}
527
513static ssize_t set_fan_min(struct device *dev, struct device_attribute 528static ssize_t set_fan_min(struct device *dev, struct device_attribute
514 *devattr, const char *buf, size_t count) 529 *devattr, const char *buf, size_t count)
515{ 530{
@@ -526,6 +541,23 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute
526 return count; 541 return count;
527} 542}
528 543
544static ssize_t set_fan_target(struct device *dev, struct device_attribute
545 *devattr, const char *buf, size_t count)
546{
547 struct f71805f_data *data = dev_get_drvdata(dev);
548 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
549 int nr = attr->index;
550 long val = simple_strtol(buf, NULL, 10);
551
552 mutex_lock(&data->update_lock);
553 data->fan_target[nr] = fan_to_reg(val);
554 f71805f_write16(data, F71805F_REG_FAN_TARGET(nr),
555 data->fan_target[nr]);
556 mutex_unlock(&data->update_lock);
557
558 return count;
559}
560
529static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, 561static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
530 char *buf) 562 char *buf)
531{ 563{
@@ -822,12 +854,18 @@ static SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR,
822static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); 854static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
823static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, 855static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
824 show_fan_min, set_fan_min, 0); 856 show_fan_min, set_fan_min, 0);
857static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR,
858 show_fan_target, set_fan_target, 0);
825static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); 859static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
826static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, 860static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR,
827 show_fan_min, set_fan_min, 1); 861 show_fan_min, set_fan_min, 1);
862static SENSOR_DEVICE_ATTR(fan2_target, S_IRUGO | S_IWUSR,
863 show_fan_target, set_fan_target, 1);
828static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); 864static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
829static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR, 865static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
830 show_fan_min, set_fan_min, 2); 866 show_fan_min, set_fan_min, 2);
867static SENSOR_DEVICE_ATTR(fan3_target, S_IRUGO | S_IWUSR,
868 show_fan_target, set_fan_target, 2);
831 869
832static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); 870static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
833static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, 871static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
@@ -956,11 +994,12 @@ static const struct attribute_group f71805f_group = {
956 .attrs = f71805f_attributes, 994 .attrs = f71805f_attributes,
957}; 995};
958 996
959static struct attribute *f71805f_attributes_fan[3][7] = { 997static struct attribute *f71805f_attributes_fan[3][8] = {
960 { 998 {
961 &sensor_dev_attr_fan1_input.dev_attr.attr, 999 &sensor_dev_attr_fan1_input.dev_attr.attr,
962 &sensor_dev_attr_fan1_min.dev_attr.attr, 1000 &sensor_dev_attr_fan1_min.dev_attr.attr,
963 &sensor_dev_attr_fan1_alarm.dev_attr.attr, 1001 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
1002 &sensor_dev_attr_fan1_target.dev_attr.attr,
964 &sensor_dev_attr_pwm1.dev_attr.attr, 1003 &sensor_dev_attr_pwm1.dev_attr.attr,
965 &sensor_dev_attr_pwm1_enable.dev_attr.attr, 1004 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
966 &sensor_dev_attr_pwm1_mode.dev_attr.attr, 1005 &sensor_dev_attr_pwm1_mode.dev_attr.attr,
@@ -969,6 +1008,7 @@ static struct attribute *f71805f_attributes_fan[3][7] = {
969 &sensor_dev_attr_fan2_input.dev_attr.attr, 1008 &sensor_dev_attr_fan2_input.dev_attr.attr,
970 &sensor_dev_attr_fan2_min.dev_attr.attr, 1009 &sensor_dev_attr_fan2_min.dev_attr.attr,
971 &sensor_dev_attr_fan2_alarm.dev_attr.attr, 1010 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
1011 &sensor_dev_attr_fan2_target.dev_attr.attr,
972 &sensor_dev_attr_pwm2.dev_attr.attr, 1012 &sensor_dev_attr_pwm2.dev_attr.attr,
973 &sensor_dev_attr_pwm2_enable.dev_attr.attr, 1013 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
974 &sensor_dev_attr_pwm2_mode.dev_attr.attr, 1014 &sensor_dev_attr_pwm2_mode.dev_attr.attr,
@@ -977,6 +1017,7 @@ static struct attribute *f71805f_attributes_fan[3][7] = {
977 &sensor_dev_attr_fan3_input.dev_attr.attr, 1017 &sensor_dev_attr_fan3_input.dev_attr.attr,
978 &sensor_dev_attr_fan3_min.dev_attr.attr, 1018 &sensor_dev_attr_fan3_min.dev_attr.attr,
979 &sensor_dev_attr_fan3_alarm.dev_attr.attr, 1019 &sensor_dev_attr_fan3_alarm.dev_attr.attr,
1020 &sensor_dev_attr_fan3_target.dev_attr.attr,
980 &sensor_dev_attr_pwm3.dev_attr.attr, 1021 &sensor_dev_attr_pwm3.dev_attr.attr,
981 &sensor_dev_attr_pwm3_enable.dev_attr.attr, 1022 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
982 &sensor_dev_attr_pwm3_mode.dev_attr.attr, 1023 &sensor_dev_attr_pwm3_mode.dev_attr.attr,
@@ -1031,6 +1072,13 @@ static void __devinit f71805f_init_device(struct f71805f_data *data)
1031 for (i = 0; i < 3; i++) { 1072 for (i = 0; i < 3; i++) {
1032 data->fan_ctrl[i] = f71805f_read8(data, 1073 data->fan_ctrl[i] = f71805f_read8(data,
1033 F71805F_REG_FAN_CTRL(i)); 1074 F71805F_REG_FAN_CTRL(i));
1075 /* Clear latch full bit, else "speed mode" fan speed control
1076 doesn't work */
1077 if (data->fan_ctrl[i] & FAN_CTRL_LATCH_FULL) {
1078 data->fan_ctrl[i] &= ~FAN_CTRL_LATCH_FULL;
1079 f71805f_write8(data, F71805F_REG_FAN_CTRL(i),
1080 data->fan_ctrl[i]);
1081 }
1034 } 1082 }
1035} 1083}
1036 1084