diff options
| -rw-r--r-- | Documentation/hwmon/it87 | 10 | ||||
| -rw-r--r-- | Documentation/hwmon/sysfs-interface | 15 | ||||
| -rw-r--r-- | drivers/hwmon/it87.c | 56 |
3 files changed, 74 insertions, 7 deletions
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87 index 74a80992d237..c0528d6f9ace 100644 --- a/Documentation/hwmon/it87 +++ b/Documentation/hwmon/it87 | |||
| @@ -135,6 +135,16 @@ Give 0 for unused sensor. Any other value is invalid. To configure this at | |||
| 135 | startup, consult lm_sensors's /etc/sensors.conf. (2 = thermistor; | 135 | startup, consult lm_sensors's /etc/sensors.conf. (2 = thermistor; |
| 136 | 3 = thermal diode) | 136 | 3 = thermal diode) |
| 137 | 137 | ||
| 138 | |||
| 139 | Fan speed control | ||
| 140 | ----------------- | ||
| 141 | |||
| 138 | The fan speed control features are limited to manual PWM mode. Automatic | 142 | The fan speed control features are limited to manual PWM mode. Automatic |
| 139 | "Smart Guardian" mode control handling is not implemented. However | 143 | "Smart Guardian" mode control handling is not implemented. However |
| 140 | if you want to go for "manual mode" just write 1 to pwmN_enable. | 144 | if you want to go for "manual mode" just write 1 to pwmN_enable. |
| 145 | |||
| 146 | If you are only able to control the fan speed with very small PWM values, | ||
| 147 | try lowering the PWM base frequency (pwm1_freq). Depending on the fan, | ||
| 148 | it may give you a somewhat greater control range. The same frequency is | ||
| 149 | used to drive all fan outputs, which is why pwm2_freq and pwm3_freq are | ||
| 150 | read-only. | ||
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface index efef3b962cd3..d73d2e8c7534 100644 --- a/Documentation/hwmon/sysfs-interface +++ b/Documentation/hwmon/sysfs-interface | |||
| @@ -166,16 +166,21 @@ pwm[1-*] Pulse width modulation fan control. | |||
| 166 | 166 | ||
| 167 | pwm[1-*]_enable | 167 | pwm[1-*]_enable |
| 168 | Switch PWM on and off. | 168 | Switch PWM on and off. |
| 169 | Not always present even if fan*_pwm is. | 169 | Not always present even if pwmN is. |
| 170 | 0: turn off | 170 | 0: turn off |
| 171 | 1: turn on in manual mode | 171 | 1: turn on in manual mode |
| 172 | 2+: turn on in automatic mode | 172 | 2+: turn on in automatic mode |
| 173 | Check individual chip documentation files for automatic mode details. | 173 | Check individual chip documentation files for automatic mode |
| 174 | details. | ||
| 174 | RW | 175 | RW |
| 175 | 176 | ||
| 176 | pwm[1-*]_mode | 177 | pwm[1-*]_mode 0: DC mode (direct current) |
| 177 | 0: DC mode | 178 | 1: PWM mode (pulse-width modulation) |
| 178 | 1: PWM mode | 179 | RW |
| 180 | |||
| 181 | pwm[1-*]_freq Base PWM frequency in Hz. | ||
| 182 | Only possibly available when pwmN_mode is PWM, but not always | ||
| 183 | present even then. | ||
| 179 | RW | 184 | RW |
| 180 | 185 | ||
| 181 | pwm[1-*]_auto_channels_temp | 186 | pwm[1-*]_auto_channels_temp |
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 1ed8b7e2c35d..bb16668ad2bd 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
| @@ -202,6 +202,17 @@ static int DIV_TO_REG(int val) | |||
| 202 | } | 202 | } |
| 203 | #define DIV_FROM_REG(val) (1 << (val)) | 203 | #define DIV_FROM_REG(val) (1 << (val)) |
| 204 | 204 | ||
| 205 | static const unsigned int pwm_freq[8] = { | ||
| 206 | 48000000 / 128, | ||
| 207 | 24000000 / 128, | ||
| 208 | 12000000 / 128, | ||
| 209 | 8000000 / 128, | ||
| 210 | 6000000 / 128, | ||
| 211 | 3000000 / 128, | ||
| 212 | 1500000 / 128, | ||
| 213 | 750000 / 128, | ||
| 214 | }; | ||
| 215 | |||
| 205 | 216 | ||
| 206 | /* For each registered IT87, we need to keep some data in memory. That | 217 | /* For each registered IT87, we need to keep some data in memory. That |
| 207 | data is pointed to by it87_list[NR]->data. The structure itself is | 218 | data is pointed to by it87_list[NR]->data. The structure itself is |
| @@ -232,6 +243,7 @@ struct it87_data { | |||
| 232 | u8 vrm; | 243 | u8 vrm; |
| 233 | u32 alarms; /* Register encoding, combined */ | 244 | u32 alarms; /* Register encoding, combined */ |
| 234 | u8 fan_main_ctrl; /* Register value */ | 245 | u8 fan_main_ctrl; /* Register value */ |
| 246 | u8 fan_ctl; /* Register value */ | ||
| 235 | u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ | 247 | u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ |
| 236 | }; | 248 | }; |
| 237 | 249 | ||
| @@ -519,6 +531,14 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | |||
| 519 | struct it87_data *data = it87_update_device(dev); | 531 | struct it87_data *data = it87_update_device(dev); |
| 520 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); | 532 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); |
| 521 | } | 533 | } |
| 534 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, | ||
| 535 | char *buf) | ||
| 536 | { | ||
| 537 | struct it87_data *data = it87_update_device(dev); | ||
| 538 | int index = (data->fan_ctl >> 4) & 0x07; | ||
| 539 | |||
| 540 | return sprintf(buf, "%u\n", pwm_freq[index]); | ||
| 541 | } | ||
| 522 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | 542 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, |
| 523 | const char *buf, size_t count) | 543 | const char *buf, size_t count) |
| 524 | { | 544 | { |
| @@ -639,6 +659,28 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
| 639 | mutex_unlock(&data->update_lock); | 659 | mutex_unlock(&data->update_lock); |
| 640 | return count; | 660 | return count; |
| 641 | } | 661 | } |
| 662 | static ssize_t set_pwm_freq(struct device *dev, | ||
| 663 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 664 | { | ||
| 665 | struct i2c_client *client = to_i2c_client(dev); | ||
| 666 | struct it87_data *data = i2c_get_clientdata(client); | ||
| 667 | unsigned long val = simple_strtoul(buf, NULL, 10); | ||
| 668 | int i; | ||
| 669 | |||
| 670 | /* Search for the nearest available frequency */ | ||
| 671 | for (i = 0; i < 7; i++) { | ||
| 672 | if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) | ||
| 673 | break; | ||
| 674 | } | ||
| 675 | |||
| 676 | mutex_lock(&data->update_lock); | ||
| 677 | data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL) & 0x8f; | ||
| 678 | data->fan_ctl |= i << 4; | ||
| 679 | it87_write_value(client, IT87_REG_FAN_CTL, data->fan_ctl); | ||
| 680 | mutex_unlock(&data->update_lock); | ||
| 681 | |||
| 682 | return count; | ||
| 683 | } | ||
| 642 | 684 | ||
| 643 | #define show_fan_offset(offset) \ | 685 | #define show_fan_offset(offset) \ |
| 644 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ | 686 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ |
| @@ -656,7 +698,10 @@ show_fan_offset(3); | |||
| 656 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ | 698 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ |
| 657 | show_pwm_enable, set_pwm_enable, offset - 1); \ | 699 | show_pwm_enable, set_pwm_enable, offset - 1); \ |
| 658 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | 700 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ |
| 659 | show_pwm, set_pwm, offset - 1); | 701 | show_pwm, set_pwm, offset - 1); \ |
| 702 | static DEVICE_ATTR(pwm##offset##_freq, \ | ||
| 703 | (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ | ||
| 704 | show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); | ||
| 660 | 705 | ||
| 661 | show_pwm_offset(1); | 706 | show_pwm_offset(1); |
| 662 | show_pwm_offset(2); | 707 | show_pwm_offset(2); |
| @@ -1021,7 +1066,13 @@ static int it87_detect(struct i2c_adapter *adapter) | |||
| 1021 | || (err = device_create_file(&new_client->dev, | 1066 | || (err = device_create_file(&new_client->dev, |
| 1022 | &sensor_dev_attr_pwm2.dev_attr)) | 1067 | &sensor_dev_attr_pwm2.dev_attr)) |
| 1023 | || (err = device_create_file(&new_client->dev, | 1068 | || (err = device_create_file(&new_client->dev, |
| 1024 | &sensor_dev_attr_pwm3.dev_attr))) | 1069 | &sensor_dev_attr_pwm3.dev_attr)) |
| 1070 | || (err = device_create_file(&new_client->dev, | ||
| 1071 | &dev_attr_pwm1_freq)) | ||
| 1072 | || (err = device_create_file(&new_client->dev, | ||
| 1073 | &dev_attr_pwm2_freq)) | ||
| 1074 | || (err = device_create_file(&new_client->dev, | ||
| 1075 | &dev_attr_pwm3_freq))) | ||
| 1025 | goto ERROR4; | 1076 | goto ERROR4; |
| 1026 | } | 1077 | } |
| 1027 | 1078 | ||
| @@ -1316,6 +1367,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
| 1316 | (it87_read_value(client, IT87_REG_ALARM2) << 8) | | 1367 | (it87_read_value(client, IT87_REG_ALARM2) << 8) | |
| 1317 | (it87_read_value(client, IT87_REG_ALARM3) << 16); | 1368 | (it87_read_value(client, IT87_REG_ALARM3) << 16); |
| 1318 | data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); | 1369 | data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); |
| 1370 | data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL); | ||
| 1319 | 1371 | ||
| 1320 | data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); | 1372 | data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); |
| 1321 | /* The 8705 does not have VID capability */ | 1373 | /* The 8705 does not have VID capability */ |
