diff options
Diffstat (limited to 'drivers/hwmon/it87.c')
-rw-r--r-- | drivers/hwmon/it87.c | 84 |
1 files changed, 61 insertions, 23 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 1ed8b7e2c35d..62afc63708a5 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -202,15 +202,23 @@ 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 chip, we need to keep some data in memory. |
207 | data is pointed to by it87_list[NR]->data. The structure itself is | 218 | The structure is dynamically allocated. */ |
208 | dynamically allocated, at the same time when a new it87 client is | ||
209 | allocated. */ | ||
210 | struct it87_data { | 219 | struct it87_data { |
211 | struct i2c_client client; | 220 | struct i2c_client client; |
212 | struct class_device *class_dev; | 221 | struct class_device *class_dev; |
213 | struct mutex lock; | ||
214 | enum chips type; | 222 | enum chips type; |
215 | 223 | ||
216 | struct mutex update_lock; | 224 | struct mutex update_lock; |
@@ -232,6 +240,7 @@ struct it87_data { | |||
232 | u8 vrm; | 240 | u8 vrm; |
233 | u32 alarms; /* Register encoding, combined */ | 241 | u32 alarms; /* Register encoding, combined */ |
234 | u8 fan_main_ctrl; /* Register value */ | 242 | u8 fan_main_ctrl; /* Register value */ |
243 | u8 fan_ctl; /* Register value */ | ||
235 | u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ | 244 | u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ |
236 | }; | 245 | }; |
237 | 246 | ||
@@ -519,6 +528,14 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | |||
519 | struct it87_data *data = it87_update_device(dev); | 528 | struct it87_data *data = it87_update_device(dev); |
520 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); | 529 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); |
521 | } | 530 | } |
531 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, | ||
532 | char *buf) | ||
533 | { | ||
534 | struct it87_data *data = it87_update_device(dev); | ||
535 | int index = (data->fan_ctl >> 4) & 0x07; | ||
536 | |||
537 | return sprintf(buf, "%u\n", pwm_freq[index]); | ||
538 | } | ||
522 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | 539 | static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, |
523 | const char *buf, size_t count) | 540 | const char *buf, size_t count) |
524 | { | 541 | { |
@@ -528,9 +545,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | |||
528 | struct i2c_client *client = to_i2c_client(dev); | 545 | struct i2c_client *client = to_i2c_client(dev); |
529 | struct it87_data *data = i2c_get_clientdata(client); | 546 | struct it87_data *data = i2c_get_clientdata(client); |
530 | int val = simple_strtol(buf, NULL, 10); | 547 | int val = simple_strtol(buf, NULL, 10); |
531 | u8 reg = it87_read_value(client, IT87_REG_FAN_DIV); | 548 | u8 reg; |
532 | 549 | ||
533 | mutex_lock(&data->update_lock); | 550 | mutex_lock(&data->update_lock); |
551 | reg = it87_read_value(client, IT87_REG_FAN_DIV); | ||
534 | switch (nr) { | 552 | switch (nr) { |
535 | case 0: data->fan_div[nr] = reg & 0x07; break; | 553 | case 0: data->fan_div[nr] = reg & 0x07; break; |
536 | case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; | 554 | case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; |
@@ -639,6 +657,28 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
639 | mutex_unlock(&data->update_lock); | 657 | mutex_unlock(&data->update_lock); |
640 | return count; | 658 | return count; |
641 | } | 659 | } |
660 | static ssize_t set_pwm_freq(struct device *dev, | ||
661 | struct device_attribute *attr, const char *buf, size_t count) | ||
662 | { | ||
663 | struct i2c_client *client = to_i2c_client(dev); | ||
664 | struct it87_data *data = i2c_get_clientdata(client); | ||
665 | unsigned long val = simple_strtoul(buf, NULL, 10); | ||
666 | int i; | ||
667 | |||
668 | /* Search for the nearest available frequency */ | ||
669 | for (i = 0; i < 7; i++) { | ||
670 | if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) | ||
671 | break; | ||
672 | } | ||
673 | |||
674 | mutex_lock(&data->update_lock); | ||
675 | data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL) & 0x8f; | ||
676 | data->fan_ctl |= i << 4; | ||
677 | it87_write_value(client, IT87_REG_FAN_CTL, data->fan_ctl); | ||
678 | mutex_unlock(&data->update_lock); | ||
679 | |||
680 | return count; | ||
681 | } | ||
642 | 682 | ||
643 | #define show_fan_offset(offset) \ | 683 | #define show_fan_offset(offset) \ |
644 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ | 684 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ |
@@ -656,7 +696,10 @@ show_fan_offset(3); | |||
656 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ | 696 | static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ |
657 | show_pwm_enable, set_pwm_enable, offset - 1); \ | 697 | show_pwm_enable, set_pwm_enable, offset - 1); \ |
658 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | 698 | static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ |
659 | show_pwm, set_pwm, offset - 1); | 699 | show_pwm, set_pwm, offset - 1); \ |
700 | static DEVICE_ATTR(pwm##offset##_freq, \ | ||
701 | (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ | ||
702 | show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); | ||
660 | 703 | ||
661 | show_pwm_offset(1); | 704 | show_pwm_offset(1); |
662 | show_pwm_offset(2); | 705 | show_pwm_offset(2); |
@@ -904,7 +947,6 @@ static int it87_detect(struct i2c_adapter *adapter) | |||
904 | } | 947 | } |
905 | 948 | ||
906 | new_client = &data->client; | 949 | new_client = &data->client; |
907 | mutex_init(&data->lock); | ||
908 | i2c_set_clientdata(new_client, data); | 950 | i2c_set_clientdata(new_client, data); |
909 | new_client->addr = isa_address; | 951 | new_client->addr = isa_address; |
910 | new_client->adapter = adapter; | 952 | new_client->adapter = adapter; |
@@ -1021,7 +1063,13 @@ static int it87_detect(struct i2c_adapter *adapter) | |||
1021 | || (err = device_create_file(&new_client->dev, | 1063 | || (err = device_create_file(&new_client->dev, |
1022 | &sensor_dev_attr_pwm2.dev_attr)) | 1064 | &sensor_dev_attr_pwm2.dev_attr)) |
1023 | || (err = device_create_file(&new_client->dev, | 1065 | || (err = device_create_file(&new_client->dev, |
1024 | &sensor_dev_attr_pwm3.dev_attr))) | 1066 | &sensor_dev_attr_pwm3.dev_attr)) |
1067 | || (err = device_create_file(&new_client->dev, | ||
1068 | &dev_attr_pwm1_freq)) | ||
1069 | || (err = device_create_file(&new_client->dev, | ||
1070 | &dev_attr_pwm2_freq)) | ||
1071 | || (err = device_create_file(&new_client->dev, | ||
1072 | &dev_attr_pwm3_freq))) | ||
1025 | goto ERROR4; | 1073 | goto ERROR4; |
1026 | } | 1074 | } |
1027 | 1075 | ||
@@ -1076,33 +1124,22 @@ static int it87_detach_client(struct i2c_client *client) | |||
1076 | return 0; | 1124 | return 0; |
1077 | } | 1125 | } |
1078 | 1126 | ||
1079 | /* ISA access must be locked explicitly! | 1127 | /* Must be called with data->update_lock held, except during initialization. |
1080 | We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, | 1128 | We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, |
1081 | would slow down the IT87 access and should not be necessary. */ | 1129 | would slow down the IT87 access and should not be necessary. */ |
1082 | static int it87_read_value(struct i2c_client *client, u8 reg) | 1130 | static int it87_read_value(struct i2c_client *client, u8 reg) |
1083 | { | 1131 | { |
1084 | struct it87_data *data = i2c_get_clientdata(client); | ||
1085 | int res; | ||
1086 | |||
1087 | mutex_lock(&data->lock); | ||
1088 | outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); | 1132 | outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); |
1089 | res = inb_p(client->addr + IT87_DATA_REG_OFFSET); | 1133 | return inb_p(client->addr + IT87_DATA_REG_OFFSET); |
1090 | mutex_unlock(&data->lock); | ||
1091 | |||
1092 | return res; | ||
1093 | } | 1134 | } |
1094 | 1135 | ||
1095 | /* ISA access must be locked explicitly! | 1136 | /* Must be called with data->update_lock held, except during initialization. |
1096 | We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, | 1137 | We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, |
1097 | would slow down the IT87 access and should not be necessary. */ | 1138 | would slow down the IT87 access and should not be necessary. */ |
1098 | static void it87_write_value(struct i2c_client *client, u8 reg, u8 value) | 1139 | static void it87_write_value(struct i2c_client *client, u8 reg, u8 value) |
1099 | { | 1140 | { |
1100 | struct it87_data *data = i2c_get_clientdata(client); | ||
1101 | |||
1102 | mutex_lock(&data->lock); | ||
1103 | outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); | 1141 | outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET); |
1104 | outb_p(value, client->addr + IT87_DATA_REG_OFFSET); | 1142 | outb_p(value, client->addr + IT87_DATA_REG_OFFSET); |
1105 | mutex_unlock(&data->lock); | ||
1106 | } | 1143 | } |
1107 | 1144 | ||
1108 | /* Return 1 if and only if the PWM interface is safe to use */ | 1145 | /* Return 1 if and only if the PWM interface is safe to use */ |
@@ -1316,6 +1353,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1316 | (it87_read_value(client, IT87_REG_ALARM2) << 8) | | 1353 | (it87_read_value(client, IT87_REG_ALARM2) << 8) | |
1317 | (it87_read_value(client, IT87_REG_ALARM3) << 16); | 1354 | (it87_read_value(client, IT87_REG_ALARM3) << 16); |
1318 | data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); | 1355 | data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL); |
1356 | data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL); | ||
1319 | 1357 | ||
1320 | data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); | 1358 | data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE); |
1321 | /* The 8705 does not have VID capability */ | 1359 | /* The 8705 does not have VID capability */ |