aboutsummaryrefslogtreecommitdiff
path: root/drivers/hwmon/pmbus/pmbus_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/pmbus/pmbus_core.c')
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c161
1 files changed, 74 insertions, 87 deletions
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 0f51cd66ecf..d1792d7195b 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -98,7 +98,11 @@ struct pmbus_sensor {
struct pmbus_boolean {
char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */
struct sensor_device_attribute attribute;
+ struct pmbus_sensor *s1;
+ struct pmbus_sensor *s2;
};
+#define to_pmbus_boolean(_attr) \
+ container_of(_attr, struct pmbus_boolean, attribute)
struct pmbus_label {
char name[PMBUS_NAME_SIZE]; /* sysfs label name */
@@ -673,25 +677,20 @@ static u16 pmbus_data2reg(struct pmbus_data *data,
/*
* Return boolean calculated from converted data.
- * <index> defines a status register index and mask, and optionally
- * two sensor indexes.
- * The upper half-word references the two sensors,
- * two sensor indices.
- * The upper half-word references the two optional sensors,
- * the lower half word references status register and mask.
- * The function returns true if (status[reg] & mask) is true and,
- * if specified, if v1 >= v2.
- * To determine if an object exceeds upper limits, specify <v, limit>.
- * To determine if an object exceeds lower limits, specify <limit, v>.
+ * <index> defines a status register index and mask.
+ * The mask is in the lower 8 bits, the register index is in bits 8..23.
*
- * For booleans created with pmbus_add_boolean_reg(), only the lower 16 bits of
- * index are set. s1 and s2 (the sensor index values) are zero in this case.
- * The function returns true if (status[reg] & mask) is true.
+ * The associated pmbus_boolean structure contains optional pointers to two
+ * sensor attributes. If specified, those attributes are compared against each
+ * other to determine if a limit has been exceeded.
*
- * If the boolean was created with pmbus_add_boolean_cmp(), a comparison against
- * a specified limit has to be performed to determine the boolean result.
+ * If the sensor attribute pointers are NULL, the function returns true if
+ * (status[reg] & mask) is true.
+ *
+ * If sensor attribute pointers are provided, a comparison against a specified
+ * limit has to be performed to determine the boolean result.
* In this case, the function returns true if v1 >= v2 (where v1 and v2 are
- * sensor values referenced by sensor indices s1 and s2).
+ * sensor values referenced by sensor attribute pointers s1 and s2).
*
* To determine if an object exceeds upper limits, specify <s1,s2> = <v,limit>.
* To determine if an object exceeds lower limits, specify <s1,s2> = <limit,v>.
@@ -699,11 +698,12 @@ static u16 pmbus_data2reg(struct pmbus_data *data,
* If a negative value is stored in any of the referenced registers, this value
* reflects an error code which will be returned.
*/
-static int pmbus_get_boolean(struct pmbus_data *data, int index)
+static int pmbus_get_boolean(struct pmbus_data *data, struct pmbus_boolean *b,
+ int index)
{
- u8 s1 = (index >> 24) & 0xff;
- u8 s2 = (index >> 16) & 0xff;
- u8 reg = (index >> 8) & 0xff;
+ struct pmbus_sensor *s1 = b->s1;
+ struct pmbus_sensor *s2 = b->s2;
+ u16 reg = (index >> 8) & 0xffff;
u8 mask = index & 0xff;
int ret, status;
u8 regval;
@@ -713,21 +713,21 @@ static int pmbus_get_boolean(struct pmbus_data *data, int index)
return status;
regval = status & mask;
- if (!s1 && !s2)
+ if (!s1 && !s2) {
ret = !!regval;
- else {
+ } else if (!s1 || !s2) {
+ BUG();
+ return 0;
+ } else {
long v1, v2;
- struct pmbus_sensor *sensor1, *sensor2;
- sensor1 = &data->sensors[s1];
- if (sensor1->data < 0)
- return sensor1->data;
- sensor2 = &data->sensors[s2];
- if (sensor2->data < 0)
- return sensor2->data;
+ if (s1->data < 0)
+ return s1->data;
+ if (s2->data < 0)
+ return s2->data;
- v1 = pmbus_reg2data(data, sensor1);
- v2 = pmbus_reg2data(data, sensor2);
+ v1 = pmbus_reg2data(data, s1);
+ v2 = pmbus_reg2data(data, s2);
ret = !!(regval && v1 >= v2);
}
return ret;
@@ -737,10 +737,11 @@ static ssize_t pmbus_show_boolean(struct device *dev,
struct device_attribute *da, char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct pmbus_boolean *boolean = to_pmbus_boolean(attr);
struct pmbus_data *data = pmbus_update_device(dev);
int val;
- val = pmbus_get_boolean(data, attr->index);
+ val = pmbus_get_boolean(data, boolean, attr->index);
if (val < 0)
return val;
return snprintf(buf, PAGE_SIZE, "%d\n", val);
@@ -829,7 +830,9 @@ static void pmbus_attr_init(struct sensor_device_attribute *a,
static int pmbus_add_boolean(struct pmbus_data *data,
const char *name, const char *type, int seq,
- int idx)
+ struct pmbus_sensor *s1,
+ struct pmbus_sensor *s2,
+ u16 reg, u8 mask)
{
struct pmbus_boolean *boolean;
struct sensor_device_attribute *a;
@@ -844,32 +847,20 @@ static int pmbus_add_boolean(struct pmbus_data *data,
snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s",
name, seq, type);
+ boolean->s1 = s1;
+ boolean->s2 = s2;
pmbus_attr_init(a, boolean->name, S_IRUGO, pmbus_show_boolean, NULL,
- idx);
+ (reg << 8) | mask);
data->attributes[data->num_attributes++] = &a->dev_attr.attr;
return 0;
}
-static int pmbus_add_boolean_reg(struct pmbus_data *data,
- const char *name, const char *type,
- int seq, int reg, int bit)
-{
- return pmbus_add_boolean(data, name, type, seq, (reg << 8) | bit);
-}
-
-static int pmbus_add_boolean_cmp(struct pmbus_data *data,
- const char *name, const char *type,
- int seq, int i1, int i2, int reg, int mask)
-{
- return pmbus_add_boolean(data, name, type, seq,
- (i1 << 24) | (i2 << 16) | (reg << 8) | mask);
-}
-
-static void pmbus_add_sensor(struct pmbus_data *data,
- const char *name, const char *type, int seq,
- int page, int reg, enum pmbus_sensor_classes class,
- bool update, bool readonly)
+static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
+ const char *name, const char *type,
+ int seq, int page, int reg,
+ enum pmbus_sensor_classes class,
+ bool update, bool readonly)
{
struct pmbus_sensor *sensor;
struct sensor_device_attribute *a;
@@ -892,6 +883,8 @@ static void pmbus_add_sensor(struct pmbus_data *data,
data->attributes[data->num_attributes++] = &a->dev_attr.attr;
data->num_sensors++;
+
+ return sensor;
}
static int pmbus_add_label(struct pmbus_data *data,
@@ -1023,38 +1016,31 @@ static int pmbus_add_limit_attrs(struct i2c_client *client,
struct pmbus_data *data,
const struct pmbus_driver_info *info,
const char *name, int index, int page,
- int cbase,
+ struct pmbus_sensor *base,
const struct pmbus_sensor_attr *attr)
{
const struct pmbus_limit_attr *l = attr->limit;
int nlimit = attr->nlimit;
int have_alarm = 0;
- int i, cindex;
- int ret;
+ int i, ret;
+ struct pmbus_sensor *curr;
for (i = 0; i < nlimit; i++) {
if (pmbus_check_word_register(client, page, l->reg)) {
- cindex = data->num_sensors;
- pmbus_add_sensor(data, name, l->attr, index, page,
- l->reg, attr->class,
- attr->update || l->update,
- false);
+ curr = pmbus_add_sensor(data, name, l->attr, index,
+ page, l->reg, attr->class,
+ attr->update || l->update,
+ false);
if (l->sbit && (info->func[page] & attr->sfunc)) {
- if (attr->compare) {
- ret = pmbus_add_boolean_cmp(data, name,
- l->alarm, index,
- l->low ? cindex : cbase,
- l->low ? cbase : cindex,
- attr->sbase + page, l->sbit);
- if (ret)
- return ret;
- } else {
- ret = pmbus_add_boolean_reg(data, name,
- l->alarm, index,
- attr->sbase + page, l->sbit);
- if (ret)
- return ret;
- }
+ ret = pmbus_add_boolean(data, name,
+ l->alarm, index,
+ attr->compare ? l->low ? curr : base
+ : NULL,
+ attr->compare ? l->low ? base : curr
+ : NULL,
+ attr->sbase + page, l->sbit);
+ if (ret)
+ return ret;
have_alarm = 1;
}
}
@@ -1070,7 +1056,7 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
int index, int page,
const struct pmbus_sensor_attr *attr)
{
- int cbase = data->num_sensors;
+ struct pmbus_sensor *base;
int ret;
if (attr->label) {
@@ -1079,11 +1065,11 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
if (ret)
return ret;
}
- pmbus_add_sensor(data, name, "input", index, page, attr->reg,
- attr->class, true, true);
+ base = pmbus_add_sensor(data, name, "input", index, page, attr->reg,
+ attr->class, true, true);
if (attr->sfunc) {
ret = pmbus_add_limit_attrs(client, data, info, name,
- index, page, cbase, attr);
+ index, page, base, attr);
if (ret < 0)
return ret;
/*
@@ -1094,9 +1080,10 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
if (!ret && attr->gbit &&
pmbus_check_byte_register(client, page,
PMBUS_STATUS_BYTE)) {
- ret = pmbus_add_boolean_reg(data, name, "alarm", index,
- PB_STATUS_BASE + page,
- attr->gbit);
+ ret = pmbus_add_boolean(data, name, "alarm", index,
+ NULL, NULL,
+ PB_STATUS_BASE + page,
+ attr->gbit);
if (ret)
return ret;
}
@@ -1635,13 +1622,13 @@ static int pmbus_add_fan_attributes(struct i2c_client *client,
base = PB_STATUS_FAN34_BASE + page;
else
base = PB_STATUS_FAN_BASE + page;
- ret = pmbus_add_boolean_reg(data, "fan",
- "alarm", index, base,
+ ret = pmbus_add_boolean(data, "fan",
+ "alarm", index, NULL, NULL, base,
PB_FAN_FAN1_WARNING >> (f & 1));
if (ret)
return ret;
- ret = pmbus_add_boolean_reg(data, "fan",
- "fault", index, base,
+ ret = pmbus_add_boolean(data, "fan",
+ "fault", index, NULL, NULL, base,
PB_FAN_FAN1_FAULT >> (f & 1));
if (ret)
return ret;