aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/f75375s.c
diff options
context:
space:
mode:
authorNikolaus Schulz <schulz@macnetix.de>2012-02-28 16:15:53 -0500
committerGuenter Roeck <guenter.roeck@ericsson.com>2012-03-02 14:56:43 -0500
commitb17d6561acc16265b65b1e0d27b649829b61a7e3 (patch)
tree0bcfd3e723d7af6787f5c9a01d825a1cc665bab1 /drivers/hwmon/f75375s.c
parentedeea102857e33b5e9b17a3a2640da390732a693 (diff)
hwmon: (f75375s) Properly map the F75387 automatic modes to pwm_enable
The F75387 supports automatic fan control using either PWM duty cycle or RPM speed values. Make the driver detect the latter mode, and expose the different modes in sysfs as per pwm_enable, so that the user can switch between them. The interpretation of the pwm_enable attribute for the F75387 is adjusted to be a superset of those values used for similar Fintek chips which do not support automatic duty mode, with 2 mapping to automatic speed mode, and moving automatic duty mode to the new value 4. Toggling the duty mode via pwm_enable is currently denied for the F75387, as the chip then simply reinterprets the fan configuration register values according to the new mode, switching between RPM and PWM units, which makes this a dangerous operation. This patch introduces a new pwm mode into the driver. This is necessary because the new mode (automatic pwm mode, 4) may already be enabled by the BIOS, and the driver should not break existing functionality. This was seen on at least one board. Signed-off-by: Nikolaus Schulz <mail@microschulz.de> Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
Diffstat (limited to 'drivers/hwmon/f75375s.c')
-rw-r--r--drivers/hwmon/f75375s.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index eb648d9c91d6..9ab034a1b4c1 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -264,6 +264,21 @@ static inline u16 rpm_to_reg(int rpm)
264 return 1500000 / rpm; 264 return 1500000 / rpm;
265} 265}
266 266
267static bool duty_mode_enabled(u8 pwm_enable)
268{
269 switch (pwm_enable) {
270 case 0: /* Manual, duty mode (full speed) */
271 case 1: /* Manual, duty mode */
272 case 4: /* Auto, duty mode */
273 return true;
274 case 2: /* Auto, speed mode */
275 case 3: /* Manual, speed mode */
276 return false;
277 default:
278 BUG();
279 }
280}
281
267static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, 282static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
268 const char *buf, size_t count) 283 const char *buf, size_t count)
269{ 284{
@@ -337,11 +352,15 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
337 struct f75375_data *data = i2c_get_clientdata(client); 352 struct f75375_data *data = i2c_get_clientdata(client);
338 u8 fanmode; 353 u8 fanmode;
339 354
340 if (val < 0 || val > 3) 355 if (val < 0 || val > 4)
341 return -EINVAL; 356 return -EINVAL;
342 357
343 fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); 358 fanmode = f75375_read8(client, F75375_REG_FAN_TIMER);
344 if (data->kind == f75387) { 359 if (data->kind == f75387) {
360 /* For now, deny dangerous toggling of duty mode */
361 if (duty_mode_enabled(data->pwm_enable[nr]) !=
362 duty_mode_enabled(val))
363 return -EOPNOTSUPP;
345 /* clear each fanX_mode bit before setting them properly */ 364 /* clear each fanX_mode bit before setting them properly */
346 fanmode &= ~(1 << F75387_FAN_DUTY_MODE(nr)); 365 fanmode &= ~(1 << F75387_FAN_DUTY_MODE(nr));
347 fanmode &= ~(1 << F75387_FAN_MANU_MODE(nr)); 366 fanmode &= ~(1 << F75387_FAN_MANU_MODE(nr));
@@ -355,12 +374,14 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
355 fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); 374 fanmode |= (1 << F75387_FAN_MANU_MODE(nr));
356 fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); 375 fanmode |= (1 << F75387_FAN_DUTY_MODE(nr));
357 break; 376 break;
358 case 2: /* AUTOMATIC*/ 377 case 2: /* Automatic, speed mode */
359 fanmode |= (1 << F75387_FAN_DUTY_MODE(nr));
360 break; 378 break;
361 case 3: /* fan speed */ 379 case 3: /* fan speed */
362 fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); 380 fanmode |= (1 << F75387_FAN_MANU_MODE(nr));
363 break; 381 break;
382 case 4: /* Automatic, pwm */
383 fanmode |= (1 << F75387_FAN_DUTY_MODE(nr));
384 break;
364 } 385 }
365 } else { 386 } else {
366 /* clear each fanX_mode bit before setting them properly */ 387 /* clear each fanX_mode bit before setting them properly */
@@ -378,6 +399,8 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
378 break; 399 break;
379 case 3: /* fan speed */ 400 case 3: /* fan speed */
380 break; 401 break;
402 case 4: /* Automatic pwm */
403 return -EINVAL;
381 } 404 }
382 } 405 }
383 406
@@ -735,14 +758,17 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data,
735 758
736 manu = ((mode >> F75387_FAN_MANU_MODE(nr)) & 1); 759 manu = ((mode >> F75387_FAN_MANU_MODE(nr)) & 1);
737 duty = ((mode >> F75387_FAN_DUTY_MODE(nr)) & 1); 760 duty = ((mode >> F75387_FAN_DUTY_MODE(nr)) & 1);
738 if (manu && duty) 761 if (!manu && duty)
739 /* speed */ 762 /* auto, pwm */
763 data->pwm_enable[nr] = 4;
764 else if (manu && !duty)
765 /* manual, speed */
740 data->pwm_enable[nr] = 3; 766 data->pwm_enable[nr] = 3;
741 else if (!manu && duty) 767 else if (!manu && !duty)
742 /* automatic */ 768 /* automatic, speed */
743 data->pwm_enable[nr] = 2; 769 data->pwm_enable[nr] = 2;
744 else 770 else
745 /* manual */ 771 /* manual, pwm */
746 data->pwm_enable[nr] = 1; 772 data->pwm_enable[nr] = 1;
747 } else { 773 } else {
748 if (!(conf & (1 << F75375_FAN_CTRL_LINEAR(nr)))) 774 if (!(conf & (1 << F75375_FAN_CTRL_LINEAR(nr))))