aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Endecott <kernel@chezphil.org>2007-06-29 03:19:14 -0400
committerMark M. Hoffman <mhoffman@lightlink.com>2007-07-19 14:22:15 -0400
commitaba5073d3f4c928c89c483d85f8cff7cc9aa3312 (patch)
treec966ca4de6e14d4edbb7232b3dcef3fb7e114b7f
parent158ce07564b68d4215b9560213a089d6f7c5a4ea (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>
-rw-r--r--Documentation/hwmon/f71805f35
-rw-r--r--drivers/hwmon/f71805f.c167
2 files changed, 188 insertions, 14 deletions
diff --git a/Documentation/hwmon/f71805f b/Documentation/hwmon/f71805f
index bfd0f154959c..94e0d2cbd3d2 100644
--- a/Documentation/hwmon/f71805f
+++ b/Documentation/hwmon/f71805f
@@ -5,11 +5,11 @@ Supported chips:
5 * Fintek F71805F/FG 5 * Fintek F71805F/FG
6 Prefix: 'f71805f' 6 Prefix: 'f71805f'
7 Addresses scanned: none, address read from Super I/O config space 7 Addresses scanned: none, address read from Super I/O config space
8 Datasheet: Provided by Fintek on request 8 Datasheet: Available from the Fintek website
9 * Fintek F71872F/FG 9 * Fintek F71872F/FG
10 Prefix: 'f71872f' 10 Prefix: 'f71872f'
11 Addresses scanned: none, address read from Super I/O config space 11 Addresses scanned: none, address read from Super I/O config space
12 Datasheet: Provided by Fintek on request 12 Datasheet: Available from the Fintek website
13 13
14Author: Jean Delvare <khali@linux-fr.org> 14Author: Jean Delvare <khali@linux-fr.org>
15 15
@@ -128,7 +128,9 @@ it.
128When the PWM method is used, you can select the operating frequency, 128When the PWM method is used, you can select the operating frequency,
129from 187.5 kHz (default) to 31 Hz. The best frequency depends on the 129from 187.5 kHz (default) to 31 Hz. The best frequency depends on the
130fan model. As a rule of thumb, lower frequencies seem to give better 130fan model. As a rule of thumb, lower frequencies seem to give better
131control, but may generate annoying high-pitch noise. Fintek recommends 131control, but may generate annoying high-pitch noise. So a frequency just
132above the audible range, such as 25 kHz, may be a good choice; if this
133doesn't give you good linear control, try reducing it. Fintek recommends
132not going below 1 kHz, as the fan tachometers get confused by lower 134not going below 1 kHz, as the fan tachometers get confused by lower
133frequencies as well. 135frequencies as well.
134 136
@@ -136,16 +138,23 @@ When the DC method is used, Fintek recommends not going below 5 V, which
136corresponds to a pwm value of 106 for the driver. The driver doesn't 138corresponds to a pwm value of 106 for the driver. The driver doesn't
137enforce this limit though. 139enforce this limit though.
138 140
139Three different fan control modes are supported: 141Three different fan control modes are supported; the mode number is written
142to the pwm<n>_enable file.
140 143
141* Manual mode 144* 1: Manual mode
142 You ask for a specific PWM duty cycle or DC voltage. 145 You ask for a specific PWM duty cycle or DC voltage by writing to the
146 pwm<n> file.
143 147
144* Fan speed mode 148* 2: Temperature mode
145 You ask for a specific fan speed. This mode assumes that pwm1 149 You define 3 temperature/fan speed trip points using the
146 corresponds to fan1, pwm2 to fan2 and pwm3 to fan3. 150 pwm<n>_auto_point<m>_temp and _fan files. These define a staircase
151 relationship between temperature and fan speed with two additional points
152 interpolated between the values that you define. When the temperature
153 is below auto_point1_temp the fan is switched off.
147 154
148* Temperature mode 155* 3: Fan speed mode
149 You define 3 temperature/fan speed trip points, and the fan speed is 156 You ask for a specific fan speed by writing to the fan<n>_target file.
150 adjusted depending on the measured temperature, using interpolation. 157
151 This mode is not yet supported by the driver. 158Both of the automatic modes require that pwm1 corresponds to fan1, pwm2 to
159fan2 and pwm3 to fan3. Temperature mode also requires that temp1 corresponds
160to pwm1 and fan1, etc.
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
154struct f71805f_auto_point {
155 u8 temp[3];
156 u16 fan[3];
157};
158
147struct f71805f_data { 159struct 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
175struct f71805f_sio_data { 188struct f71805f_sio_data {
@@ -312,7 +325,7 @@ static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val)
312static struct f71805f_data *f71805f_update_device(struct device *dev) 325static 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
733static 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
746static 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
765static 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
778static 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
708static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, 797static 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);
933static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2); 1022static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2);
934 1023
1024static 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);
1027static 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);
1030static 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);
1033static 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);
1036static 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);
1039static 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
1043static 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);
1046static 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);
1049static 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);
1052static 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);
1055static 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);
1058static 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
1062static 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);
1065static 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);
1068static 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);
1071static 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);
1074static 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);
1077static 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
935static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); 1081static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
936static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); 1082static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
937static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); 1083static 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,