diff options
| -rw-r--r-- | drivers/hwmon/f75375s.c | 89 |
1 files changed, 75 insertions, 14 deletions
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 6bab2001ef3b..6aa5a9fad879 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c | |||
| @@ -178,6 +178,16 @@ static inline void f75375_write16(struct i2c_client *client, u8 reg, | |||
| 178 | i2c_smbus_write_byte_data(client, reg + 1, (value & 0xFF)); | 178 | i2c_smbus_write_byte_data(client, reg + 1, (value & 0xFF)); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | static void f75375_write_pwm(struct i2c_client *client, int nr) | ||
| 182 | { | ||
| 183 | struct f75375_data *data = i2c_get_clientdata(client); | ||
| 184 | if (data->kind == f75387) | ||
| 185 | f75375_write16(client, F75375_REG_FAN_EXP(nr), data->pwm[nr]); | ||
| 186 | else | ||
| 187 | f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr), | ||
| 188 | data->pwm[nr]); | ||
| 189 | } | ||
| 190 | |||
| 181 | static struct f75375_data *f75375_update_device(struct device *dev) | 191 | static struct f75375_data *f75375_update_device(struct device *dev) |
| 182 | { | 192 | { |
| 183 | struct i2c_client *client = to_i2c_client(dev); | 193 | struct i2c_client *client = to_i2c_client(dev); |
| @@ -254,6 +264,36 @@ static inline u16 rpm_to_reg(int rpm) | |||
| 254 | return 1500000 / rpm; | 264 | return 1500000 / rpm; |
| 255 | } | 265 | } |
| 256 | 266 | ||
| 267 | static 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 | |||
| 282 | static bool auto_mode_enabled(u8 pwm_enable) | ||
| 283 | { | ||
| 284 | switch (pwm_enable) { | ||
| 285 | case 0: /* Manual, duty mode (full speed) */ | ||
| 286 | case 1: /* Manual, duty mode */ | ||
| 287 | case 3: /* Manual, speed mode */ | ||
| 288 | return false; | ||
| 289 | case 2: /* Auto, speed mode */ | ||
| 290 | case 4: /* Auto, duty mode */ | ||
| 291 | return true; | ||
| 292 | default: | ||
| 293 | BUG(); | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 257 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | 297 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, |
| 258 | const char *buf, size_t count) | 298 | const char *buf, size_t count) |
| 259 | { | 299 | { |
| @@ -287,6 +327,11 @@ static ssize_t set_fan_target(struct device *dev, struct device_attribute *attr, | |||
| 287 | if (err < 0) | 327 | if (err < 0) |
| 288 | return err; | 328 | return err; |
| 289 | 329 | ||
| 330 | if (auto_mode_enabled(data->pwm_enable[nr])) | ||
| 331 | return -EINVAL; | ||
| 332 | if (data->kind == f75387 && duty_mode_enabled(data->pwm_enable[nr])) | ||
| 333 | return -EINVAL; | ||
| 334 | |||
| 290 | mutex_lock(&data->update_lock); | 335 | mutex_lock(&data->update_lock); |
| 291 | data->fan_target[nr] = rpm_to_reg(val); | 336 | data->fan_target[nr] = rpm_to_reg(val); |
| 292 | f75375_write16(client, F75375_REG_FAN_EXP(nr), data->fan_target[nr]); | 337 | f75375_write16(client, F75375_REG_FAN_EXP(nr), data->fan_target[nr]); |
| @@ -307,9 +352,13 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
| 307 | if (err < 0) | 352 | if (err < 0) |
| 308 | return err; | 353 | return err; |
| 309 | 354 | ||
| 355 | if (auto_mode_enabled(data->pwm_enable[nr]) || | ||
| 356 | !duty_mode_enabled(data->pwm_enable[nr])) | ||
| 357 | return -EINVAL; | ||
| 358 | |||
| 310 | mutex_lock(&data->update_lock); | 359 | mutex_lock(&data->update_lock); |
| 311 | data->pwm[nr] = SENSORS_LIMIT(val, 0, 255); | 360 | data->pwm[nr] = SENSORS_LIMIT(val, 0, 255); |
| 312 | f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr), data->pwm[nr]); | 361 | f75375_write_pwm(client, nr); |
| 313 | mutex_unlock(&data->update_lock); | 362 | mutex_unlock(&data->update_lock); |
| 314 | return count; | 363 | return count; |
| 315 | } | 364 | } |
| @@ -327,11 +376,15 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) | |||
| 327 | struct f75375_data *data = i2c_get_clientdata(client); | 376 | struct f75375_data *data = i2c_get_clientdata(client); |
| 328 | u8 fanmode; | 377 | u8 fanmode; |
| 329 | 378 | ||
| 330 | if (val < 0 || val > 3) | 379 | if (val < 0 || val > 4) |
| 331 | return -EINVAL; | 380 | return -EINVAL; |
| 332 | 381 | ||
| 333 | fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); | 382 | fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); |
| 334 | if (data->kind == f75387) { | 383 | if (data->kind == f75387) { |
| 384 | /* For now, deny dangerous toggling of duty mode */ | ||
| 385 | if (duty_mode_enabled(data->pwm_enable[nr]) != | ||
| 386 | duty_mode_enabled(val)) | ||
| 387 | return -EOPNOTSUPP; | ||
| 335 | /* clear each fanX_mode bit before setting them properly */ | 388 | /* clear each fanX_mode bit before setting them properly */ |
| 336 | fanmode &= ~(1 << F75387_FAN_DUTY_MODE(nr)); | 389 | fanmode &= ~(1 << F75387_FAN_DUTY_MODE(nr)); |
| 337 | fanmode &= ~(1 << F75387_FAN_MANU_MODE(nr)); | 390 | fanmode &= ~(1 << F75387_FAN_MANU_MODE(nr)); |
| @@ -345,12 +398,14 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) | |||
| 345 | fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); | 398 | fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); |
| 346 | fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); | 399 | fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); |
| 347 | break; | 400 | break; |
| 348 | case 2: /* AUTOMATIC*/ | 401 | case 2: /* Automatic, speed mode */ |
| 349 | fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); | ||
| 350 | break; | 402 | break; |
| 351 | case 3: /* fan speed */ | 403 | case 3: /* fan speed */ |
| 352 | fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); | 404 | fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); |
| 353 | break; | 405 | break; |
| 406 | case 4: /* Automatic, pwm */ | ||
| 407 | fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); | ||
| 408 | break; | ||
| 354 | } | 409 | } |
| 355 | } else { | 410 | } else { |
| 356 | /* clear each fanX_mode bit before setting them properly */ | 411 | /* clear each fanX_mode bit before setting them properly */ |
| @@ -368,14 +423,15 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) | |||
| 368 | break; | 423 | break; |
| 369 | case 3: /* fan speed */ | 424 | case 3: /* fan speed */ |
| 370 | break; | 425 | break; |
| 426 | case 4: /* Automatic pwm */ | ||
| 427 | return -EINVAL; | ||
| 371 | } | 428 | } |
| 372 | } | 429 | } |
| 373 | 430 | ||
| 374 | f75375_write8(client, F75375_REG_FAN_TIMER, fanmode); | 431 | f75375_write8(client, F75375_REG_FAN_TIMER, fanmode); |
| 375 | data->pwm_enable[nr] = val; | 432 | data->pwm_enable[nr] = val; |
| 376 | if (val == 0) | 433 | if (val == 0) |
| 377 | f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr), | 434 | f75375_write_pwm(client, nr); |
| 378 | data->pwm[nr]); | ||
| 379 | return 0; | 435 | return 0; |
| 380 | } | 436 | } |
| 381 | 437 | ||
| @@ -726,14 +782,17 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data, | |||
| 726 | 782 | ||
| 727 | manu = ((mode >> F75387_FAN_MANU_MODE(nr)) & 1); | 783 | manu = ((mode >> F75387_FAN_MANU_MODE(nr)) & 1); |
| 728 | duty = ((mode >> F75387_FAN_DUTY_MODE(nr)) & 1); | 784 | duty = ((mode >> F75387_FAN_DUTY_MODE(nr)) & 1); |
| 729 | if (manu && duty) | 785 | if (!manu && duty) |
| 730 | /* speed */ | 786 | /* auto, pwm */ |
| 787 | data->pwm_enable[nr] = 4; | ||
| 788 | else if (manu && !duty) | ||
| 789 | /* manual, speed */ | ||
| 731 | data->pwm_enable[nr] = 3; | 790 | data->pwm_enable[nr] = 3; |
| 732 | else if (!manu && duty) | 791 | else if (!manu && !duty) |
| 733 | /* automatic */ | 792 | /* automatic, speed */ |
| 734 | data->pwm_enable[nr] = 2; | 793 | data->pwm_enable[nr] = 2; |
| 735 | else | 794 | else |
| 736 | /* manual */ | 795 | /* manual, pwm */ |
| 737 | data->pwm_enable[nr] = 1; | 796 | data->pwm_enable[nr] = 1; |
| 738 | } else { | 797 | } else { |
| 739 | if (!(conf & (1 << F75375_FAN_CTRL_LINEAR(nr)))) | 798 | if (!(conf & (1 << F75375_FAN_CTRL_LINEAR(nr)))) |
| @@ -758,9 +817,11 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data, | |||
| 758 | set_pwm_enable_direct(client, 0, f75375s_pdata->pwm_enable[0]); | 817 | set_pwm_enable_direct(client, 0, f75375s_pdata->pwm_enable[0]); |
| 759 | set_pwm_enable_direct(client, 1, f75375s_pdata->pwm_enable[1]); | 818 | set_pwm_enable_direct(client, 1, f75375s_pdata->pwm_enable[1]); |
| 760 | for (nr = 0; nr < 2; nr++) { | 819 | for (nr = 0; nr < 2; nr++) { |
| 820 | if (auto_mode_enabled(f75375s_pdata->pwm_enable[nr]) || | ||
| 821 | !duty_mode_enabled(f75375s_pdata->pwm_enable[nr])) | ||
| 822 | continue; | ||
| 761 | data->pwm[nr] = SENSORS_LIMIT(f75375s_pdata->pwm[nr], 0, 255); | 823 | data->pwm[nr] = SENSORS_LIMIT(f75375s_pdata->pwm[nr], 0, 255); |
| 762 | f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr), | 824 | f75375_write_pwm(client, nr); |
| 763 | data->pwm[nr]); | ||
| 764 | } | 825 | } |
| 765 | 826 | ||
| 766 | } | 827 | } |
| @@ -787,7 +848,7 @@ static int f75375_probe(struct i2c_client *client, | |||
| 787 | if (err) | 848 | if (err) |
| 788 | goto exit_free; | 849 | goto exit_free; |
| 789 | 850 | ||
| 790 | if (data->kind == f75375) { | 851 | if (data->kind != f75373) { |
| 791 | err = sysfs_chmod_file(&client->dev.kobj, | 852 | err = sysfs_chmod_file(&client->dev.kobj, |
| 792 | &sensor_dev_attr_pwm1_mode.dev_attr.attr, | 853 | &sensor_dev_attr_pwm1_mode.dev_attr.attr, |
| 793 | S_IRUGO | S_IWUSR); | 854 | S_IRUGO | S_IWUSR); |
