aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/it87.c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2007-02-14 15:15:02 -0500
committerJean Delvare <khali@arrakis.delvare>2007-02-14 15:15:02 -0500
commitf8d0c19a93cea3a26a90f2462295e1e01a4cd250 (patch)
tree6d874a35f611a1c344896ef13a911a80a3d10017 /drivers/hwmon/it87.c
parentac98695d6c1508b724f246f38ce57fb4e3cec356 (diff)
hwmon/it87: Add PWM base frequency control
Let the user select the base PWM frequency when using the it87 hardware monitoring driver. Different frequencies can give better control on some fans. Also update the documentation to mention the PWM frequency control files, with misc cleanups to the PWM section. Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/it87.c')
-rw-r--r--drivers/hwmon/it87.c56
1 files changed, 54 insertions, 2 deletions
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
205static 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}
534static 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}
522static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, 542static 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}
662static 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) \
644static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ 686static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
@@ -656,7 +698,10 @@ show_fan_offset(3);
656static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ 698static 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); \
658static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ 700static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
659 show_pwm, set_pwm, offset - 1); 701 show_pwm, set_pwm, offset - 1); \
702static 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
661show_pwm_offset(1); 706show_pwm_offset(1);
662show_pwm_offset(2); 707show_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 */