diff options
author | Charles Spirakis <bezaur@gmail.com> | 2007-09-04 16:31:56 -0400 |
---|---|---|
committer | Mark M. Hoffman <mhoffman@lightlink.com> | 2007-10-09 22:56:30 -0400 |
commit | 6438312367523b26bd628b60cfd16f25a7a6f7ae (patch) | |
tree | 70798f9f3d2c19993e227e1205861982ca636059 | |
parent | 7b6d1f044d95395ca103bfb6869caa996fedbbd2 (diff) |
hwmon: (w83791d) new sysfs beep/alarm methodology
Add new sysfs alarm methodology to w83791d driver
Signed-off-by: Charles Spirakis <bezaur@gmail.com>
Acked-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Mark M. Hoffman <mhoffman@lightlink.com>
-rw-r--r-- | Documentation/hwmon/w83791d | 96 | ||||
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | drivers/hwmon/w83791d.c | 122 |
3 files changed, 176 insertions, 44 deletions
diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d index db9881df88a5..f153b2f6d62c 100644 --- a/Documentation/hwmon/w83791d +++ b/Documentation/hwmon/w83791d | |||
@@ -75,46 +75,64 @@ Voltage sensors (also known as IN sensors) report their values in millivolts. | |||
75 | An alarm is triggered if the voltage has crossed a programmable minimum | 75 | An alarm is triggered if the voltage has crossed a programmable minimum |
76 | or maximum limit. | 76 | or maximum limit. |
77 | 77 | ||
78 | The bit ordering for the alarm "realtime status register" and the | 78 | The w83791d has a global bit used to enable beeping from the speaker when an |
79 | "beep enable registers" are different. | 79 | alarm is triggered as well as a bitmask to enable or disable the beep for |
80 | 80 | specific alarms. You need both the global beep enable bit and the | |
81 | in0 (VCORE) : alarms: 0x000001 beep_enable: 0x000001 | 81 | corresponding beep bit to be on for a triggered alarm to sound a beep. |
82 | in1 (VINR0) : alarms: 0x000002 beep_enable: 0x002000 <== mismatch | 82 | |
83 | in2 (+3.3VIN): alarms: 0x000004 beep_enable: 0x000004 | 83 | The sysfs interface to the gloabal enable is via the sysfs beep_enable file. |
84 | in3 (5VDD) : alarms: 0x000008 beep_enable: 0x000008 | 84 | This file is used for both legacy and new code. |
85 | in4 (+12VIN) : alarms: 0x000100 beep_enable: 0x000100 | 85 | |
86 | in5 (-12VIN) : alarms: 0x000200 beep_enable: 0x000200 | 86 | The sysfs interface to the beep bitmask has migrated from the original legacy |
87 | in6 (-5VIN) : alarms: 0x000400 beep_enable: 0x000400 | 87 | method of a single sysfs beep_mask file to a newer method using multiple |
88 | in7 (VSB) : alarms: 0x080000 beep_enable: 0x010000 <== mismatch | 88 | *_beep files as described in .../Documentation/hwmon/sysfs-interface. |
89 | in8 (VBAT) : alarms: 0x100000 beep_enable: 0x020000 <== mismatch | 89 | |
90 | in9 (VINR1) : alarms: 0x004000 beep_enable: 0x004000 | 90 | A similar change has occured for the bitmap corresponding to the alarms. The |
91 | temp1 : alarms: 0x000010 beep_enable: 0x000010 | 91 | original legacy method used a single sysfs alarms file containing a bitmap |
92 | temp2 : alarms: 0x000020 beep_enable: 0x000020 | 92 | of triggered alarms. The newer method uses multiple sysfs *_alarm files |
93 | temp3 : alarms: 0x002000 beep_enable: 0x000002 <== mismatch | 93 | (again following the pattern described in sysfs-interface). |
94 | fan1 : alarms: 0x000040 beep_enable: 0x000040 | 94 | |
95 | fan2 : alarms: 0x000080 beep_enable: 0x000080 | 95 | Since both methods read and write the underlying hardware, they can be used |
96 | fan3 : alarms: 0x000800 beep_enable: 0x000800 | 96 | interchangeably and changes in one will automatically be reflected by |
97 | fan4 : alarms: 0x200000 beep_enable: 0x200000 | 97 | the other. If you use the legacy bitmask method, your user-space code is |
98 | fan5 : alarms: 0x400000 beep_enable: 0x400000 | 98 | responsible for handling the fact that the alarms and beep_mask bitmaps |
99 | tart1 : alarms: 0x010000 beep_enable: 0x040000 <== mismatch | 99 | are not the same (see the table below). |
100 | tart2 : alarms: 0x020000 beep_enable: 0x080000 <== mismatch | 100 | |
101 | tart3 : alarms: 0x040000 beep_enable: 0x100000 <== mismatch | 101 | NOTE: All new code should be written to use the newer sysfs-interface |
102 | case_open : alarms: 0x001000 beep_enable: 0x001000 | 102 | specification as that avoids bitmap problems and is the preferred interface |
103 | user_enable : alarms: -------- beep_enable: 0x800000 | 103 | going forward. |
104 | 104 | ||
105 | *** NOTE: It is the responsibility of user-space code to handle the fact | 105 | The driver reads the hardware chip values at most once every three seconds. |
106 | that the beep enable and alarm bits are in different positions when using that | 106 | User mode code requesting values more often will receive cached values. |
107 | feature of the chip. | 107 | |
108 | 108 | Alarms bitmap vs. beep_mask bitmask | |
109 | When an alarm goes off, you can be warned by a beeping signal through your | 109 | ------------------------------------ |
110 | computer speaker. It is possible to enable all beeping globally, or only | 110 | For legacy code using the alarms and beep_mask files: |
111 | the beeping for some alarms. | 111 | |
112 | 112 | in0 (VCORE) : alarms: 0x000001 beep_mask: 0x000001 | |
113 | The driver only reads the chip values each 3 seconds; reading them more | 113 | in1 (VINR0) : alarms: 0x000002 beep_mask: 0x002000 <== mismatch |
114 | often will do no harm, but will return 'old' values. | 114 | in2 (+3.3VIN): alarms: 0x000004 beep_mask: 0x000004 |
115 | in3 (5VDD) : alarms: 0x000008 beep_mask: 0x000008 | ||
116 | in4 (+12VIN) : alarms: 0x000100 beep_mask: 0x000100 | ||
117 | in5 (-12VIN) : alarms: 0x000200 beep_mask: 0x000200 | ||
118 | in6 (-5VIN) : alarms: 0x000400 beep_mask: 0x000400 | ||
119 | in7 (VSB) : alarms: 0x080000 beep_mask: 0x010000 <== mismatch | ||
120 | in8 (VBAT) : alarms: 0x100000 beep_mask: 0x020000 <== mismatch | ||
121 | in9 (VINR1) : alarms: 0x004000 beep_mask: 0x004000 | ||
122 | temp1 : alarms: 0x000010 beep_mask: 0x000010 | ||
123 | temp2 : alarms: 0x000020 beep_mask: 0x000020 | ||
124 | temp3 : alarms: 0x002000 beep_mask: 0x000002 <== mismatch | ||
125 | fan1 : alarms: 0x000040 beep_mask: 0x000040 | ||
126 | fan2 : alarms: 0x000080 beep_mask: 0x000080 | ||
127 | fan3 : alarms: 0x000800 beep_mask: 0x000800 | ||
128 | fan4 : alarms: 0x200000 beep_mask: 0x200000 | ||
129 | fan5 : alarms: 0x400000 beep_mask: 0x400000 | ||
130 | tart1 : alarms: 0x010000 beep_mask: 0x040000 <== mismatch | ||
131 | tart2 : alarms: 0x020000 beep_mask: 0x080000 <== mismatch | ||
132 | tart3 : alarms: 0x040000 beep_mask: 0x100000 <== mismatch | ||
133 | case_open : alarms: 0x001000 beep_mask: 0x001000 | ||
134 | global_enable: alarms: -------- beep_mask: 0x800000 (modified via beep_enable) | ||
115 | 135 | ||
116 | W83791D TODO: | 136 | W83791D TODO: |
117 | --------------- | 137 | --------------- |
118 | Provide a patch for per-file alarms and beep enables as defined in the hwmon | ||
119 | documentation (Documentation/hwmon/sysfs-interface) | ||
120 | Provide a patch for smart-fan control (still need appropriate motherboard/fans) | 138 | Provide a patch for smart-fan control (still need appropriate motherboard/fans) |
diff --git a/MAINTAINERS b/MAINTAINERS index 9a91d9e3f1f2..62931dbb4a75 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4106,7 +4106,7 @@ W83791D HARDWARE MONITORING DRIVER | |||
4106 | P: Charles Spirakis | 4106 | P: Charles Spirakis |
4107 | M: bezaur@gmail.com | 4107 | M: bezaur@gmail.com |
4108 | L: lm-sensors@lm-sensors.org | 4108 | L: lm-sensors@lm-sensors.org |
4109 | S: Maintained | 4109 | S: Odd Fixes |
4110 | 4110 | ||
4111 | W83793 HARDWARE MONITORING DRIVER | 4111 | W83793 HARDWARE MONITORING DRIVER |
4112 | P: Rudolf Marek | 4112 | P: Rudolf Marek |
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index a3cb89455ea7..de4eb3e7b271 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c | |||
@@ -2,7 +2,7 @@ | |||
2 | w83791d.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | w83791d.c - Part of lm_sensors, Linux kernel modules for hardware |
3 | monitoring | 3 | monitoring |
4 | 4 | ||
5 | Copyright (C) 2006 Charles Spirakis <bezaur@gmail.com> | 5 | Copyright (C) 2006-2007 Charles Spirakis <bezaur@gmail.com> |
6 | 6 | ||
7 | This program is free software; you can redistribute it and/or modify | 7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by | 8 | it under the terms of the GNU General Public License as published by |
@@ -384,6 +384,85 @@ static struct sensor_device_attribute sda_in_max[] = { | |||
384 | SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), | 384 | SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), |
385 | }; | 385 | }; |
386 | 386 | ||
387 | |||
388 | static ssize_t show_beep(struct device *dev, struct device_attribute *attr, | ||
389 | char *buf) | ||
390 | { | ||
391 | struct sensor_device_attribute *sensor_attr = | ||
392 | to_sensor_dev_attr(attr); | ||
393 | struct w83791d_data *data = w83791d_update_device(dev); | ||
394 | int bitnr = sensor_attr->index; | ||
395 | |||
396 | return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1); | ||
397 | } | ||
398 | |||
399 | static ssize_t store_beep(struct device *dev, struct device_attribute *attr, | ||
400 | const char *buf, size_t count) | ||
401 | { | ||
402 | struct sensor_device_attribute *sensor_attr = | ||
403 | to_sensor_dev_attr(attr); | ||
404 | struct i2c_client *client = to_i2c_client(dev); | ||
405 | struct w83791d_data *data = i2c_get_clientdata(client); | ||
406 | int bitnr = sensor_attr->index; | ||
407 | int bytenr = bitnr / 8; | ||
408 | long val = simple_strtol(buf, NULL, 10) ? 1 : 0; | ||
409 | |||
410 | mutex_lock(&data->update_lock); | ||
411 | |||
412 | data->beep_mask &= ~(0xff << (bytenr * 8)); | ||
413 | data->beep_mask |= w83791d_read(client, W83791D_REG_BEEP_CTRL[bytenr]) | ||
414 | << (bytenr * 8); | ||
415 | |||
416 | data->beep_mask &= ~(1 << bitnr); | ||
417 | data->beep_mask |= val << bitnr; | ||
418 | |||
419 | w83791d_write(client, W83791D_REG_BEEP_CTRL[bytenr], | ||
420 | (data->beep_mask >> (bytenr * 8)) & 0xff); | ||
421 | |||
422 | mutex_unlock(&data->update_lock); | ||
423 | |||
424 | return count; | ||
425 | } | ||
426 | |||
427 | static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, | ||
428 | char *buf) | ||
429 | { | ||
430 | struct sensor_device_attribute *sensor_attr = | ||
431 | to_sensor_dev_attr(attr); | ||
432 | struct w83791d_data *data = w83791d_update_device(dev); | ||
433 | int bitnr = sensor_attr->index; | ||
434 | |||
435 | return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); | ||
436 | } | ||
437 | |||
438 | /* Note: The bitmask for the beep enable/disable is different than | ||
439 | the bitmask for the alarm. */ | ||
440 | static struct sensor_device_attribute sda_in_beep[] = { | ||
441 | SENSOR_ATTR(in0_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 0), | ||
442 | SENSOR_ATTR(in1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 13), | ||
443 | SENSOR_ATTR(in2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 2), | ||
444 | SENSOR_ATTR(in3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 3), | ||
445 | SENSOR_ATTR(in4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 8), | ||
446 | SENSOR_ATTR(in5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 9), | ||
447 | SENSOR_ATTR(in6_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 10), | ||
448 | SENSOR_ATTR(in7_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 16), | ||
449 | SENSOR_ATTR(in8_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 17), | ||
450 | SENSOR_ATTR(in9_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 14), | ||
451 | }; | ||
452 | |||
453 | static struct sensor_device_attribute sda_in_alarm[] = { | ||
454 | SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), | ||
455 | SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), | ||
456 | SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), | ||
457 | SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), | ||
458 | SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8), | ||
459 | SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9), | ||
460 | SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10), | ||
461 | SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 19), | ||
462 | SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20), | ||
463 | SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 14), | ||
464 | }; | ||
465 | |||
387 | #define show_fan_reg(reg) \ | 466 | #define show_fan_reg(reg) \ |
388 | static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ | 467 | static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ |
389 | char *buf) \ | 468 | char *buf) \ |
@@ -536,6 +615,22 @@ static struct sensor_device_attribute sda_fan_div[] = { | |||
536 | show_fan_div, store_fan_div, 4), | 615 | show_fan_div, store_fan_div, 4), |
537 | }; | 616 | }; |
538 | 617 | ||
618 | static struct sensor_device_attribute sda_fan_beep[] = { | ||
619 | SENSOR_ATTR(fan1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 6), | ||
620 | SENSOR_ATTR(fan2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 7), | ||
621 | SENSOR_ATTR(fan3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 11), | ||
622 | SENSOR_ATTR(fan4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 21), | ||
623 | SENSOR_ATTR(fan5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 22), | ||
624 | }; | ||
625 | |||
626 | static struct sensor_device_attribute sda_fan_alarm[] = { | ||
627 | SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6), | ||
628 | SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7), | ||
629 | SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11), | ||
630 | SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21), | ||
631 | SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22), | ||
632 | }; | ||
633 | |||
539 | /* read/write the temperature1, includes measured value and limits */ | 634 | /* read/write the temperature1, includes measured value and limits */ |
540 | static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr, | 635 | static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr, |
541 | char *buf) | 636 | char *buf) |
@@ -618,6 +713,19 @@ static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { | |||
618 | show_temp23, store_temp23, 1, 2), | 713 | show_temp23, store_temp23, 1, 2), |
619 | }; | 714 | }; |
620 | 715 | ||
716 | /* Note: The bitmask for the beep enable/disable is different than | ||
717 | the bitmask for the alarm. */ | ||
718 | static struct sensor_device_attribute sda_temp_beep[] = { | ||
719 | SENSOR_ATTR(temp1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 4), | ||
720 | SENSOR_ATTR(temp2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 5), | ||
721 | SENSOR_ATTR(temp3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 1), | ||
722 | }; | ||
723 | |||
724 | static struct sensor_device_attribute sda_temp_alarm[] = { | ||
725 | SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), | ||
726 | SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), | ||
727 | SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), | ||
728 | }; | ||
621 | 729 | ||
622 | /* get reatime status of all sensors items: voltage, temp, fan */ | 730 | /* get reatime status of all sensors items: voltage, temp, fan */ |
623 | static ssize_t show_alarms_reg(struct device *dev, | 731 | static ssize_t show_alarms_reg(struct device *dev, |
@@ -749,17 +857,23 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); | |||
749 | #define IN_UNIT_ATTRS(X) \ | 857 | #define IN_UNIT_ATTRS(X) \ |
750 | &sda_in_input[X].dev_attr.attr, \ | 858 | &sda_in_input[X].dev_attr.attr, \ |
751 | &sda_in_min[X].dev_attr.attr, \ | 859 | &sda_in_min[X].dev_attr.attr, \ |
752 | &sda_in_max[X].dev_attr.attr | 860 | &sda_in_max[X].dev_attr.attr, \ |
861 | &sda_in_beep[X].dev_attr.attr, \ | ||
862 | &sda_in_alarm[X].dev_attr.attr | ||
753 | 863 | ||
754 | #define FAN_UNIT_ATTRS(X) \ | 864 | #define FAN_UNIT_ATTRS(X) \ |
755 | &sda_fan_input[X].dev_attr.attr, \ | 865 | &sda_fan_input[X].dev_attr.attr, \ |
756 | &sda_fan_min[X].dev_attr.attr, \ | 866 | &sda_fan_min[X].dev_attr.attr, \ |
757 | &sda_fan_div[X].dev_attr.attr | 867 | &sda_fan_div[X].dev_attr.attr, \ |
868 | &sda_fan_beep[X].dev_attr.attr, \ | ||
869 | &sda_fan_alarm[X].dev_attr.attr | ||
758 | 870 | ||
759 | #define TEMP_UNIT_ATTRS(X) \ | 871 | #define TEMP_UNIT_ATTRS(X) \ |
760 | &sda_temp_input[X].dev_attr.attr, \ | 872 | &sda_temp_input[X].dev_attr.attr, \ |
761 | &sda_temp_max[X].dev_attr.attr, \ | 873 | &sda_temp_max[X].dev_attr.attr, \ |
762 | &sda_temp_max_hyst[X].dev_attr.attr | 874 | &sda_temp_max_hyst[X].dev_attr.attr, \ |
875 | &sda_temp_beep[X].dev_attr.attr, \ | ||
876 | &sda_temp_alarm[X].dev_attr.attr | ||
763 | 877 | ||
764 | static struct attribute *w83791d_attributes[] = { | 878 | static struct attribute *w83791d_attributes[] = { |
765 | IN_UNIT_ATTRS(0), | 879 | IN_UNIT_ATTRS(0), |