diff options
Diffstat (limited to 'drivers/hwmon/f71805f.c')
| -rw-r--r-- | drivers/hwmon/f71805f.c | 178 |
1 files changed, 170 insertions, 8 deletions
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index cdbe309b8fc4..6f60715f34f8 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c | |||
| @@ -127,6 +127,13 @@ superio_exit(int base) | |||
| 127 | #define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr)) | 127 | #define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr)) |
| 128 | #define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr)) | 128 | #define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr)) |
| 129 | #define F71805F_REG_TEMP_MODE 0x01 | 129 | #define F71805F_REG_TEMP_MODE 0x01 |
| 130 | /* pwm/fan pwmnr from 0 to 2, auto point apnr from 0 to 2 */ | ||
| 131 | /* map Fintek numbers to our numbers as follows: 9->0, 5->1, 1->2 */ | ||
| 132 | #define F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr) \ | ||
| 133 | (0xA0 + 0x10 * (pwmnr) + (2 - (apnr))) | ||
| 134 | #define F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr) \ | ||
| 135 | (0xA4 + 0x10 * (pwmnr) + \ | ||
| 136 | 2 * (2 - (apnr))) | ||
| 130 | 137 | ||
| 131 | #define F71805F_REG_START 0x00 | 138 | #define F71805F_REG_START 0x00 |
| 132 | /* status nr from 0 to 2 */ | 139 | /* status nr from 0 to 2 */ |
| @@ -144,6 +151,11 @@ superio_exit(int base) | |||
| 144 | * Data structures and manipulation thereof | 151 | * Data structures and manipulation thereof |
| 145 | */ | 152 | */ |
| 146 | 153 | ||
| 154 | struct f71805f_auto_point { | ||
| 155 | u8 temp[3]; | ||
| 156 | u16 fan[3]; | ||
| 157 | }; | ||
| 158 | |||
| 147 | struct f71805f_data { | 159 | struct f71805f_data { |
| 148 | unsigned short addr; | 160 | unsigned short addr; |
| 149 | const char *name; | 161 | const char *name; |
| @@ -170,6 +182,7 @@ struct f71805f_data { | |||
| 170 | u8 temp_hyst[3]; | 182 | u8 temp_hyst[3]; |
| 171 | u8 temp_mode; | 183 | u8 temp_mode; |
| 172 | unsigned long alarms; | 184 | unsigned long alarms; |
| 185 | struct f71805f_auto_point auto_points[3]; | ||
| 173 | }; | 186 | }; |
| 174 | 187 | ||
| 175 | struct f71805f_sio_data { | 188 | struct f71805f_sio_data { |
| @@ -312,7 +325,7 @@ static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) | |||
| 312 | static struct f71805f_data *f71805f_update_device(struct device *dev) | 325 | static struct f71805f_data *f71805f_update_device(struct device *dev) |
| 313 | { | 326 | { |
| 314 | struct f71805f_data *data = dev_get_drvdata(dev); | 327 | struct f71805f_data *data = dev_get_drvdata(dev); |
| 315 | int nr; | 328 | int nr, apnr; |
| 316 | 329 | ||
| 317 | mutex_lock(&data->update_lock); | 330 | mutex_lock(&data->update_lock); |
| 318 | 331 | ||
| @@ -342,6 +355,18 @@ static struct f71805f_data *f71805f_update_device(struct device *dev) | |||
| 342 | F71805F_REG_TEMP_HYST(nr)); | 355 | F71805F_REG_TEMP_HYST(nr)); |
| 343 | } | 356 | } |
| 344 | data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE); | 357 | data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE); |
| 358 | for (nr = 0; nr < 3; nr++) { | ||
| 359 | for (apnr = 0; apnr < 3; apnr++) { | ||
| 360 | data->auto_points[nr].temp[apnr] = | ||
| 361 | f71805f_read8(data, | ||
| 362 | F71805F_REG_PWM_AUTO_POINT_TEMP(nr, | ||
| 363 | apnr)); | ||
| 364 | data->auto_points[nr].fan[apnr] = | ||
| 365 | f71805f_read16(data, | ||
| 366 | F71805F_REG_PWM_AUTO_POINT_FAN(nr, | ||
| 367 | apnr)); | ||
| 368 | } | ||
| 369 | } | ||
| 345 | 370 | ||
| 346 | data->last_limits = jiffies; | 371 | data->last_limits = jiffies; |
| 347 | } | 372 | } |
| @@ -705,6 +730,70 @@ static ssize_t set_pwm_freq(struct device *dev, struct device_attribute | |||
| 705 | return count; | 730 | return count; |
| 706 | } | 731 | } |
| 707 | 732 | ||
| 733 | static ssize_t show_pwm_auto_point_temp(struct device *dev, | ||
| 734 | struct device_attribute *devattr, | ||
| 735 | char* buf) | ||
| 736 | { | ||
| 737 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
| 738 | struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); | ||
| 739 | int pwmnr = attr->nr; | ||
| 740 | int apnr = attr->index; | ||
| 741 | |||
| 742 | return sprintf(buf, "%ld\n", | ||
| 743 | temp_from_reg(data->auto_points[pwmnr].temp[apnr])); | ||
| 744 | } | ||
| 745 | |||
| 746 | static ssize_t set_pwm_auto_point_temp(struct device *dev, | ||
| 747 | struct device_attribute *devattr, | ||
| 748 | const char* buf, size_t count) | ||
| 749 | { | ||
| 750 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
| 751 | struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); | ||
| 752 | int pwmnr = attr->nr; | ||
| 753 | int apnr = attr->index; | ||
| 754 | unsigned long val = simple_strtol(buf, NULL, 10); | ||
| 755 | |||
| 756 | mutex_lock(&data->update_lock); | ||
| 757 | data->auto_points[pwmnr].temp[apnr] = temp_to_reg(val); | ||
| 758 | f71805f_write8(data, F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr), | ||
| 759 | data->auto_points[pwmnr].temp[apnr]); | ||
| 760 | mutex_unlock(&data->update_lock); | ||
| 761 | |||
| 762 | return count; | ||
| 763 | } | ||
| 764 | |||
| 765 | static ssize_t show_pwm_auto_point_fan(struct device *dev, | ||
| 766 | struct device_attribute *devattr, | ||
| 767 | char* buf) | ||
| 768 | { | ||
| 769 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
| 770 | struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); | ||
| 771 | int pwmnr = attr->nr; | ||
| 772 | int apnr = attr->index; | ||
| 773 | |||
| 774 | return sprintf(buf, "%ld\n", | ||
| 775 | fan_from_reg(data->auto_points[pwmnr].fan[apnr])); | ||
| 776 | } | ||
| 777 | |||
| 778 | static ssize_t set_pwm_auto_point_fan(struct device *dev, | ||
| 779 | struct device_attribute *devattr, | ||
| 780 | const char* buf, size_t count) | ||
| 781 | { | ||
| 782 | struct f71805f_data *data = dev_get_drvdata(dev); | ||
| 783 | struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); | ||
| 784 | int pwmnr = attr->nr; | ||
| 785 | int apnr = attr->index; | ||
| 786 | unsigned long val = simple_strtoul(buf, NULL, 10); | ||
| 787 | |||
| 788 | mutex_lock(&data->update_lock); | ||
| 789 | data->auto_points[pwmnr].fan[apnr] = fan_to_reg(val); | ||
| 790 | f71805f_write16(data, F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr), | ||
| 791 | data->auto_points[pwmnr].fan[apnr]); | ||
| 792 | mutex_unlock(&data->update_lock); | ||
| 793 | |||
| 794 | return count; | ||
| 795 | } | ||
| 796 | |||
| 708 | static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, | 797 | static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, |
| 709 | char *buf) | 798 | char *buf) |
| 710 | { | 799 | { |
| @@ -932,6 +1021,63 @@ static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO | S_IWUSR, | |||
| 932 | show_pwm_freq, set_pwm_freq, 2); | 1021 | show_pwm_freq, set_pwm_freq, 2); |
| 933 | static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2); | 1022 | static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2); |
| 934 | 1023 | ||
| 1024 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR, | ||
| 1025 | show_pwm_auto_point_temp, set_pwm_auto_point_temp, | ||
| 1026 | 0, 0); | ||
| 1027 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_fan, S_IRUGO | S_IWUSR, | ||
| 1028 | show_pwm_auto_point_fan, set_pwm_auto_point_fan, | ||
| 1029 | 0, 0); | ||
| 1030 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR, | ||
| 1031 | show_pwm_auto_point_temp, set_pwm_auto_point_temp, | ||
| 1032 | 0, 1); | ||
| 1033 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_fan, S_IRUGO | S_IWUSR, | ||
| 1034 | show_pwm_auto_point_fan, set_pwm_auto_point_fan, | ||
| 1035 | 0, 1); | ||
| 1036 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR, | ||
| 1037 | show_pwm_auto_point_temp, set_pwm_auto_point_temp, | ||
| 1038 | 0, 2); | ||
| 1039 | static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_fan, S_IRUGO | S_IWUSR, | ||
| 1040 | show_pwm_auto_point_fan, set_pwm_auto_point_fan, | ||
| 1041 | 0, 2); | ||
| 1042 | |||
| 1043 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp, S_IRUGO | S_IWUSR, | ||
| 1044 | show_pwm_auto_point_temp, set_pwm_auto_point_temp, | ||
| 1045 | 1, 0); | ||
| 1046 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_fan, S_IRUGO | S_IWUSR, | ||
| 1047 | show_pwm_auto_point_fan, set_pwm_auto_point_fan, | ||
| 1048 | 1, 0); | ||
| 1049 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_temp, S_IRUGO | S_IWUSR, | ||
| 1050 | show_pwm_auto_point_temp, set_pwm_auto_point_temp, | ||
| 1051 | 1, 1); | ||
| 1052 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_fan, S_IRUGO | S_IWUSR, | ||
| 1053 | show_pwm_auto_point_fan, set_pwm_auto_point_fan, | ||
| 1054 | 1, 1); | ||
| 1055 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR, | ||
| 1056 | show_pwm_auto_point_temp, set_pwm_auto_point_temp, | ||
| 1057 | 1, 2); | ||
| 1058 | static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_fan, S_IRUGO | S_IWUSR, | ||
| 1059 | show_pwm_auto_point_fan, set_pwm_auto_point_fan, | ||
| 1060 | 1, 2); | ||
| 1061 | |||
| 1062 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp, S_IRUGO | S_IWUSR, | ||
| 1063 | show_pwm_auto_point_temp, set_pwm_auto_point_temp, | ||
| 1064 | 2, 0); | ||
| 1065 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_fan, S_IRUGO | S_IWUSR, | ||
| 1066 | show_pwm_auto_point_fan, set_pwm_auto_point_fan, | ||
| 1067 | 2, 0); | ||
| 1068 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_temp, S_IRUGO | S_IWUSR, | ||
| 1069 | show_pwm_auto_point_temp, set_pwm_auto_point_temp, | ||
| 1070 | 2, 1); | ||
| 1071 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_fan, S_IRUGO | S_IWUSR, | ||
| 1072 | show_pwm_auto_point_fan, set_pwm_auto_point_fan, | ||
| 1073 | 2, 1); | ||
| 1074 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR, | ||
| 1075 | show_pwm_auto_point_temp, set_pwm_auto_point_temp, | ||
| 1076 | 2, 2); | ||
| 1077 | static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_fan, S_IRUGO | S_IWUSR, | ||
| 1078 | show_pwm_auto_point_fan, set_pwm_auto_point_fan, | ||
| 1079 | 2, 2); | ||
| 1080 | |||
| 935 | static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); | 1081 | static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); |
| 936 | static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); | 1082 | static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); |
| 937 | static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); | 1083 | static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); |
| @@ -1014,6 +1160,25 @@ static struct attribute *f71805f_attributes[] = { | |||
| 1014 | &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, | 1160 | &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, |
| 1015 | &sensor_dev_attr_temp3_type.dev_attr.attr, | 1161 | &sensor_dev_attr_temp3_type.dev_attr.attr, |
| 1016 | 1162 | ||
| 1163 | &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, | ||
| 1164 | &sensor_dev_attr_pwm1_auto_point1_fan.dev_attr.attr, | ||
| 1165 | &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, | ||
| 1166 | &sensor_dev_attr_pwm1_auto_point2_fan.dev_attr.attr, | ||
| 1167 | &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, | ||
| 1168 | &sensor_dev_attr_pwm1_auto_point3_fan.dev_attr.attr, | ||
| 1169 | &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr, | ||
| 1170 | &sensor_dev_attr_pwm2_auto_point1_fan.dev_attr.attr, | ||
| 1171 | &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, | ||
| 1172 | &sensor_dev_attr_pwm2_auto_point2_fan.dev_attr.attr, | ||
| 1173 | &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr, | ||
| 1174 | &sensor_dev_attr_pwm2_auto_point3_fan.dev_attr.attr, | ||
| 1175 | &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr, | ||
| 1176 | &sensor_dev_attr_pwm3_auto_point1_fan.dev_attr.attr, | ||
| 1177 | &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, | ||
| 1178 | &sensor_dev_attr_pwm3_auto_point2_fan.dev_attr.attr, | ||
| 1179 | &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr, | ||
| 1180 | &sensor_dev_attr_pwm3_auto_point3_fan.dev_attr.attr, | ||
| 1181 | |||
| 1017 | &sensor_dev_attr_in0_alarm.dev_attr.attr, | 1182 | &sensor_dev_attr_in0_alarm.dev_attr.attr, |
| 1018 | &sensor_dev_attr_in1_alarm.dev_attr.attr, | 1183 | &sensor_dev_attr_in1_alarm.dev_attr.attr, |
| 1019 | &sensor_dev_attr_in2_alarm.dev_attr.attr, | 1184 | &sensor_dev_attr_in2_alarm.dev_attr.attr, |
| @@ -1242,12 +1407,12 @@ static int __devexit f71805f_remove(struct platform_device *pdev) | |||
| 1242 | struct resource *res; | 1407 | struct resource *res; |
| 1243 | int i; | 1408 | int i; |
| 1244 | 1409 | ||
| 1245 | platform_set_drvdata(pdev, NULL); | ||
| 1246 | hwmon_device_unregister(data->class_dev); | 1410 | hwmon_device_unregister(data->class_dev); |
| 1247 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group); | 1411 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group); |
| 1248 | for (i = 0; i < 4; i++) | 1412 | for (i = 0; i < 4; i++) |
| 1249 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); | 1413 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); |
| 1250 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); | 1414 | sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); |
| 1415 | platform_set_drvdata(pdev, NULL); | ||
| 1251 | kfree(data); | 1416 | kfree(data); |
| 1252 | 1417 | ||
| 1253 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1418 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
| @@ -1290,15 +1455,12 @@ static int __init f71805f_device_add(unsigned short address, | |||
| 1290 | goto exit_device_put; | 1455 | goto exit_device_put; |
| 1291 | } | 1456 | } |
| 1292 | 1457 | ||
| 1293 | pdev->dev.platform_data = kmalloc(sizeof(struct f71805f_sio_data), | 1458 | err = platform_device_add_data(pdev, sio_data, |
| 1294 | GFP_KERNEL); | 1459 | sizeof(struct f71805f_sio_data)); |
| 1295 | if (!pdev->dev.platform_data) { | 1460 | if (err) { |
| 1296 | err = -ENOMEM; | ||
| 1297 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); | 1461 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); |
| 1298 | goto exit_device_put; | 1462 | goto exit_device_put; |
| 1299 | } | 1463 | } |
| 1300 | memcpy(pdev->dev.platform_data, sio_data, | ||
| 1301 | sizeof(struct f71805f_sio_data)); | ||
| 1302 | 1464 | ||
| 1303 | err = platform_device_add(pdev); | 1465 | err = platform_device_add(pdev); |
| 1304 | if (err) { | 1466 | if (err) { |
