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>wifi-calibration
parent
7b6d1f044d
commit
6438312367
|
@ -75,46 +75,64 @@ Voltage sensors (also known as IN sensors) report their values in millivolts.
|
||||||
An alarm is triggered if the voltage has crossed a programmable minimum
|
An alarm is triggered if the voltage has crossed a programmable minimum
|
||||||
or maximum limit.
|
or maximum limit.
|
||||||
|
|
||||||
The bit ordering for the alarm "realtime status register" and the
|
The w83791d has a global bit used to enable beeping from the speaker when an
|
||||||
"beep enable registers" are different.
|
alarm is triggered as well as a bitmask to enable or disable the beep for
|
||||||
|
specific alarms. You need both the global beep enable bit and the
|
||||||
|
corresponding beep bit to be on for a triggered alarm to sound a beep.
|
||||||
|
|
||||||
in0 (VCORE) : alarms: 0x000001 beep_enable: 0x000001
|
The sysfs interface to the gloabal enable is via the sysfs beep_enable file.
|
||||||
in1 (VINR0) : alarms: 0x000002 beep_enable: 0x002000 <== mismatch
|
This file is used for both legacy and new code.
|
||||||
in2 (+3.3VIN): alarms: 0x000004 beep_enable: 0x000004
|
|
||||||
in3 (5VDD) : alarms: 0x000008 beep_enable: 0x000008
|
|
||||||
in4 (+12VIN) : alarms: 0x000100 beep_enable: 0x000100
|
|
||||||
in5 (-12VIN) : alarms: 0x000200 beep_enable: 0x000200
|
|
||||||
in6 (-5VIN) : alarms: 0x000400 beep_enable: 0x000400
|
|
||||||
in7 (VSB) : alarms: 0x080000 beep_enable: 0x010000 <== mismatch
|
|
||||||
in8 (VBAT) : alarms: 0x100000 beep_enable: 0x020000 <== mismatch
|
|
||||||
in9 (VINR1) : alarms: 0x004000 beep_enable: 0x004000
|
|
||||||
temp1 : alarms: 0x000010 beep_enable: 0x000010
|
|
||||||
temp2 : alarms: 0x000020 beep_enable: 0x000020
|
|
||||||
temp3 : alarms: 0x002000 beep_enable: 0x000002 <== mismatch
|
|
||||||
fan1 : alarms: 0x000040 beep_enable: 0x000040
|
|
||||||
fan2 : alarms: 0x000080 beep_enable: 0x000080
|
|
||||||
fan3 : alarms: 0x000800 beep_enable: 0x000800
|
|
||||||
fan4 : alarms: 0x200000 beep_enable: 0x200000
|
|
||||||
fan5 : alarms: 0x400000 beep_enable: 0x400000
|
|
||||||
tart1 : alarms: 0x010000 beep_enable: 0x040000 <== mismatch
|
|
||||||
tart2 : alarms: 0x020000 beep_enable: 0x080000 <== mismatch
|
|
||||||
tart3 : alarms: 0x040000 beep_enable: 0x100000 <== mismatch
|
|
||||||
case_open : alarms: 0x001000 beep_enable: 0x001000
|
|
||||||
user_enable : alarms: -------- beep_enable: 0x800000
|
|
||||||
|
|
||||||
*** NOTE: It is the responsibility of user-space code to handle the fact
|
The sysfs interface to the beep bitmask has migrated from the original legacy
|
||||||
that the beep enable and alarm bits are in different positions when using that
|
method of a single sysfs beep_mask file to a newer method using multiple
|
||||||
feature of the chip.
|
*_beep files as described in .../Documentation/hwmon/sysfs-interface.
|
||||||
|
|
||||||
When an alarm goes off, you can be warned by a beeping signal through your
|
A similar change has occured for the bitmap corresponding to the alarms. The
|
||||||
computer speaker. It is possible to enable all beeping globally, or only
|
original legacy method used a single sysfs alarms file containing a bitmap
|
||||||
the beeping for some alarms.
|
of triggered alarms. The newer method uses multiple sysfs *_alarm files
|
||||||
|
(again following the pattern described in sysfs-interface).
|
||||||
|
|
||||||
The driver only reads the chip values each 3 seconds; reading them more
|
Since both methods read and write the underlying hardware, they can be used
|
||||||
often will do no harm, but will return 'old' values.
|
interchangeably and changes in one will automatically be reflected by
|
||||||
|
the other. If you use the legacy bitmask method, your user-space code is
|
||||||
|
responsible for handling the fact that the alarms and beep_mask bitmaps
|
||||||
|
are not the same (see the table below).
|
||||||
|
|
||||||
|
NOTE: All new code should be written to use the newer sysfs-interface
|
||||||
|
specification as that avoids bitmap problems and is the preferred interface
|
||||||
|
going forward.
|
||||||
|
|
||||||
|
The driver reads the hardware chip values at most once every three seconds.
|
||||||
|
User mode code requesting values more often will receive cached values.
|
||||||
|
|
||||||
|
Alarms bitmap vs. beep_mask bitmask
|
||||||
|
------------------------------------
|
||||||
|
For legacy code using the alarms and beep_mask files:
|
||||||
|
|
||||||
|
in0 (VCORE) : alarms: 0x000001 beep_mask: 0x000001
|
||||||
|
in1 (VINR0) : alarms: 0x000002 beep_mask: 0x002000 <== mismatch
|
||||||
|
in2 (+3.3VIN): alarms: 0x000004 beep_mask: 0x000004
|
||||||
|
in3 (5VDD) : alarms: 0x000008 beep_mask: 0x000008
|
||||||
|
in4 (+12VIN) : alarms: 0x000100 beep_mask: 0x000100
|
||||||
|
in5 (-12VIN) : alarms: 0x000200 beep_mask: 0x000200
|
||||||
|
in6 (-5VIN) : alarms: 0x000400 beep_mask: 0x000400
|
||||||
|
in7 (VSB) : alarms: 0x080000 beep_mask: 0x010000 <== mismatch
|
||||||
|
in8 (VBAT) : alarms: 0x100000 beep_mask: 0x020000 <== mismatch
|
||||||
|
in9 (VINR1) : alarms: 0x004000 beep_mask: 0x004000
|
||||||
|
temp1 : alarms: 0x000010 beep_mask: 0x000010
|
||||||
|
temp2 : alarms: 0x000020 beep_mask: 0x000020
|
||||||
|
temp3 : alarms: 0x002000 beep_mask: 0x000002 <== mismatch
|
||||||
|
fan1 : alarms: 0x000040 beep_mask: 0x000040
|
||||||
|
fan2 : alarms: 0x000080 beep_mask: 0x000080
|
||||||
|
fan3 : alarms: 0x000800 beep_mask: 0x000800
|
||||||
|
fan4 : alarms: 0x200000 beep_mask: 0x200000
|
||||||
|
fan5 : alarms: 0x400000 beep_mask: 0x400000
|
||||||
|
tart1 : alarms: 0x010000 beep_mask: 0x040000 <== mismatch
|
||||||
|
tart2 : alarms: 0x020000 beep_mask: 0x080000 <== mismatch
|
||||||
|
tart3 : alarms: 0x040000 beep_mask: 0x100000 <== mismatch
|
||||||
|
case_open : alarms: 0x001000 beep_mask: 0x001000
|
||||||
|
global_enable: alarms: -------- beep_mask: 0x800000 (modified via beep_enable)
|
||||||
|
|
||||||
W83791D TODO:
|
W83791D TODO:
|
||||||
---------------
|
---------------
|
||||||
Provide a patch for per-file alarms and beep enables as defined in the hwmon
|
|
||||||
documentation (Documentation/hwmon/sysfs-interface)
|
|
||||||
Provide a patch for smart-fan control (still need appropriate motherboard/fans)
|
Provide a patch for smart-fan control (still need appropriate motherboard/fans)
|
||||||
|
|
|
@ -4106,7 +4106,7 @@ W83791D HARDWARE MONITORING DRIVER
|
||||||
P: Charles Spirakis
|
P: Charles Spirakis
|
||||||
M: bezaur@gmail.com
|
M: bezaur@gmail.com
|
||||||
L: lm-sensors@lm-sensors.org
|
L: lm-sensors@lm-sensors.org
|
||||||
S: Maintained
|
S: Odd Fixes
|
||||||
|
|
||||||
W83793 HARDWARE MONITORING DRIVER
|
W83793 HARDWARE MONITORING DRIVER
|
||||||
P: Rudolf Marek
|
P: Rudolf Marek
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
w83791d.c - Part of lm_sensors, Linux kernel modules for hardware
|
w83791d.c - Part of lm_sensors, Linux kernel modules for hardware
|
||||||
monitoring
|
monitoring
|
||||||
|
|
||||||
Copyright (C) 2006 Charles Spirakis <bezaur@gmail.com>
|
Copyright (C) 2006-2007 Charles Spirakis <bezaur@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
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[] = {
|
||||||
SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
|
SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct sensor_device_attribute *sensor_attr =
|
||||||
|
to_sensor_dev_attr(attr);
|
||||||
|
struct w83791d_data *data = w83791d_update_device(dev);
|
||||||
|
int bitnr = sensor_attr->index;
|
||||||
|
|
||||||
|
return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t store_beep(struct device *dev, struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct sensor_device_attribute *sensor_attr =
|
||||||
|
to_sensor_dev_attr(attr);
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct w83791d_data *data = i2c_get_clientdata(client);
|
||||||
|
int bitnr = sensor_attr->index;
|
||||||
|
int bytenr = bitnr / 8;
|
||||||
|
long val = simple_strtol(buf, NULL, 10) ? 1 : 0;
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
|
data->beep_mask &= ~(0xff << (bytenr * 8));
|
||||||
|
data->beep_mask |= w83791d_read(client, W83791D_REG_BEEP_CTRL[bytenr])
|
||||||
|
<< (bytenr * 8);
|
||||||
|
|
||||||
|
data->beep_mask &= ~(1 << bitnr);
|
||||||
|
data->beep_mask |= val << bitnr;
|
||||||
|
|
||||||
|
w83791d_write(client, W83791D_REG_BEEP_CTRL[bytenr],
|
||||||
|
(data->beep_mask >> (bytenr * 8)) & 0xff);
|
||||||
|
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct sensor_device_attribute *sensor_attr =
|
||||||
|
to_sensor_dev_attr(attr);
|
||||||
|
struct w83791d_data *data = w83791d_update_device(dev);
|
||||||
|
int bitnr = sensor_attr->index;
|
||||||
|
|
||||||
|
return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: The bitmask for the beep enable/disable is different than
|
||||||
|
the bitmask for the alarm. */
|
||||||
|
static struct sensor_device_attribute sda_in_beep[] = {
|
||||||
|
SENSOR_ATTR(in0_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 0),
|
||||||
|
SENSOR_ATTR(in1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 13),
|
||||||
|
SENSOR_ATTR(in2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 2),
|
||||||
|
SENSOR_ATTR(in3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 3),
|
||||||
|
SENSOR_ATTR(in4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 8),
|
||||||
|
SENSOR_ATTR(in5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 9),
|
||||||
|
SENSOR_ATTR(in6_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 10),
|
||||||
|
SENSOR_ATTR(in7_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 16),
|
||||||
|
SENSOR_ATTR(in8_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 17),
|
||||||
|
SENSOR_ATTR(in9_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 14),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sensor_device_attribute sda_in_alarm[] = {
|
||||||
|
SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0),
|
||||||
|
SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1),
|
||||||
|
SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2),
|
||||||
|
SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3),
|
||||||
|
SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8),
|
||||||
|
SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9),
|
||||||
|
SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10),
|
||||||
|
SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 19),
|
||||||
|
SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20),
|
||||||
|
SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 14),
|
||||||
|
};
|
||||||
|
|
||||||
#define show_fan_reg(reg) \
|
#define show_fan_reg(reg) \
|
||||||
static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
|
static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
|
||||||
char *buf) \
|
char *buf) \
|
||||||
|
@ -536,6 +615,22 @@ static struct sensor_device_attribute sda_fan_div[] = {
|
||||||
show_fan_div, store_fan_div, 4),
|
show_fan_div, store_fan_div, 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct sensor_device_attribute sda_fan_beep[] = {
|
||||||
|
SENSOR_ATTR(fan1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 6),
|
||||||
|
SENSOR_ATTR(fan2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 7),
|
||||||
|
SENSOR_ATTR(fan3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 11),
|
||||||
|
SENSOR_ATTR(fan4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 21),
|
||||||
|
SENSOR_ATTR(fan5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 22),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sensor_device_attribute sda_fan_alarm[] = {
|
||||||
|
SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6),
|
||||||
|
SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7),
|
||||||
|
SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11),
|
||||||
|
SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21),
|
||||||
|
SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22),
|
||||||
|
};
|
||||||
|
|
||||||
/* read/write the temperature1, includes measured value and limits */
|
/* read/write the temperature1, includes measured value and limits */
|
||||||
static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr,
|
static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr,
|
||||||
char *buf)
|
char *buf)
|
||||||
|
@ -618,6 +713,19 @@ static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
|
||||||
show_temp23, store_temp23, 1, 2),
|
show_temp23, store_temp23, 1, 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Note: The bitmask for the beep enable/disable is different than
|
||||||
|
the bitmask for the alarm. */
|
||||||
|
static struct sensor_device_attribute sda_temp_beep[] = {
|
||||||
|
SENSOR_ATTR(temp1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 4),
|
||||||
|
SENSOR_ATTR(temp2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 5),
|
||||||
|
SENSOR_ATTR(temp3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sensor_device_attribute sda_temp_alarm[] = {
|
||||||
|
SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4),
|
||||||
|
SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5),
|
||||||
|
SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
|
||||||
|
};
|
||||||
|
|
||||||
/* get reatime status of all sensors items: voltage, temp, fan */
|
/* get reatime status of all sensors items: voltage, temp, fan */
|
||||||
static ssize_t show_alarms_reg(struct device *dev,
|
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);
|
||||||
#define IN_UNIT_ATTRS(X) \
|
#define IN_UNIT_ATTRS(X) \
|
||||||
&sda_in_input[X].dev_attr.attr, \
|
&sda_in_input[X].dev_attr.attr, \
|
||||||
&sda_in_min[X].dev_attr.attr, \
|
&sda_in_min[X].dev_attr.attr, \
|
||||||
&sda_in_max[X].dev_attr.attr
|
&sda_in_max[X].dev_attr.attr, \
|
||||||
|
&sda_in_beep[X].dev_attr.attr, \
|
||||||
|
&sda_in_alarm[X].dev_attr.attr
|
||||||
|
|
||||||
#define FAN_UNIT_ATTRS(X) \
|
#define FAN_UNIT_ATTRS(X) \
|
||||||
&sda_fan_input[X].dev_attr.attr, \
|
&sda_fan_input[X].dev_attr.attr, \
|
||||||
&sda_fan_min[X].dev_attr.attr, \
|
&sda_fan_min[X].dev_attr.attr, \
|
||||||
&sda_fan_div[X].dev_attr.attr
|
&sda_fan_div[X].dev_attr.attr, \
|
||||||
|
&sda_fan_beep[X].dev_attr.attr, \
|
||||||
|
&sda_fan_alarm[X].dev_attr.attr
|
||||||
|
|
||||||
#define TEMP_UNIT_ATTRS(X) \
|
#define TEMP_UNIT_ATTRS(X) \
|
||||||
&sda_temp_input[X].dev_attr.attr, \
|
&sda_temp_input[X].dev_attr.attr, \
|
||||||
&sda_temp_max[X].dev_attr.attr, \
|
&sda_temp_max[X].dev_attr.attr, \
|
||||||
&sda_temp_max_hyst[X].dev_attr.attr
|
&sda_temp_max_hyst[X].dev_attr.attr, \
|
||||||
|
&sda_temp_beep[X].dev_attr.attr, \
|
||||||
|
&sda_temp_alarm[X].dev_attr.attr
|
||||||
|
|
||||||
static struct attribute *w83791d_attributes[] = {
|
static struct attribute *w83791d_attributes[] = {
|
||||||
IN_UNIT_ATTRS(0),
|
IN_UNIT_ATTRS(0),
|
||||||
|
|
Loading…
Reference in New Issue