diff options
-rw-r--r-- | Documentation/hwmon/w83791d | 13 | ||||
-rw-r--r-- | drivers/hwmon/w83791d.c | 79 |
2 files changed, 91 insertions, 1 deletions
diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d index 49c0e94a118c..b1e4798764e8 100644 --- a/Documentation/hwmon/w83791d +++ b/Documentation/hwmon/w83791d | |||
@@ -108,6 +108,17 @@ going forward. | |||
108 | The driver reads the hardware chip values at most once every three seconds. | 108 | The driver reads the hardware chip values at most once every three seconds. |
109 | User mode code requesting values more often will receive cached values. | 109 | User mode code requesting values more often will receive cached values. |
110 | 110 | ||
111 | /sys files | ||
112 | ---------- | ||
113 | The sysfs-interface is documented in the 'sysfs-interface' file. Only | ||
114 | chip-specific options are documented here. | ||
115 | |||
116 | pwm[1-3]_enable - this file controls mode of fan/temperature control for | ||
117 | fan 1-3. Fan/PWM 4-5 only support manual mode. | ||
118 | * 1 Manual mode | ||
119 | * 2 Thermal Cruise mode (no further support) | ||
120 | * 3 Fan Speed Cruise mode (no further support) | ||
121 | |||
111 | Alarms bitmap vs. beep_mask bitmask | 122 | Alarms bitmap vs. beep_mask bitmask |
112 | ------------------------------------ | 123 | ------------------------------------ |
113 | For legacy code using the alarms and beep_mask files: | 124 | For legacy code using the alarms and beep_mask files: |
@@ -138,4 +149,4 @@ global_enable: alarms: -------- beep_mask: 0x800000 (modified via beep_enable) | |||
138 | 149 | ||
139 | W83791D TODO: | 150 | W83791D TODO: |
140 | --------------- | 151 | --------------- |
141 | Provide a patch for smart-fan control (still need appropriate motherboard/fans) | 152 | Provide a patch for Thermal Cruise registers. |
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index a8ff4e126713..a4d2b02d9e04 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c | |||
@@ -287,6 +287,8 @@ struct w83791d_data { | |||
287 | 287 | ||
288 | /* PWMs */ | 288 | /* PWMs */ |
289 | u8 pwm[5]; /* pwm duty cycle */ | 289 | u8 pwm[5]; /* pwm duty cycle */ |
290 | u8 pwm_enable[3]; /* pwm enable status for fan 1-3 | ||
291 | (fan 4-5 only support manual mode) */ | ||
290 | 292 | ||
291 | /* Misc */ | 293 | /* Misc */ |
292 | u32 alarms; /* realtime status register encoding,combined */ | 294 | u32 alarms; /* realtime status register encoding,combined */ |
@@ -707,6 +709,71 @@ static struct sensor_device_attribute sda_pwm[] = { | |||
707 | show_pwm, store_pwm, 4), | 709 | show_pwm, store_pwm, 4), |
708 | }; | 710 | }; |
709 | 711 | ||
712 | static ssize_t show_pwmenable(struct device *dev, struct device_attribute *attr, | ||
713 | char *buf) | ||
714 | { | ||
715 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
716 | int nr = sensor_attr->index; | ||
717 | struct w83791d_data *data = w83791d_update_device(dev); | ||
718 | return sprintf(buf, "%u\n", data->pwm_enable[nr] + 1); | ||
719 | } | ||
720 | |||
721 | static ssize_t store_pwmenable(struct device *dev, | ||
722 | struct device_attribute *attr, const char *buf, size_t count) | ||
723 | { | ||
724 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
725 | struct i2c_client *client = to_i2c_client(dev); | ||
726 | struct w83791d_data *data = i2c_get_clientdata(client); | ||
727 | int nr = sensor_attr->index; | ||
728 | unsigned long val; | ||
729 | u8 reg_cfg_tmp; | ||
730 | u8 reg_idx = 0; | ||
731 | u8 val_shift = 0; | ||
732 | u8 keep_mask = 0; | ||
733 | |||
734 | int ret = strict_strtoul(buf, 10, &val); | ||
735 | |||
736 | if (ret || val < 1 || val > 3) | ||
737 | return -EINVAL; | ||
738 | |||
739 | mutex_lock(&data->update_lock); | ||
740 | data->pwm_enable[nr] = val - 1; | ||
741 | switch (nr) { | ||
742 | case 0: | ||
743 | reg_idx = 0; | ||
744 | val_shift = 2; | ||
745 | keep_mask = 0xf3; | ||
746 | break; | ||
747 | case 1: | ||
748 | reg_idx = 0; | ||
749 | val_shift = 4; | ||
750 | keep_mask = 0xcf; | ||
751 | break; | ||
752 | case 2: | ||
753 | reg_idx = 1; | ||
754 | val_shift = 2; | ||
755 | keep_mask = 0xf3; | ||
756 | break; | ||
757 | } | ||
758 | |||
759 | reg_cfg_tmp = w83791d_read(client, W83791D_REG_FAN_CFG[reg_idx]); | ||
760 | reg_cfg_tmp = (reg_cfg_tmp & keep_mask) | | ||
761 | data->pwm_enable[nr] << val_shift; | ||
762 | |||
763 | w83791d_write(client, W83791D_REG_FAN_CFG[reg_idx], reg_cfg_tmp); | ||
764 | mutex_unlock(&data->update_lock); | ||
765 | |||
766 | return count; | ||
767 | } | ||
768 | static struct sensor_device_attribute sda_pwmenable[] = { | ||
769 | SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, | ||
770 | show_pwmenable, store_pwmenable, 0), | ||
771 | SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, | ||
772 | show_pwmenable, store_pwmenable, 1), | ||
773 | SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, | ||
774 | show_pwmenable, store_pwmenable, 2), | ||
775 | }; | ||
776 | |||
710 | /* read/write the temperature1, includes measured value and limits */ | 777 | /* read/write the temperature1, includes measured value and limits */ |
711 | static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr, | 778 | static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr, |
712 | char *buf) | 779 | char *buf) |
@@ -974,6 +1041,9 @@ static struct attribute *w83791d_attributes[] = { | |||
974 | &sda_pwm[0].dev_attr.attr, | 1041 | &sda_pwm[0].dev_attr.attr, |
975 | &sda_pwm[1].dev_attr.attr, | 1042 | &sda_pwm[1].dev_attr.attr, |
976 | &sda_pwm[2].dev_attr.attr, | 1043 | &sda_pwm[2].dev_attr.attr, |
1044 | &sda_pwmenable[0].dev_attr.attr, | ||
1045 | &sda_pwmenable[1].dev_attr.attr, | ||
1046 | &sda_pwmenable[2].dev_attr.attr, | ||
977 | NULL | 1047 | NULL |
978 | }; | 1048 | }; |
979 | 1049 | ||
@@ -1325,6 +1395,15 @@ static struct w83791d_data *w83791d_update_device(struct device *dev) | |||
1325 | W83791D_REG_PWM[i]); | 1395 | W83791D_REG_PWM[i]); |
1326 | } | 1396 | } |
1327 | 1397 | ||
1398 | /* Update PWM enable status */ | ||
1399 | for (i = 0; i < 2; i++) { | ||
1400 | reg_array_tmp[i] = w83791d_read(client, | ||
1401 | W83791D_REG_FAN_CFG[i]); | ||
1402 | } | ||
1403 | data->pwm_enable[0] = (reg_array_tmp[0] >> 2) & 0x03; | ||
1404 | data->pwm_enable[1] = (reg_array_tmp[0] >> 4) & 0x03; | ||
1405 | data->pwm_enable[2] = (reg_array_tmp[1] >> 2) & 0x03; | ||
1406 | |||
1328 | /* Update the first temperature sensor */ | 1407 | /* Update the first temperature sensor */ |
1329 | for (i = 0; i < 3; i++) { | 1408 | for (i = 0; i < 3; i++) { |
1330 | data->temp1[i] = w83791d_read(client, | 1409 | data->temp1[i] = w83791d_read(client, |