diff options
author | Jean Delvare <khali@linux-fr.org> | 2012-03-23 05:02:19 -0400 |
---|---|---|
committer | Jean Delvare <khali@endymion.delvare> | 2012-03-23 05:02:19 -0400 |
commit | af2ef4fc043f8fef078ba58c6cd8483d1348d70b (patch) | |
tree | fb29644aa69298791ee454e02dd137a007e8316b /drivers/hwmon | |
parent | 817c6cc546a4ebea8016766f0f26e7d53118c6b6 (diff) |
hwmon: (lm63) Let the user adjust the lookup table
Make the automatic fan speed control lookup table writable. This lets
the user tweak the fan speed / temperature response curve.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Acked-by: Guenter Roeck <guenter.roeck@ericsson.com>
Tested-by: Guenter Roeck <guenter.roeck@ericsson.com>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/lm63.c | 118 |
1 files changed, 76 insertions, 42 deletions
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 910599ac31ca..602a0f0b0de8 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c | |||
@@ -205,6 +205,15 @@ static inline int lut_temp_from_reg(struct lm63_data *data, int nr) | |||
205 | return data->temp8[nr] * (data->lut_temp_highres ? 500 : 1000); | 205 | return data->temp8[nr] * (data->lut_temp_highres ? 500 : 1000); |
206 | } | 206 | } |
207 | 207 | ||
208 | static inline int lut_temp_to_reg(struct lm63_data *data, long val) | ||
209 | { | ||
210 | val -= data->temp2_offset; | ||
211 | if (data->lut_temp_highres) | ||
212 | return DIV_ROUND_CLOSEST(SENSORS_LIMIT(val, 0, 127500), 500); | ||
213 | else | ||
214 | return DIV_ROUND_CLOSEST(SENSORS_LIMIT(val, 0, 127000), 1000); | ||
215 | } | ||
216 | |||
208 | /* | 217 | /* |
209 | * Update the lookup table register cache. | 218 | * Update the lookup table register cache. |
210 | * client->update_lock must be held when calling this function. | 219 | * client->update_lock must be held when calling this function. |
@@ -387,13 +396,16 @@ static ssize_t show_pwm1(struct device *dev, struct device_attribute *devattr, | |||
387 | return sprintf(buf, "%d\n", pwm); | 396 | return sprintf(buf, "%d\n", pwm); |
388 | } | 397 | } |
389 | 398 | ||
390 | static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy, | 399 | static ssize_t set_pwm1(struct device *dev, struct device_attribute *devattr, |
391 | const char *buf, size_t count) | 400 | const char *buf, size_t count) |
392 | { | 401 | { |
402 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
393 | struct i2c_client *client = to_i2c_client(dev); | 403 | struct i2c_client *client = to_i2c_client(dev); |
394 | struct lm63_data *data = i2c_get_clientdata(client); | 404 | struct lm63_data *data = i2c_get_clientdata(client); |
405 | int nr = attr->index; | ||
395 | unsigned long val; | 406 | unsigned long val; |
396 | int err; | 407 | int err; |
408 | u8 reg; | ||
397 | 409 | ||
398 | if (!(data->config_fan & 0x20)) /* register is read-only */ | 410 | if (!(data->config_fan & 0x20)) /* register is read-only */ |
399 | return -EPERM; | 411 | return -EPERM; |
@@ -402,11 +414,13 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy, | |||
402 | if (err) | 414 | if (err) |
403 | return err; | 415 | return err; |
404 | 416 | ||
417 | reg = nr ? LM63_REG_LUT_PWM(nr - 1) : LM63_REG_PWM_VALUE; | ||
405 | val = SENSORS_LIMIT(val, 0, 255); | 418 | val = SENSORS_LIMIT(val, 0, 255); |
419 | |||
406 | mutex_lock(&data->update_lock); | 420 | mutex_lock(&data->update_lock); |
407 | data->pwm1[0] = data->pwm_highres ? val : | 421 | data->pwm1[nr] = data->pwm_highres ? val : |
408 | (val * data->pwm1_freq * 2 + 127) / 255; | 422 | (val * data->pwm1_freq * 2 + 127) / 255; |
409 | i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1[0]); | 423 | i2c_smbus_write_byte_data(client, reg, data->pwm1[nr]); |
410 | mutex_unlock(&data->update_lock); | 424 | mutex_unlock(&data->update_lock); |
411 | return count; | 425 | return count; |
412 | } | 426 | } |
@@ -495,23 +509,31 @@ static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, | |||
495 | struct i2c_client *client = to_i2c_client(dev); | 509 | struct i2c_client *client = to_i2c_client(dev); |
496 | struct lm63_data *data = i2c_get_clientdata(client); | 510 | struct lm63_data *data = i2c_get_clientdata(client); |
497 | int nr = attr->index; | 511 | int nr = attr->index; |
498 | int reg = nr == 2 ? LM63_REG_REMOTE_TCRIT : LM63_REG_LOCAL_HIGH; | ||
499 | long val; | 512 | long val; |
500 | int err; | 513 | int err; |
501 | int temp; | 514 | int temp; |
515 | u8 reg; | ||
502 | 516 | ||
503 | err = kstrtol(buf, 10, &val); | 517 | err = kstrtol(buf, 10, &val); |
504 | if (err) | 518 | if (err) |
505 | return err; | 519 | return err; |
506 | 520 | ||
507 | mutex_lock(&data->update_lock); | 521 | mutex_lock(&data->update_lock); |
508 | if (nr == 2) { | 522 | switch (nr) { |
523 | case 2: | ||
524 | reg = LM63_REG_REMOTE_TCRIT; | ||
509 | if (data->remote_unsigned) | 525 | if (data->remote_unsigned) |
510 | temp = TEMP8U_TO_REG(val - data->temp2_offset); | 526 | temp = TEMP8U_TO_REG(val - data->temp2_offset); |
511 | else | 527 | else |
512 | temp = TEMP8_TO_REG(val - data->temp2_offset); | 528 | temp = TEMP8_TO_REG(val - data->temp2_offset); |
513 | } else { | 529 | break; |
530 | case 1: | ||
531 | reg = LM63_REG_LOCAL_HIGH; | ||
514 | temp = TEMP8_TO_REG(val); | 532 | temp = TEMP8_TO_REG(val); |
533 | break; | ||
534 | default: /* lookup table */ | ||
535 | reg = LM63_REG_LUT_TEMP(nr - 3); | ||
536 | temp = lut_temp_to_reg(data, val); | ||
515 | } | 537 | } |
516 | data->temp8[nr] = temp; | 538 | data->temp8[nr] = temp; |
517 | i2c_smbus_write_byte_data(client, reg, temp); | 539 | i2c_smbus_write_byte_data(client, reg, temp); |
@@ -743,64 +765,76 @@ static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan, | |||
743 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1, 0); | 765 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1, 0); |
744 | static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, | 766 | static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, |
745 | show_pwm1_enable, set_pwm1_enable); | 767 | show_pwm1_enable, set_pwm1_enable); |
746 | static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, show_pwm1, NULL, 1); | 768 | static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, |
747 | static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IRUGO, | 769 | show_pwm1, set_pwm1, 1); |
748 | show_lut_temp, NULL, 3); | 770 | static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO, |
771 | show_lut_temp, set_temp8, 3); | ||
749 | static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp_hyst, S_IRUGO, | 772 | static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp_hyst, S_IRUGO, |
750 | show_lut_temp_hyst, NULL, 3); | 773 | show_lut_temp_hyst, NULL, 3); |
751 | static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IRUGO, show_pwm1, NULL, 2); | 774 | static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, |
752 | static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IRUGO, | 775 | show_pwm1, set_pwm1, 2); |
753 | show_lut_temp, NULL, 4); | 776 | static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IWUSR | S_IRUGO, |
777 | show_lut_temp, set_temp8, 4); | ||
754 | static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp_hyst, S_IRUGO, | 778 | static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp_hyst, S_IRUGO, |
755 | show_lut_temp_hyst, NULL, 4); | 779 | show_lut_temp_hyst, NULL, 4); |
756 | static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, show_pwm1, NULL, 3); | 780 | static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IWUSR | S_IRUGO, |
757 | static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp, S_IRUGO, | 781 | show_pwm1, set_pwm1, 3); |
758 | show_lut_temp, NULL, 5); | 782 | static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp, S_IWUSR | S_IRUGO, |
783 | show_lut_temp, set_temp8, 5); | ||
759 | static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp_hyst, S_IRUGO, | 784 | static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp_hyst, S_IRUGO, |
760 | show_lut_temp_hyst, NULL, 5); | 785 | show_lut_temp_hyst, NULL, 5); |
761 | static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IRUGO, show_pwm1, NULL, 4); | 786 | static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IWUSR | S_IRUGO, |
762 | static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp, S_IRUGO, | 787 | show_pwm1, set_pwm1, 4); |
763 | show_lut_temp, NULL, 6); | 788 | static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp, S_IWUSR | S_IRUGO, |
789 | show_lut_temp, set_temp8, 6); | ||
764 | static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp_hyst, S_IRUGO, | 790 | static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp_hyst, S_IRUGO, |
765 | show_lut_temp_hyst, NULL, 6); | 791 | show_lut_temp_hyst, NULL, 6); |
766 | static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IRUGO, show_pwm1, NULL, 5); | 792 | static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IWUSR | S_IRUGO, |
767 | static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp, S_IRUGO, | 793 | show_pwm1, set_pwm1, 5); |
768 | show_lut_temp, NULL, 7); | 794 | static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp, S_IWUSR | S_IRUGO, |
795 | show_lut_temp, set_temp8, 7); | ||
769 | static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp_hyst, S_IRUGO, | 796 | static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp_hyst, S_IRUGO, |
770 | show_lut_temp_hyst, NULL, 7); | 797 | show_lut_temp_hyst, NULL, 7); |
771 | static SENSOR_DEVICE_ATTR(pwm1_auto_point6_pwm, S_IRUGO, show_pwm1, NULL, 6); | 798 | static SENSOR_DEVICE_ATTR(pwm1_auto_point6_pwm, S_IWUSR | S_IRUGO, |
772 | static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp, S_IRUGO, | 799 | show_pwm1, set_pwm1, 6); |
773 | show_lut_temp, NULL, 8); | 800 | static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp, S_IWUSR | S_IRUGO, |
801 | show_lut_temp, set_temp8, 8); | ||
774 | static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp_hyst, S_IRUGO, | 802 | static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp_hyst, S_IRUGO, |
775 | show_lut_temp_hyst, NULL, 8); | 803 | show_lut_temp_hyst, NULL, 8); |
776 | static SENSOR_DEVICE_ATTR(pwm1_auto_point7_pwm, S_IRUGO, show_pwm1, NULL, 7); | 804 | static SENSOR_DEVICE_ATTR(pwm1_auto_point7_pwm, S_IWUSR | S_IRUGO, |
777 | static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp, S_IRUGO, | 805 | show_pwm1, set_pwm1, 7); |
778 | show_lut_temp, NULL, 9); | 806 | static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp, S_IWUSR | S_IRUGO, |
807 | show_lut_temp, set_temp8, 9); | ||
779 | static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp_hyst, S_IRUGO, | 808 | static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp_hyst, S_IRUGO, |
780 | show_lut_temp_hyst, NULL, 9); | 809 | show_lut_temp_hyst, NULL, 9); |
781 | static SENSOR_DEVICE_ATTR(pwm1_auto_point8_pwm, S_IRUGO, show_pwm1, NULL, 8); | 810 | static SENSOR_DEVICE_ATTR(pwm1_auto_point8_pwm, S_IWUSR | S_IRUGO, |
782 | static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp, S_IRUGO, | 811 | show_pwm1, set_pwm1, 8); |
783 | show_lut_temp, NULL, 10); | 812 | static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp, S_IWUSR | S_IRUGO, |
813 | show_lut_temp, set_temp8, 10); | ||
784 | static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp_hyst, S_IRUGO, | 814 | static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp_hyst, S_IRUGO, |
785 | show_lut_temp_hyst, NULL, 10); | 815 | show_lut_temp_hyst, NULL, 10); |
786 | static SENSOR_DEVICE_ATTR(pwm1_auto_point9_pwm, S_IRUGO, show_pwm1, NULL, 9); | 816 | static SENSOR_DEVICE_ATTR(pwm1_auto_point9_pwm, S_IWUSR | S_IRUGO, |
787 | static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp, S_IRUGO, | 817 | show_pwm1, set_pwm1, 9); |
788 | show_lut_temp, NULL, 11); | 818 | static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp, S_IWUSR | S_IRUGO, |
819 | show_lut_temp, set_temp8, 11); | ||
789 | static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp_hyst, S_IRUGO, | 820 | static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp_hyst, S_IRUGO, |
790 | show_lut_temp_hyst, NULL, 11); | 821 | show_lut_temp_hyst, NULL, 11); |
791 | static SENSOR_DEVICE_ATTR(pwm1_auto_point10_pwm, S_IRUGO, show_pwm1, NULL, 10); | 822 | static SENSOR_DEVICE_ATTR(pwm1_auto_point10_pwm, S_IWUSR | S_IRUGO, |
792 | static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp, S_IRUGO, | 823 | show_pwm1, set_pwm1, 10); |
793 | show_lut_temp, NULL, 12); | 824 | static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp, S_IWUSR | S_IRUGO, |
825 | show_lut_temp, set_temp8, 12); | ||
794 | static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp_hyst, S_IRUGO, | 826 | static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp_hyst, S_IRUGO, |
795 | show_lut_temp_hyst, NULL, 12); | 827 | show_lut_temp_hyst, NULL, 12); |
796 | static SENSOR_DEVICE_ATTR(pwm1_auto_point11_pwm, S_IRUGO, show_pwm1, NULL, 11); | 828 | static SENSOR_DEVICE_ATTR(pwm1_auto_point11_pwm, S_IWUSR | S_IRUGO, |
797 | static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp, S_IRUGO, | 829 | show_pwm1, set_pwm1, 11); |
798 | show_lut_temp, NULL, 13); | 830 | static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp, S_IWUSR | S_IRUGO, |
831 | show_lut_temp, set_temp8, 13); | ||
799 | static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp_hyst, S_IRUGO, | 832 | static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp_hyst, S_IRUGO, |
800 | show_lut_temp_hyst, NULL, 13); | 833 | show_lut_temp_hyst, NULL, 13); |
801 | static SENSOR_DEVICE_ATTR(pwm1_auto_point12_pwm, S_IRUGO, show_pwm1, NULL, 12); | 834 | static SENSOR_DEVICE_ATTR(pwm1_auto_point12_pwm, S_IWUSR | S_IRUGO, |
802 | static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp, S_IRUGO, | 835 | show_pwm1, set_pwm1, 12); |
803 | show_lut_temp, NULL, 14); | 836 | static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp, S_IWUSR | S_IRUGO, |
837 | show_lut_temp, set_temp8, 14); | ||
804 | static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp_hyst, S_IRUGO, | 838 | static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp_hyst, S_IRUGO, |
805 | show_lut_temp_hyst, NULL, 14); | 839 | show_lut_temp_hyst, NULL, 14); |
806 | 840 | ||