diff options
author | Chris Packham <chris.packham@alliedtelesis.co.nz> | 2017-05-14 21:30:27 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2017-06-11 20:08:19 -0400 |
commit | 1d58f5efbf2d8599a9062e4c800a072e2f015625 (patch) | |
tree | fff4e3b1eb18e6ccf32d0cb07c62d6c6bb356967 | |
parent | e4651640403307d79559dff113da4933c0921714 (diff) |
hwmon: (adt7475) fan stall prevention
By default adt7475 will stop the fans (pwm duty cycle 0%) when the
temperature drops past Tmin - hysteresis. Some systems want to keep the
fans moving even when the temperature drops so add new sysfs attributes
that configure the enhanced acoustics min 1-3 which allows the fans to
run at the minimum configure pwm duty cycle.
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r-- | Documentation/hwmon/adt7475 | 5 | ||||
-rw-r--r-- | drivers/hwmon/adt7475.c | 50 |
2 files changed, 55 insertions, 0 deletions
diff --git a/Documentation/hwmon/adt7475 b/Documentation/hwmon/adt7475 index 0502f2b464e1..dc0b55794c47 100644 --- a/Documentation/hwmon/adt7475 +++ b/Documentation/hwmon/adt7475 | |||
@@ -109,6 +109,11 @@ fan speed) is applied. PWM values range from 0 (off) to 255 (full speed). | |||
109 | Fan speed may be set to maximum when the temperature sensor associated with | 109 | Fan speed may be set to maximum when the temperature sensor associated with |
110 | the PWM control exceeds temp#_max. | 110 | the PWM control exceeds temp#_max. |
111 | 111 | ||
112 | At Tmin - hysteresis the PWM output can either be off (0% duty cycle) or at the | ||
113 | minimum (i.e. auto_point1_pwm). This behaviour can be configured using the | ||
114 | pwm[1-*]_stall_disable sysfs attribute. A value of 0 means the fans will shut | ||
115 | off. A value of 1 means the fans will run at auto_point1_pwm. | ||
116 | |||
112 | Notes | 117 | Notes |
113 | ----- | 118 | ----- |
114 | 119 | ||
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index ec0c43fbcdce..3eb8c5c2f8af 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c | |||
@@ -79,6 +79,9 @@ | |||
79 | 79 | ||
80 | #define REG_TEMP_TRANGE_BASE 0x5F | 80 | #define REG_TEMP_TRANGE_BASE 0x5F |
81 | 81 | ||
82 | #define REG_ENHANCE_ACOUSTICS1 0x62 | ||
83 | #define REG_ENHANCE_ACOUSTICS2 0x63 | ||
84 | |||
82 | #define REG_PWM_MIN_BASE 0x64 | 85 | #define REG_PWM_MIN_BASE 0x64 |
83 | 86 | ||
84 | #define REG_TEMP_TMIN_BASE 0x67 | 87 | #define REG_TEMP_TMIN_BASE 0x67 |
@@ -209,6 +212,7 @@ struct adt7475_data { | |||
209 | u8 range[3]; | 212 | u8 range[3]; |
210 | u8 pwmctl[3]; | 213 | u8 pwmctl[3]; |
211 | u8 pwmchan[3]; | 214 | u8 pwmchan[3]; |
215 | u8 enh_acoustics[2]; | ||
212 | 216 | ||
213 | u8 vid; | 217 | u8 vid; |
214 | u8 vrm; | 218 | u8 vrm; |
@@ -700,6 +704,43 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
700 | data->pwm[sattr->nr][sattr->index] = clamp_val(val, 0, 0xFF); | 704 | data->pwm[sattr->nr][sattr->index] = clamp_val(val, 0, 0xFF); |
701 | i2c_smbus_write_byte_data(client, reg, | 705 | i2c_smbus_write_byte_data(client, reg, |
702 | data->pwm[sattr->nr][sattr->index]); | 706 | data->pwm[sattr->nr][sattr->index]); |
707 | mutex_unlock(&data->lock); | ||
708 | |||
709 | return count; | ||
710 | } | ||
711 | |||
712 | static ssize_t show_stall_disable(struct device *dev, | ||
713 | struct device_attribute *attr, char *buf) | ||
714 | { | ||
715 | struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); | ||
716 | struct i2c_client *client = to_i2c_client(dev); | ||
717 | struct adt7475_data *data = i2c_get_clientdata(client); | ||
718 | u8 mask = BIT(5 + sattr->index); | ||
719 | |||
720 | return sprintf(buf, "%d\n", !!(data->enh_acoustics[0] & mask)); | ||
721 | } | ||
722 | |||
723 | static ssize_t set_stall_disable(struct device *dev, | ||
724 | struct device_attribute *attr, const char *buf, | ||
725 | size_t count) | ||
726 | { | ||
727 | struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); | ||
728 | struct i2c_client *client = to_i2c_client(dev); | ||
729 | struct adt7475_data *data = i2c_get_clientdata(client); | ||
730 | long val; | ||
731 | u8 mask = BIT(5 + sattr->index); | ||
732 | |||
733 | if (kstrtol(buf, 10, &val)) | ||
734 | return -EINVAL; | ||
735 | |||
736 | mutex_lock(&data->lock); | ||
737 | |||
738 | data->enh_acoustics[0] &= ~mask; | ||
739 | if (val) | ||
740 | data->enh_acoustics[0] |= mask; | ||
741 | |||
742 | i2c_smbus_write_byte_data(client, REG_ENHANCE_ACOUSTICS1, | ||
743 | data->enh_acoustics[0]); | ||
703 | 744 | ||
704 | mutex_unlock(&data->lock); | 745 | mutex_unlock(&data->lock); |
705 | 746 | ||
@@ -1028,6 +1069,8 @@ static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, | |||
1028 | set_pwm, MIN, 0); | 1069 | set_pwm, MIN, 0); |
1029 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, | 1070 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, |
1030 | set_pwm, MAX, 0); | 1071 | set_pwm, MAX, 0); |
1072 | static SENSOR_DEVICE_ATTR_2(pwm1_stall_disable, S_IRUGO | S_IWUSR, | ||
1073 | show_stall_disable, set_stall_disable, 0, 0); | ||
1031 | static SENSOR_DEVICE_ATTR_2(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, | 1074 | static SENSOR_DEVICE_ATTR_2(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, |
1032 | 1); | 1075 | 1); |
1033 | static SENSOR_DEVICE_ATTR_2(pwm2_freq, S_IRUGO | S_IWUSR, show_pwmfreq, | 1076 | static SENSOR_DEVICE_ATTR_2(pwm2_freq, S_IRUGO | S_IWUSR, show_pwmfreq, |
@@ -1040,6 +1083,8 @@ static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, | |||
1040 | set_pwm, MIN, 1); | 1083 | set_pwm, MIN, 1); |
1041 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, | 1084 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, |
1042 | set_pwm, MAX, 1); | 1085 | set_pwm, MAX, 1); |
1086 | static SENSOR_DEVICE_ATTR_2(pwm2_stall_disable, S_IRUGO | S_IWUSR, | ||
1087 | show_stall_disable, set_stall_disable, 0, 1); | ||
1043 | static SENSOR_DEVICE_ATTR_2(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, | 1088 | static SENSOR_DEVICE_ATTR_2(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, |
1044 | 2); | 1089 | 2); |
1045 | static SENSOR_DEVICE_ATTR_2(pwm3_freq, S_IRUGO | S_IWUSR, show_pwmfreq, | 1090 | static SENSOR_DEVICE_ATTR_2(pwm3_freq, S_IRUGO | S_IWUSR, show_pwmfreq, |
@@ -1052,6 +1097,8 @@ static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, | |||
1052 | set_pwm, MIN, 2); | 1097 | set_pwm, MIN, 2); |
1053 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, | 1098 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, |
1054 | set_pwm, MAX, 2); | 1099 | set_pwm, MAX, 2); |
1100 | static SENSOR_DEVICE_ATTR_2(pwm3_stall_disable, S_IRUGO | S_IWUSR, | ||
1101 | show_stall_disable, set_stall_disable, 0, 2); | ||
1055 | 1102 | ||
1056 | /* Non-standard name, might need revisiting */ | 1103 | /* Non-standard name, might need revisiting */ |
1057 | static DEVICE_ATTR_RW(pwm_use_point2_pwm_at_crit); | 1104 | static DEVICE_ATTR_RW(pwm_use_point2_pwm_at_crit); |
@@ -1112,12 +1159,14 @@ static struct attribute *adt7475_attrs[] = { | |||
1112 | &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, | 1159 | &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, |
1113 | &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, | 1160 | &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, |
1114 | &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, | 1161 | &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, |
1162 | &sensor_dev_attr_pwm1_stall_disable.dev_attr.attr, | ||
1115 | &sensor_dev_attr_pwm3.dev_attr.attr, | 1163 | &sensor_dev_attr_pwm3.dev_attr.attr, |
1116 | &sensor_dev_attr_pwm3_freq.dev_attr.attr, | 1164 | &sensor_dev_attr_pwm3_freq.dev_attr.attr, |
1117 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | 1165 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, |
1118 | &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, | 1166 | &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, |
1119 | &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, | 1167 | &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, |
1120 | &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, | 1168 | &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, |
1169 | &sensor_dev_attr_pwm3_stall_disable.dev_attr.attr, | ||
1121 | &dev_attr_pwm_use_point2_pwm_at_crit.attr, | 1170 | &dev_attr_pwm_use_point2_pwm_at_crit.attr, |
1122 | NULL, | 1171 | NULL, |
1123 | }; | 1172 | }; |
@@ -1136,6 +1185,7 @@ static struct attribute *pwm2_attrs[] = { | |||
1136 | &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, | 1185 | &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, |
1137 | &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, | 1186 | &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, |
1138 | &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, | 1187 | &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, |
1188 | &sensor_dev_attr_pwm2_stall_disable.dev_attr.attr, | ||
1139 | NULL | 1189 | NULL |
1140 | }; | 1190 | }; |
1141 | 1191 | ||