diff options
author | Dominik Geyer <dominik.geyer@gmx.de> | 2008-08-06 16:41:04 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-08-06 16:41:04 -0400 |
commit | a95a5ed856e902e513119d4cc5b745faa202f761 (patch) | |
tree | d4b34c3c8ed304a058158444d6d70d2ca4104e23 /drivers/hwmon/w83627hf.c | |
parent | ad02ad85cf221c9a0574b48516762e37cceca0da (diff) |
hwmon: (w83627hf) Add pwm_enable sysfs interface
Adds support for pwm_enable sysfs interface for the w83627hf driver.
Signed-off-by: Dominik Geyer <dominik.geyer@gmx.de>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/w83627hf.c')
-rw-r--r-- | drivers/hwmon/w83627hf.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 9564fb069957..ba8b069b1082 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c | |||
@@ -209,6 +209,13 @@ static const u16 w83627hf_reg_temp_over[] = { 0x39, 0x155, 0x255 }; | |||
209 | #define W83627HF_REG_PWM1 0x5A | 209 | #define W83627HF_REG_PWM1 0x5A |
210 | #define W83627HF_REG_PWM2 0x5B | 210 | #define W83627HF_REG_PWM2 0x5B |
211 | 211 | ||
212 | static const u8 W83627THF_REG_PWM_ENABLE[] = { | ||
213 | 0x04, /* FAN 1 mode */ | ||
214 | 0x04, /* FAN 2 mode */ | ||
215 | 0x12, /* FAN AUX mode */ | ||
216 | }; | ||
217 | static const u8 W83627THF_PWM_ENABLE_SHIFT[] = { 2, 4, 1 }; | ||
218 | |||
212 | #define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */ | 219 | #define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */ |
213 | #define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */ | 220 | #define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */ |
214 | #define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */ | 221 | #define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */ |
@@ -366,6 +373,9 @@ struct w83627hf_data { | |||
366 | u32 alarms; /* Register encoding, combined */ | 373 | u32 alarms; /* Register encoding, combined */ |
367 | u32 beep_mask; /* Register encoding, combined */ | 374 | u32 beep_mask; /* Register encoding, combined */ |
368 | u8 pwm[3]; /* Register value */ | 375 | u8 pwm[3]; /* Register value */ |
376 | u8 pwm_enable[3]; /* 1 = manual | ||
377 | 2 = thermal cruise (also called SmartFan I) | ||
378 | 3 = fan speed cruise */ | ||
369 | u8 pwm_freq[3]; /* Register value */ | 379 | u8 pwm_freq[3]; /* Register value */ |
370 | u16 sens[3]; /* 1 = pentium diode; 2 = 3904 diode; | 380 | u16 sens[3]; /* 1 = pentium diode; 2 = 3904 diode; |
371 | 4 = thermistor */ | 381 | 4 = thermistor */ |
@@ -957,6 +967,42 @@ static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1); | |||
957 | static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2); | 967 | static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2); |
958 | 968 | ||
959 | static ssize_t | 969 | static ssize_t |
970 | show_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf) | ||
971 | { | ||
972 | int nr = to_sensor_dev_attr(devattr)->index; | ||
973 | struct w83627hf_data *data = w83627hf_update_device(dev); | ||
974 | return sprintf(buf, "%d\n", data->pwm_enable[nr]); | ||
975 | } | ||
976 | |||
977 | static ssize_t | ||
978 | store_pwm_enable(struct device *dev, struct device_attribute *devattr, | ||
979 | const char *buf, size_t count) | ||
980 | { | ||
981 | int nr = to_sensor_dev_attr(devattr)->index; | ||
982 | struct w83627hf_data *data = dev_get_drvdata(dev); | ||
983 | unsigned long val = simple_strtoul(buf, NULL, 10); | ||
984 | u8 reg; | ||
985 | |||
986 | if (!val || (val > 3)) /* modes 1, 2 and 3 are supported */ | ||
987 | return -EINVAL; | ||
988 | mutex_lock(&data->update_lock); | ||
989 | data->pwm_enable[nr] = val; | ||
990 | reg = w83627hf_read_value(data, W83627THF_REG_PWM_ENABLE[nr]); | ||
991 | reg &= ~(0x03 << W83627THF_PWM_ENABLE_SHIFT[nr]); | ||
992 | reg |= (val - 1) << W83627THF_PWM_ENABLE_SHIFT[nr]; | ||
993 | w83627hf_write_value(data, W83627THF_REG_PWM_ENABLE[nr], reg); | ||
994 | mutex_unlock(&data->update_lock); | ||
995 | return count; | ||
996 | } | ||
997 | |||
998 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
999 | store_pwm_enable, 0); | ||
1000 | static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
1001 | store_pwm_enable, 1); | ||
1002 | static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
1003 | store_pwm_enable, 2); | ||
1004 | |||
1005 | static ssize_t | ||
960 | show_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf) | 1006 | show_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf) |
961 | { | 1007 | { |
962 | int nr = to_sensor_dev_attr(devattr)->index; | 1008 | int nr = to_sensor_dev_attr(devattr)->index; |
@@ -1223,6 +1269,11 @@ static struct attribute *w83627hf_attributes_opt[] = { | |||
1223 | &sensor_dev_attr_pwm1_freq.dev_attr.attr, | 1269 | &sensor_dev_attr_pwm1_freq.dev_attr.attr, |
1224 | &sensor_dev_attr_pwm2_freq.dev_attr.attr, | 1270 | &sensor_dev_attr_pwm2_freq.dev_attr.attr, |
1225 | &sensor_dev_attr_pwm3_freq.dev_attr.attr, | 1271 | &sensor_dev_attr_pwm3_freq.dev_attr.attr, |
1272 | |||
1273 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
1274 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
1275 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
1276 | |||
1226 | NULL | 1277 | NULL |
1227 | }; | 1278 | }; |
1228 | 1279 | ||
@@ -1366,6 +1417,19 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) | |||
1366 | &sensor_dev_attr_pwm3_freq.dev_attr))) | 1417 | &sensor_dev_attr_pwm3_freq.dev_attr))) |
1367 | goto ERROR4; | 1418 | goto ERROR4; |
1368 | 1419 | ||
1420 | if (data->type != w83627hf) | ||
1421 | if ((err = device_create_file(dev, | ||
1422 | &sensor_dev_attr_pwm1_enable.dev_attr)) | ||
1423 | || (err = device_create_file(dev, | ||
1424 | &sensor_dev_attr_pwm2_enable.dev_attr))) | ||
1425 | goto ERROR4; | ||
1426 | |||
1427 | if (data->type == w83627thf || data->type == w83637hf | ||
1428 | || data->type == w83687thf) | ||
1429 | if ((err = device_create_file(dev, | ||
1430 | &sensor_dev_attr_pwm3_enable.dev_attr))) | ||
1431 | goto ERROR4; | ||
1432 | |||
1369 | data->hwmon_dev = hwmon_device_register(dev); | 1433 | data->hwmon_dev = hwmon_device_register(dev); |
1370 | if (IS_ERR(data->hwmon_dev)) { | 1434 | if (IS_ERR(data->hwmon_dev)) { |
1371 | err = PTR_ERR(data->hwmon_dev); | 1435 | err = PTR_ERR(data->hwmon_dev); |
@@ -1655,6 +1719,7 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) | |||
1655 | { | 1719 | { |
1656 | struct w83627hf_data *data = dev_get_drvdata(dev); | 1720 | struct w83627hf_data *data = dev_get_drvdata(dev); |
1657 | int i, num_temps = (data->type == w83697hf) ? 2 : 3; | 1721 | int i, num_temps = (data->type == w83697hf) ? 2 : 3; |
1722 | int num_pwms = (data->type == w83697hf) ? 2 : 3; | ||
1658 | 1723 | ||
1659 | mutex_lock(&data->update_lock); | 1724 | mutex_lock(&data->update_lock); |
1660 | 1725 | ||
@@ -1707,6 +1772,15 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) | |||
1707 | break; | 1772 | break; |
1708 | } | 1773 | } |
1709 | } | 1774 | } |
1775 | if (data->type != w83627hf) { | ||
1776 | for (i = 0; i < num_pwms; i++) { | ||
1777 | u8 tmp = w83627hf_read_value(data, | ||
1778 | W83627THF_REG_PWM_ENABLE[i]); | ||
1779 | data->pwm_enable[i] = | ||
1780 | ((tmp >> W83627THF_PWM_ENABLE_SHIFT[i]) | ||
1781 | & 0x03) + 1; | ||
1782 | } | ||
1783 | } | ||
1710 | for (i = 0; i < num_temps; i++) { | 1784 | for (i = 0; i < num_temps; i++) { |
1711 | data->temp[i] = w83627hf_read_value( | 1785 | data->temp[i] = w83627hf_read_value( |
1712 | data, w83627hf_reg_temp[i]); | 1786 | data, w83627hf_reg_temp[i]); |