aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorDaniel J Blueman <daniel.blueman@gmail.com>2009-12-14 21:01:37 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-15 11:53:35 -0500
commit41e9a062361de204d3710038925ae7f356ebb40d (patch)
tree8615207c3c024f8835fe867f18038dca101846b1 /drivers/hwmon
parente40d6eaa79bc9d9d347c3c51fe0c9204e9025b79 (diff)
hwmon: w83627ehf updates
Add control of fan minimum turn-on output levels, decoupling it from the fan turn-off output level. Add control of rate of change of fan output level. These in turn allow lower turn-off rotor speed and smoother transitions for better thermal and acoustic control authority. Add support for constant fan speed and proportional-response operations modes. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Daniel J Blueman <daniel.blueman@gmail.com> Cc: Jean Delvare <khali@linux-fr.org> Cc: David Hubbard <david.c.hubbard@gmail.com> Cc: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/w83627ehf.c72
1 files changed, 53 insertions, 19 deletions
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index bb5e78748783..0dcaba9b7189 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -5,6 +5,7 @@
5 Copyright (C) 2006 Yuan Mu (Winbond), 5 Copyright (C) 2006 Yuan Mu (Winbond),
6 Rudolf Marek <r.marek@assembler.cz> 6 Rudolf Marek <r.marek@assembler.cz>
7 David Hubbard <david.c.hubbard@gmail.com> 7 David Hubbard <david.c.hubbard@gmail.com>
8 Daniel J Blueman <daniel.blueman@gmail.com>
8 9
9 Shamelessly ripped from the w83627hf driver 10 Shamelessly ripped from the w83627hf driver
10 Copyright (C) 2003 Mark Studebaker 11 Copyright (C) 2003 Mark Studebaker
@@ -177,12 +178,15 @@ static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
177#define W83627EHF_REG_ALARM3 0x45B 178#define W83627EHF_REG_ALARM3 0x45B
178 179
179/* SmartFan registers */ 180/* SmartFan registers */
181#define W83627EHF_REG_FAN_STEPUP_TIME 0x0f
182#define W83627EHF_REG_FAN_STEPDOWN_TIME 0x0e
183
180/* DC or PWM output fan configuration */ 184/* DC or PWM output fan configuration */
181static const u8 W83627EHF_REG_PWM_ENABLE[] = { 185static const u8 W83627EHF_REG_PWM_ENABLE[] = {
182 0x04, /* SYS FAN0 output mode and PWM mode */ 186 0x04, /* SYS FAN0 output mode and PWM mode */
183 0x04, /* CPU FAN0 output mode and PWM mode */ 187 0x04, /* CPU FAN0 output mode and PWM mode */
184 0x12, /* AUX FAN mode */ 188 0x12, /* AUX FAN mode */
185 0x62, /* CPU fan1 mode */ 189 0x62, /* CPU FAN1 mode */
186}; 190};
187 191
188static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 }; 192static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 };
@@ -193,10 +197,12 @@ static const u8 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 };
193static const u8 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 }; 197static const u8 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 };
194static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 }; 198static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 };
195 199
196
197/* Advanced Fan control, some values are common for all fans */ 200/* Advanced Fan control, some values are common for all fans */
198static const u8 W83627EHF_REG_FAN_MIN_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 }; 201static const u8 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 };
199static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0C, 0x0D, 0x17, 0x66 }; 202static const u8 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
203static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 };
204static const u8 W83627EHF_REG_FAN_MAX_OUTPUT[] = { 0xff, 0x67, 0xff, 0x69 };
205static const u8 W83627EHF_REG_FAN_STEP_OUTPUT[] = { 0xff, 0x68, 0xff, 0x6a };
200 206
201/* 207/*
202 * Conversions 208 * Conversions
@@ -295,14 +301,19 @@ struct w83627ehf_data {
295 301
296 u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */ 302 u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
297 u8 pwm_enable[4]; /* 1->manual 303 u8 pwm_enable[4]; /* 1->manual
298 2->thermal cruise (also called SmartFan I) */ 304 2->thermal cruise mode (also called SmartFan I)
305 3->fan speed cruise mode
306 4->variable thermal cruise (also called SmartFan III) */
299 u8 pwm_num; /* number of pwm */ 307 u8 pwm_num; /* number of pwm */
300 u8 pwm[4]; 308 u8 pwm[4];
301 u8 target_temp[4]; 309 u8 target_temp[4];
302 u8 tolerance[4]; 310 u8 tolerance[4];
303 311
304 u8 fan_min_output[4]; /* minimum fan speed */ 312 u8 fan_start_output[4]; /* minimum fan speed when spinning up */
305 u8 fan_stop_time[4]; 313 u8 fan_stop_output[4]; /* minimum fan speed when spinning down */
314 u8 fan_stop_time[4]; /* time at minimum before disabling fan */
315 u8 fan_max_output[4]; /* maximum fan speed */
316 u8 fan_step_output[4]; /* rate of change output value */
306 317
307 u8 vid; 318 u8 vid;
308 u8 vrm; 319 u8 vrm;
@@ -529,8 +540,10 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
529 & 3) + 1; 540 & 3) + 1;
530 data->pwm[i] = w83627ehf_read_value(data, 541 data->pwm[i] = w83627ehf_read_value(data,
531 W83627EHF_REG_PWM[i]); 542 W83627EHF_REG_PWM[i]);
532 data->fan_min_output[i] = w83627ehf_read_value(data, 543 data->fan_start_output[i] = w83627ehf_read_value(data,
533 W83627EHF_REG_FAN_MIN_OUTPUT[i]); 544 W83627EHF_REG_FAN_START_OUTPUT[i]);
545 data->fan_stop_output[i] = w83627ehf_read_value(data,
546 W83627EHF_REG_FAN_STOP_OUTPUT[i]);
534 data->fan_stop_time[i] = w83627ehf_read_value(data, 547 data->fan_stop_time[i] = w83627ehf_read_value(data,
535 W83627EHF_REG_FAN_STOP_TIME[i]); 548 W83627EHF_REG_FAN_STOP_TIME[i]);
536 data->target_temp[i] = 549 data->target_temp[i] =
@@ -976,7 +989,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
976 u32 val = simple_strtoul(buf, NULL, 10); 989 u32 val = simple_strtoul(buf, NULL, 10);
977 u16 reg; 990 u16 reg;
978 991
979 if (!val || (val > 2)) /* only modes 1 and 2 are supported */ 992 if (!val || (val > 4))
980 return -EINVAL; 993 return -EINVAL;
981 mutex_lock(&data->update_lock); 994 mutex_lock(&data->update_lock);
982 reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]); 995 reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
@@ -1118,7 +1131,10 @@ store_##reg(struct device *dev, struct device_attribute *attr, \
1118 return count; \ 1131 return count; \
1119} 1132}
1120 1133
1121fan_functions(fan_min_output, FAN_MIN_OUTPUT) 1134fan_functions(fan_start_output, FAN_START_OUTPUT)
1135fan_functions(fan_stop_output, FAN_STOP_OUTPUT)
1136fan_functions(fan_max_output, FAN_MAX_OUTPUT)
1137fan_functions(fan_step_output, FAN_STEP_OUTPUT)
1122 1138
1123#define fan_time_functions(reg, REG) \ 1139#define fan_time_functions(reg, REG) \
1124static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ 1140static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
@@ -1161,8 +1177,14 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
1161static struct sensor_device_attribute sda_sf3_arrays_fan4[] = { 1177static struct sensor_device_attribute sda_sf3_arrays_fan4[] = {
1162 SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, 1178 SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1163 store_fan_stop_time, 3), 1179 store_fan_stop_time, 3),
1164 SENSOR_ATTR(pwm4_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, 1180 SENSOR_ATTR(pwm4_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
1165 store_fan_min_output, 3), 1181 store_fan_start_output, 3),
1182 SENSOR_ATTR(pwm4_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
1183 store_fan_stop_output, 3),
1184 SENSOR_ATTR(pwm4_max_output, S_IWUSR | S_IRUGO, show_fan_max_output,
1185 store_fan_max_output, 3),
1186 SENSOR_ATTR(pwm4_step_output, S_IWUSR | S_IRUGO, show_fan_step_output,
1187 store_fan_step_output, 3),
1166}; 1188};
1167 1189
1168static struct sensor_device_attribute sda_sf3_arrays[] = { 1190static struct sensor_device_attribute sda_sf3_arrays[] = {
@@ -1172,12 +1194,24 @@ static struct sensor_device_attribute sda_sf3_arrays[] = {
1172 store_fan_stop_time, 1), 1194 store_fan_stop_time, 1),
1173 SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, 1195 SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
1174 store_fan_stop_time, 2), 1196 store_fan_stop_time, 2),
1175 SENSOR_ATTR(pwm1_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, 1197 SENSOR_ATTR(pwm1_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
1176 store_fan_min_output, 0), 1198 store_fan_start_output, 0),
1177 SENSOR_ATTR(pwm2_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, 1199 SENSOR_ATTR(pwm2_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
1178 store_fan_min_output, 1), 1200 store_fan_start_output, 1),
1179 SENSOR_ATTR(pwm3_min_output, S_IWUSR | S_IRUGO, show_fan_min_output, 1201 SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output,
1180 store_fan_min_output, 2), 1202 store_fan_start_output, 2),
1203 SENSOR_ATTR(pwm1_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
1204 store_fan_stop_output, 0),
1205 SENSOR_ATTR(pwm2_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
1206 store_fan_stop_output, 1),
1207 SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output,
1208 store_fan_stop_output, 2),
1209
1210 /* pwm1 and pwm3 don't support max and step settings */
1211 SENSOR_ATTR(pwm2_max_output, S_IWUSR | S_IRUGO, show_fan_max_output,
1212 store_fan_max_output, 1),
1213 SENSOR_ATTR(pwm2_step_output, S_IWUSR | S_IRUGO, show_fan_step_output,
1214 store_fan_step_output, 1),
1181}; 1215};
1182 1216
1183static ssize_t 1217static ssize_t