diff options
author | Phil Endecott <kernel@chezphil.org> | 2007-06-29 03:19:14 -0400 |
---|---|---|
committer | Mark M. Hoffman <mhoffman@lightlink.com> | 2007-07-19 14:22:15 -0400 |
commit | aba5073d3f4c928c89c483d85f8cff7cc9aa3312 (patch) | |
tree | c966ca4de6e14d4edbb7232b3dcef3fb7e114b7f /drivers | |
parent | 158ce07564b68d4215b9560213a089d6f7c5a4ea (diff) |
hwmon/f71805f: Add temperature-tracking fan control mode
Add support for the "temperature mode" fan speed control. In this mode,
the user can define 3 temperature/speed trip points, and the chip will
set the speed automatically according to the temperature changes.
Signed-off-by: Phil Endecott <kernel@chezphil.org>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Mark M. Hoffman <mhoffman@lightlink.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/f71805f.c | 167 |
1 files changed, 166 insertions, 1 deletions
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 8fe4d70d8f51..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, |