aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorMarc Hulsman <m.hulsman@tudelft.nl>2008-10-17 11:51:17 -0400
committerJean Delvare <khali@mahadeva.delvare>2008-10-17 11:51:17 -0400
commit6495ce184033d5e70dfdf5bb8d149e9e02feaaa9 (patch)
treed1d0d2f2e52363f3c416413c5e554d4e42a61b16 /drivers/hwmon
parent6e1ecd9b8f1358ed4d099f0c54434240dc40debe (diff)
hwmon: (w83791d) add manual PWM support
Add PWM manual control. Signed-off-by: Marc Hulsman <m.hulsman@tudelft.nl> Acked-by: Hans de Goede <j.w.r.degoede@hhs.nl> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/w83791d.c67
1 files changed, 66 insertions, 1 deletions
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index 6b1cec9950ff..a8ff4e126713 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -23,7 +23,7 @@
23 Supports following chips: 23 Supports following chips:
24 24
25 Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA 25 Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
26 w83791d 10 5 3 3 0x71 0x5ca3 yes no 26 w83791d 10 5 5 3 0x71 0x5ca3 yes no
27 27
28 The w83791d chip appears to be part way between the 83781d and the 28 The w83791d chip appears to be part way between the 83781d and the
29 83792d. Thus, this file is derived from both the w83792d.c and 29 83792d. Thus, this file is derived from both the w83792d.c and
@@ -45,6 +45,7 @@
45#define NUMBER_OF_VIN 10 45#define NUMBER_OF_VIN 10
46#define NUMBER_OF_FANIN 5 46#define NUMBER_OF_FANIN 5
47#define NUMBER_OF_TEMPIN 3 47#define NUMBER_OF_TEMPIN 3
48#define NUMBER_OF_PWM 5
48 49
49/* Addresses to scan */ 50/* Addresses to scan */
50static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, 51static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
@@ -116,6 +117,14 @@ static const u8 W83791D_REG_FAN_MIN[NUMBER_OF_FANIN] = {
116 0xBD, /* FAN 5 Count Low Limit in DataSheet */ 117 0xBD, /* FAN 5 Count Low Limit in DataSheet */
117}; 118};
118 119
120static const u8 W83791D_REG_PWM[NUMBER_OF_PWM] = {
121 0x81, /* PWM 1 duty cycle register in DataSheet */
122 0x83, /* PWM 2 duty cycle register in DataSheet */
123 0x94, /* PWM 3 duty cycle register in DataSheet */
124 0xA0, /* PWM 4 duty cycle register in DataSheet */
125 0xA1, /* PWM 5 duty cycle register in DataSheet */
126};
127
119static const u8 W83791D_REG_FAN_CFG[2] = { 128static const u8 W83791D_REG_FAN_CFG[2] = {
120 0x84, /* FAN 1/2 configuration */ 129 0x84, /* FAN 1/2 configuration */
121 0x95, /* FAN 3 configuration */ 130 0x95, /* FAN 3 configuration */
@@ -276,6 +285,9 @@ struct w83791d_data {
276 two sensors with three values 285 two sensors with three values
277 (cur, over, hyst) */ 286 (cur, over, hyst) */
278 287
288 /* PWMs */
289 u8 pwm[5]; /* pwm duty cycle */
290
279 /* Misc */ 291 /* Misc */
280 u32 alarms; /* realtime status register encoding,combined */ 292 u32 alarms; /* realtime status register encoding,combined */
281 u8 beep_enable; /* Global beep enable */ 293 u8 beep_enable; /* Global beep enable */
@@ -653,6 +665,48 @@ static struct sensor_device_attribute sda_fan_alarm[] = {
653 SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22), 665 SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22),
654}; 666};
655 667
668/* read/write PWMs */
669static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
670 char *buf)
671{
672 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
673 int nr = sensor_attr->index;
674 struct w83791d_data *data = w83791d_update_device(dev);
675 return sprintf(buf, "%u\n", data->pwm[nr]);
676}
677
678static ssize_t store_pwm(struct device *dev, struct device_attribute *attr,
679 const char *buf, size_t count)
680{
681 struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
682 struct i2c_client *client = to_i2c_client(dev);
683 struct w83791d_data *data = i2c_get_clientdata(client);
684 int nr = sensor_attr->index;
685 unsigned long val;
686
687 if (strict_strtoul(buf, 10, &val))
688 return -EINVAL;
689
690 mutex_lock(&data->update_lock);
691 data->pwm[nr] = SENSORS_LIMIT(val, 0, 255);
692 w83791d_write(client, W83791D_REG_PWM[nr], data->pwm[nr]);
693 mutex_unlock(&data->update_lock);
694 return count;
695}
696
697static struct sensor_device_attribute sda_pwm[] = {
698 SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO,
699 show_pwm, store_pwm, 0),
700 SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO,
701 show_pwm, store_pwm, 1),
702 SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO,
703 show_pwm, store_pwm, 2),
704 SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO,
705 show_pwm, store_pwm, 3),
706 SENSOR_ATTR(pwm5, S_IWUSR | S_IRUGO,
707 show_pwm, store_pwm, 4),
708};
709
656/* read/write the temperature1, includes measured value and limits */ 710/* read/write the temperature1, includes measured value and limits */
657static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr, 711static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr,
658 char *buf) 712 char *buf)
@@ -917,6 +971,9 @@ static struct attribute *w83791d_attributes[] = {
917 &sda_beep_ctrl[1].dev_attr.attr, 971 &sda_beep_ctrl[1].dev_attr.attr,
918 &dev_attr_cpu0_vid.attr, 972 &dev_attr_cpu0_vid.attr,
919 &dev_attr_vrm.attr, 973 &dev_attr_vrm.attr,
974 &sda_pwm[0].dev_attr.attr,
975 &sda_pwm[1].dev_attr.attr,
976 &sda_pwm[2].dev_attr.attr,
920 NULL 977 NULL
921}; 978};
922 979
@@ -930,6 +987,8 @@ static const struct attribute_group w83791d_group = {
930static struct attribute *w83791d_attributes_fanpwm45[] = { 987static struct attribute *w83791d_attributes_fanpwm45[] = {
931 FAN_UNIT_ATTRS(3), 988 FAN_UNIT_ATTRS(3),
932 FAN_UNIT_ATTRS(4), 989 FAN_UNIT_ATTRS(4),
990 &sda_pwm[3].dev_attr.attr,
991 &sda_pwm[4].dev_attr.attr,
933 NULL 992 NULL
934}; 993};
935 994
@@ -1260,6 +1319,12 @@ static struct w83791d_data *w83791d_update_device(struct device *dev)
1260 for (i = 0; i < 3; i++) 1319 for (i = 0; i < 3; i++)
1261 data->fan_div[i] |= (vbat_reg >> (3 + i)) & 0x04; 1320 data->fan_div[i] |= (vbat_reg >> (3 + i)) & 0x04;
1262 1321
1322 /* Update PWM duty cycle */
1323 for (i = 0; i < NUMBER_OF_PWM; i++) {
1324 data->pwm[i] = w83791d_read(client,
1325 W83791D_REG_PWM[i]);
1326 }
1327
1263 /* Update the first temperature sensor */ 1328 /* Update the first temperature sensor */
1264 for (i = 0; i < 3; i++) { 1329 for (i = 0; i < 3; i++) {
1265 data->temp1[i] = w83791d_read(client, 1330 data->temp1[i] = w83791d_read(client,