Commit 6948708d authored by Guenter Roeck's avatar Guenter Roeck Committed by Jean Delvare

hwmon: (lm90) Add support for extra features of max6659

Signed-off-by: default avatarGuenter Roeck <guenter.roeck@ericsson.com>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 13c84951
...@@ -101,10 +101,11 @@ well as the temperature of up to one external diode. It is compatible ...@@ -101,10 +101,11 @@ well as the temperature of up to one external diode. It is compatible
with many other devices, many of which are supported by this driver. with many other devices, many of which are supported by this driver.
Note that there is no easy way to differentiate between the MAX6657, Note that there is no easy way to differentiate between the MAX6657,
MAX6658 and MAX6659 variants. The extra address and features of the MAX6658 and MAX6659 variants. The extra features of the MAX6659 are only
MAX6659 are not supported by this driver. The MAX6680 and MAX6681 only supported by this driver if the chip is located at address 0x4d or 0x4e,
differ in their pinout, therefore they obviously can't (and don't need to) or if the chip type is explicitly selected as max6659.
be distinguished. The MAX6680 and MAX6681 only differ in their pinout, therefore they obviously
can't (and don't need to) be distinguished.
The specificity of this family of chipsets over the ADM1021/LM84 The specificity of this family of chipsets over the ADM1021/LM84
family is that it features critical limits with hysteresis, and an family is that it features critical limits with hysteresis, and an
......
...@@ -28,9 +28,11 @@ ...@@ -28,9 +28,11 @@
* This driver also supports the MAX6657, MAX6658 and MAX6659 sensor * This driver also supports the MAX6657, MAX6658 and MAX6659 sensor
* chips made by Maxim. These chips are similar to the LM86. * chips made by Maxim. These chips are similar to the LM86.
* Note that there is no easy way to differentiate between the three * Note that there is no easy way to differentiate between the three
* variants. The extra address and features of the MAX6659 are not * variants. We use the device address to detect MAX6659, which will result
* supported by this driver. These chips lack the remote temperature * in a detection as max6657 if it is on address 0x4c. The extra address
* offset feature. * and features of the MAX6659 are only supported if the chip is configured
* explicitly as max6659, or if its address is not 0x4c.
* These chips lack the remote temperature offset feature.
* *
* This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and
* MAX6692 chips made by Maxim. These are again similar to the LM86, * MAX6692 chips made by Maxim. These are again similar to the LM86,
...@@ -138,6 +140,10 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, ...@@ -138,6 +140,10 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
/* MAX6646/6647/6649/6657/6658/6659 registers */ /* MAX6646/6647/6649/6657/6658/6659 registers */
#define MAX6657_REG_R_LOCAL_TEMPL 0x11 #define MAX6657_REG_R_LOCAL_TEMPL 0x11
#define MAX6659_REG_R_REMOTE_EMERG 0x16
#define MAX6659_REG_W_REMOTE_EMERG 0x16
#define MAX6659_REG_R_LOCAL_EMERG 0x17
#define MAX6659_REG_W_LOCAL_EMERG 0x17
/* /*
* Device flags * Device flags
...@@ -147,6 +153,7 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, ...@@ -147,6 +153,7 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
#define LM90_HAVE_OFFSET (1 << 1) /* temperature offset register */ #define LM90_HAVE_OFFSET (1 << 1) /* temperature offset register */
#define LM90_HAVE_LOCAL_EXT (1 << 2) /* extended local temperature */ #define LM90_HAVE_LOCAL_EXT (1 << 2) /* extended local temperature */
#define LM90_HAVE_REM_LIMIT_EXT (1 << 3) /* extended remote limit */ #define LM90_HAVE_REM_LIMIT_EXT (1 << 3) /* extended remote limit */
#define LM90_HAVE_EMERGENCY (1 << 4) /* 3rd upper (emergency) limit */
/* /*
* Functions declaration * Functions declaration
...@@ -213,10 +220,12 @@ struct lm90_data { ...@@ -213,10 +220,12 @@ struct lm90_data {
u8 alert_alarms; /* Which alarm bits trigger ALERT# */ u8 alert_alarms; /* Which alarm bits trigger ALERT# */
/* registers values */ /* registers values */
s8 temp8[4]; /* 0: local low limit s8 temp8[6]; /* 0: local low limit
1: local high limit 1: local high limit
2: local critical limit 2: local critical limit
3: remote critical limit */ 3: remote critical limit
4: local emergency limit (max6659 only)
5: remote emergency limit (max6659 only) */
s16 temp11[5]; /* 0: remote input s16 temp11[5]; /* 0: remote input
1: remote low limit 1: remote low limit
2: remote high limit 2: remote high limit
...@@ -381,11 +390,13 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr, ...@@ -381,11 +390,13 @@ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
static const u8 reg[4] = { static const u8 reg[6] = {
LM90_REG_W_LOCAL_LOW, LM90_REG_W_LOCAL_LOW,
LM90_REG_W_LOCAL_HIGH, LM90_REG_W_LOCAL_HIGH,
LM90_REG_W_LOCAL_CRIT, LM90_REG_W_LOCAL_CRIT,
LM90_REG_W_REMOTE_CRIT, LM90_REG_W_REMOTE_CRIT,
MAX6659_REG_W_LOCAL_EMERG,
MAX6659_REG_W_REMOTE_EMERG,
}; };
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
...@@ -608,6 +619,30 @@ static const struct attribute_group lm90_group = { ...@@ -608,6 +619,30 @@ static const struct attribute_group lm90_group = {
.attrs = lm90_attributes, .attrs = lm90_attributes,
}; };
/*
* Additional attributes for devices with emergency sensors
*/
static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO, show_temp8,
set_temp8, 4);
static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO, show_temp8,
set_temp8, 5);
static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO, show_temphyst,
NULL, 4);
static SENSOR_DEVICE_ATTR(temp2_emergency_hyst, S_IRUGO, show_temphyst,
NULL, 5);
static struct attribute *lm90_emergency_attributes[] = {
&sensor_dev_attr_temp1_emergency.dev_attr.attr,
&sensor_dev_attr_temp2_emergency.dev_attr.attr,
&sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr,
&sensor_dev_attr_temp2_emergency_hyst.dev_attr.attr,
NULL
};
static const struct attribute_group lm90_emergency_group = {
.attrs = lm90_emergency_attributes,
};
/* pec used for ADM1032 only */ /* pec used for ADM1032 only */
static ssize_t show_pec(struct device *dev, struct device_attribute *dummy, static ssize_t show_pec(struct device *dev, struct device_attribute *dummy,
char *buf) char *buf)
...@@ -826,6 +861,9 @@ static int lm90_detect(struct i2c_client *new_client, ...@@ -826,6 +861,9 @@ static int lm90_detect(struct i2c_client *new_client,
static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data) static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data)
{ {
if (data->flags & LM90_HAVE_EMERGENCY)
sysfs_remove_group(&client->dev.kobj,
&lm90_emergency_group);
if (data->flags & LM90_HAVE_OFFSET) if (data->flags & LM90_HAVE_OFFSET)
device_remove_file(&client->dev, device_remove_file(&client->dev,
&sensor_dev_attr_temp2_offset.dev_attr); &sensor_dev_attr_temp2_offset.dev_attr);
...@@ -881,6 +919,9 @@ static int lm90_probe(struct i2c_client *new_client, ...@@ -881,6 +919,9 @@ static int lm90_probe(struct i2c_client *new_client,
&& data->kind != max6646 && data->kind != max6680) && data->kind != max6646 && data->kind != max6680)
data->flags |= LM90_HAVE_REM_LIMIT_EXT; data->flags |= LM90_HAVE_REM_LIMIT_EXT;
if (data->kind == max6659)
data->flags |= LM90_HAVE_EMERGENCY;
/* Initialize the LM90 chip */ /* Initialize the LM90 chip */
lm90_init_client(new_client); lm90_init_client(new_client);
...@@ -899,6 +940,12 @@ static int lm90_probe(struct i2c_client *new_client, ...@@ -899,6 +940,12 @@ static int lm90_probe(struct i2c_client *new_client,
if (err) if (err)
goto exit_remove_files; goto exit_remove_files;
} }
if (data->flags & LM90_HAVE_EMERGENCY) {
err = sysfs_create_group(&new_client->dev.kobj,
&lm90_emergency_group);
if (err)
goto exit_remove_files;
}
data->hwmon_dev = hwmon_device_register(&new_client->dev); data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) { if (IS_ERR(data->hwmon_dev)) {
...@@ -1082,6 +1129,12 @@ static struct lm90_data *lm90_update_device(struct device *dev) ...@@ -1082,6 +1129,12 @@ static struct lm90_data *lm90_update_device(struct device *dev)
&l) == 0) &l) == 0)
data->temp11[3] = (h << 8) | l; data->temp11[3] = (h << 8) | l;
} }
if (data->flags & LM90_HAVE_EMERGENCY) {
lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG,
&data->temp8[4]);
lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG,
&data->temp8[5]);
}
lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms); lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);
/* Re-enable ALERT# output if it was originally enabled and /* Re-enable ALERT# output if it was originally enabled and
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment