aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/it87.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/it87.c')
-rw-r--r--drivers/hwmon/it87.c182
1 files changed, 180 insertions, 2 deletions
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 8282282eb4ca..bbb0c7443b9b 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -192,6 +192,9 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
192 192
193#define IT87_REG_CHIPID 0x58 193#define IT87_REG_CHIPID 0x58
194 194
195#define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i))
196#define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i))
197
195#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255)) 198#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255))
196#define IN_FROM_REG(val) ((val) * 16) 199#define IN_FROM_REG(val) ((val) * 16)
197 200
@@ -293,6 +296,10 @@ struct it87_data {
293 u8 pwm_ctrl[3]; /* Register value */ 296 u8 pwm_ctrl[3]; /* Register value */
294 u8 pwm_duty[3]; /* Manual PWM value set by user (bit 6-0) */ 297 u8 pwm_duty[3]; /* Manual PWM value set by user (bit 6-0) */
295 u8 pwm_temp_map[3]; /* PWM to temp. chan. mapping (bits 1-0) */ 298 u8 pwm_temp_map[3]; /* PWM to temp. chan. mapping (bits 1-0) */
299
300 /* Automatic fan speed control registers */
301 u8 auto_pwm[3][4]; /* [nr][3] is hard-coded */
302 s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */
296}; 303};
297 304
298static inline int has_16bit_fans(const struct it87_data *data) 305static inline int has_16bit_fans(const struct it87_data *data)
@@ -307,6 +314,15 @@ static inline int has_16bit_fans(const struct it87_data *data)
307 || data->type == it8720; 314 || data->type == it8720;
308} 315}
309 316
317static inline int has_old_autopwm(const struct it87_data *data)
318{
319 /* The old automatic fan speed control interface is implemented
320 by IT8705F chips up to revision F and IT8712F chips up to
321 revision G. */
322 return (data->type == it87 && data->revision < 0x03)
323 || (data->type == it8712 && data->revision < 0x08);
324}
325
310static int it87_probe(struct platform_device *pdev); 326static int it87_probe(struct platform_device *pdev);
311static int __devexit it87_remove(struct platform_device *pdev); 327static int __devexit it87_remove(struct platform_device *pdev);
312 328
@@ -813,6 +829,13 @@ static ssize_t set_pwm_temp_map(struct device *dev,
813 long val; 829 long val;
814 u8 reg; 830 u8 reg;
815 831
832 /* This check can go away if we ever support automatic fan speed
833 control on newer chips. */
834 if (!has_old_autopwm(data)) {
835 dev_notice(dev, "Mapping change disabled for safety reasons\n");
836 return -EINVAL;
837 }
838
816 if (strict_strtol(buf, 10, &val) < 0) 839 if (strict_strtol(buf, 10, &val) < 0)
817 return -EINVAL; 840 return -EINVAL;
818 841
@@ -842,6 +865,72 @@ static ssize_t set_pwm_temp_map(struct device *dev,
842 return count; 865 return count;
843} 866}
844 867
868static ssize_t show_auto_pwm(struct device *dev,
869 struct device_attribute *attr, char *buf)
870{
871 struct it87_data *data = it87_update_device(dev);
872 struct sensor_device_attribute_2 *sensor_attr =
873 to_sensor_dev_attr_2(attr);
874 int nr = sensor_attr->nr;
875 int point = sensor_attr->index;
876
877 return sprintf(buf, "%d\n", PWM_FROM_REG(data->auto_pwm[nr][point]));
878}
879
880static ssize_t set_auto_pwm(struct device *dev,
881 struct device_attribute *attr, const char *buf, size_t count)
882{
883 struct it87_data *data = dev_get_drvdata(dev);
884 struct sensor_device_attribute_2 *sensor_attr =
885 to_sensor_dev_attr_2(attr);
886 int nr = sensor_attr->nr;
887 int point = sensor_attr->index;
888 long val;
889
890 if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 255)
891 return -EINVAL;
892
893 mutex_lock(&data->update_lock);
894 data->auto_pwm[nr][point] = PWM_TO_REG(val);
895 it87_write_value(data, IT87_REG_AUTO_PWM(nr, point),
896 data->auto_pwm[nr][point]);
897 mutex_unlock(&data->update_lock);
898 return count;
899}
900
901static ssize_t show_auto_temp(struct device *dev,
902 struct device_attribute *attr, char *buf)
903{
904 struct it87_data *data = it87_update_device(dev);
905 struct sensor_device_attribute_2 *sensor_attr =
906 to_sensor_dev_attr_2(attr);
907 int nr = sensor_attr->nr;
908 int point = sensor_attr->index;
909
910 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->auto_temp[nr][point]));
911}
912
913static ssize_t set_auto_temp(struct device *dev,
914 struct device_attribute *attr, const char *buf, size_t count)
915{
916 struct it87_data *data = dev_get_drvdata(dev);
917 struct sensor_device_attribute_2 *sensor_attr =
918 to_sensor_dev_attr_2(attr);
919 int nr = sensor_attr->nr;
920 int point = sensor_attr->index;
921 long val;
922
923 if (strict_strtol(buf, 10, &val) < 0 || val < -128000 || val > 127000)
924 return -EINVAL;
925
926 mutex_lock(&data->update_lock);
927 data->auto_temp[nr][point] = TEMP_TO_REG(val);
928 it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point),
929 data->auto_temp[nr][point]);
930 mutex_unlock(&data->update_lock);
931 return count;
932}
933
845#define show_fan_offset(offset) \ 934#define show_fan_offset(offset) \
846static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ 935static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
847 show_fan, NULL, offset - 1); \ 936 show_fan, NULL, offset - 1); \
@@ -863,8 +952,34 @@ static DEVICE_ATTR(pwm##offset##_freq, \
863 (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ 952 (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \
864 show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); \ 953 show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); \
865static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels_temp, \ 954static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels_temp, \
866 S_IRUGO, show_pwm_temp_map, set_pwm_temp_map, \ 955 S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, \
867 offset - 1); 956 offset - 1); \
957static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_pwm, \
958 S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \
959 offset - 1, 0); \
960static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_pwm, \
961 S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \
962 offset - 1, 1); \
963static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_pwm, \
964 S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \
965 offset - 1, 2); \
966static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_pwm, \
967 S_IRUGO, show_auto_pwm, NULL, offset - 1, 3); \
968static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp, \
969 S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \
970 offset - 1, 1); \
971static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp_hyst, \
972 S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \
973 offset - 1, 0); \
974static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_temp, \
975 S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \
976 offset - 1, 2); \
977static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_temp, \
978 S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \
979 offset - 1, 3); \
980static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_temp, \
981 S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \
982 offset - 1, 4);
868 983
869show_pwm_offset(1); 984show_pwm_offset(1);
870show_pwm_offset(2); 985show_pwm_offset(2);
@@ -1219,6 +1334,47 @@ static const struct attribute_group it87_group_pwm[3] = {
1219 { .attrs = it87_attributes_pwm[2] }, 1334 { .attrs = it87_attributes_pwm[2] },
1220}; 1335};
1221 1336
1337static struct attribute *it87_attributes_autopwm[3][9+1] = { {
1338 &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
1339 &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
1340 &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
1341 &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
1342 &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
1343 &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr,
1344 &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
1345 &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
1346 &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
1347 NULL
1348}, {
1349 &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
1350 &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
1351 &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr,
1352 &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr,
1353 &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
1354 &sensor_dev_attr_pwm2_auto_point1_temp_hyst.dev_attr.attr,
1355 &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
1356 &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
1357 &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr,
1358 NULL
1359}, {
1360 &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
1361 &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
1362 &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr,
1363 &sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr,
1364 &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr,
1365 &sensor_dev_attr_pwm3_auto_point1_temp_hyst.dev_attr.attr,
1366 &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,
1367 &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr,
1368 &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr,
1369 NULL
1370} };
1371
1372static const struct attribute_group it87_group_autopwm[3] = {
1373 { .attrs = it87_attributes_autopwm[0] },
1374 { .attrs = it87_attributes_autopwm[1] },
1375 { .attrs = it87_attributes_autopwm[2] },
1376};
1377
1222static struct attribute *it87_attributes_fan_beep[] = { 1378static struct attribute *it87_attributes_fan_beep[] = {
1223 &sensor_dev_attr_fan1_beep.dev_attr.attr, 1379 &sensor_dev_attr_fan1_beep.dev_attr.attr,
1224 &sensor_dev_attr_fan2_beep.dev_attr.attr, 1380 &sensor_dev_attr_fan2_beep.dev_attr.attr,
@@ -1382,6 +1538,9 @@ static void it87_remove_files(struct device *dev)
1382 if (sio_data->skip_pwm & (1 << 0)) 1538 if (sio_data->skip_pwm & (1 << 0))
1383 continue; 1539 continue;
1384 sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]); 1540 sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]);
1541 if (has_old_autopwm(data))
1542 sysfs_remove_group(&dev->kobj,
1543 &it87_group_autopwm[i]);
1385 } 1544 }
1386 if (!sio_data->skip_vid) 1545 if (!sio_data->skip_vid)
1387 sysfs_remove_group(&dev->kobj, &it87_group_vid); 1546 sysfs_remove_group(&dev->kobj, &it87_group_vid);
@@ -1491,6 +1650,13 @@ static int __devinit it87_probe(struct platform_device *pdev)
1491 &it87_group_pwm[i]); 1650 &it87_group_pwm[i]);
1492 if (err) 1651 if (err)
1493 goto ERROR4; 1652 goto ERROR4;
1653
1654 if (!has_old_autopwm(data))
1655 continue;
1656 err = sysfs_create_group(&dev->kobj,
1657 &it87_group_autopwm[i]);
1658 if (err)
1659 goto ERROR4;
1494 } 1660 }
1495 } 1661 }
1496 1662
@@ -1624,6 +1790,7 @@ static void __devinit it87_init_device(struct platform_device *pdev)
1624 for (i = 0; i < 3; i++) { 1790 for (i = 0; i < 3; i++) {
1625 data->pwm_temp_map[i] = i; 1791 data->pwm_temp_map[i] = i;
1626 data->pwm_duty[i] = 0x7f; /* Full speed */ 1792 data->pwm_duty[i] = 0x7f; /* Full speed */
1793 data->auto_pwm[i][3] = 0x7f; /* Full speed, hard-coded */
1627 } 1794 }
1628 1795
1629 /* Some chips seem to have default value 0xff for all limit 1796 /* Some chips seem to have default value 0xff for all limit
@@ -1703,6 +1870,17 @@ static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
1703 data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; 1870 data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
1704 else /* Manual mode */ 1871 else /* Manual mode */
1705 data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f; 1872 data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
1873
1874 if (has_old_autopwm(data)) {
1875 int i;
1876
1877 for (i = 0; i < 5 ; i++)
1878 data->auto_temp[nr][i] = it87_read_value(data,
1879 IT87_REG_AUTO_TEMP(nr, i));
1880 for (i = 0; i < 3 ; i++)
1881 data->auto_pwm[nr][i] = it87_read_value(data,
1882 IT87_REG_AUTO_PWM(nr, i));
1883 }
1706} 1884}
1707 1885
1708static struct it87_data *it87_update_device(struct device *dev) 1886static struct it87_data *it87_update_device(struct device *dev)