hwmon: (max6650) Add support for alarms

Export the alarm flags provided by the MAX6650/MAX6651 fan-speed regulator
and monitor chips via sysfs.

Signed-off-by: Christian Engelmayer <christian.engelmayer@frequentis.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
This commit is contained in:
Christian Engelmayer 2009-06-15 18:39:52 +02:00 committed by Jean Delvare
parent 09475d32e6
commit 52b5226f48
1 changed files with 85 additions and 1 deletions

View File

@ -12,7 +12,7 @@
* also work with the MAX6651. It does not distinguish max6650 and max6651
* chips.
*
* Tha datasheet was last seen at:
* The datasheet was last seen at:
*
* http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf
*
@ -98,6 +98,16 @@ I2C_CLIENT_INSMOD_1(max6650);
#define MAX6650_CFG_MODE_OPEN_LOOP 0x30
#define MAX6650_COUNT_MASK 0x03
/*
* Alarm status register bits
*/
#define MAX6650_ALRM_MAX 0x01
#define MAX6650_ALRM_MIN 0x02
#define MAX6650_ALRM_TACH 0x04
#define MAX6650_ALRM_GPIO1 0x08
#define MAX6650_ALRM_GPIO2 0x10
/* Minimum and maximum values of the FAN-RPM */
#define FAN_RPM_MIN 240
#define FAN_RPM_MAX 30000
@ -151,6 +161,7 @@ struct max6650_data
u8 tach[4];
u8 count;
u8 dac;
u8 alarm;
};
static ssize_t get_fan(struct device *dev, struct device_attribute *devattr,
@ -418,6 +429,33 @@ static ssize_t set_div(struct device *dev, struct device_attribute *devattr,
return count;
}
/*
* Get alarm stati:
* Possible values:
* 0 = no alarm
* 1 = alarm
*/
static ssize_t get_alarm(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct max6650_data *data = max6650_update_device(dev);
struct i2c_client *client = to_i2c_client(dev);
int alarm = 0;
if (data->alarm & attr->index) {
mutex_lock(&data->update_lock);
alarm = 1;
data->alarm &= ~attr->index;
data->alarm |= i2c_smbus_read_byte_data(client,
MAX6650_REG_ALARM);
mutex_unlock(&data->update_lock);
}
return sprintf(buf, "%d\n", alarm);
}
static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0);
static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1);
static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2);
@ -426,7 +464,41 @@ static DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, get_target, set_target);
static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, get_div, set_div);
static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, get_enable, set_enable);
static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm);
static SENSOR_DEVICE_ATTR(fan1_max_alarm, S_IRUGO, get_alarm, NULL,
MAX6650_ALRM_MAX);
static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, get_alarm, NULL,
MAX6650_ALRM_MIN);
static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_alarm, NULL,
MAX6650_ALRM_TACH);
static SENSOR_DEVICE_ATTR(gpio1_alarm, S_IRUGO, get_alarm, NULL,
MAX6650_ALRM_GPIO1);
static SENSOR_DEVICE_ATTR(gpio2_alarm, S_IRUGO, get_alarm, NULL,
MAX6650_ALRM_GPIO2);
static mode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a,
int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct i2c_client *client = to_i2c_client(dev);
u8 alarm_en = i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN);
struct device_attribute *devattr;
/*
* Hide the alarms that have not been enabled by the firmware
*/
devattr = container_of(a, struct device_attribute, attr);
if (devattr == &sensor_dev_attr_fan1_max_alarm.dev_attr
|| devattr == &sensor_dev_attr_fan1_min_alarm.dev_attr
|| devattr == &sensor_dev_attr_fan1_fault.dev_attr
|| devattr == &sensor_dev_attr_gpio1_alarm.dev_attr
|| devattr == &sensor_dev_attr_gpio2_alarm.dev_attr) {
if (!(alarm_en & to_sensor_dev_attr(devattr)->index))
return 0;
}
return a->mode;
}
static struct attribute *max6650_attrs[] = {
&sensor_dev_attr_fan1_input.dev_attr.attr,
@ -437,11 +509,17 @@ static struct attribute *max6650_attrs[] = {
&dev_attr_fan1_div.attr,
&dev_attr_pwm1_enable.attr,
&dev_attr_pwm1.attr,
&sensor_dev_attr_fan1_max_alarm.dev_attr.attr,
&sensor_dev_attr_fan1_min_alarm.dev_attr.attr,
&sensor_dev_attr_fan1_fault.dev_attr.attr,
&sensor_dev_attr_gpio1_alarm.dev_attr.attr,
&sensor_dev_attr_gpio2_alarm.dev_attr.attr,
NULL
};
static struct attribute_group max6650_attr_grp = {
.attrs = max6650_attrs,
.is_visible = max6650_attrs_visible,
};
/*
@ -659,6 +737,12 @@ static struct max6650_data *max6650_update_device(struct device *dev)
MAX6650_REG_COUNT);
data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC);
/* Alarms are cleared on read in case the condition that
* caused the alarm is removed. Keep the value latched here
* for providing the register through different alarm files. */
data->alarm |= i2c_smbus_read_byte_data(client,
MAX6650_REG_ALARM);
data->last_updated = jiffies;
data->valid = 1;
}