diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h index ceb71f7b91ac6a59e5db8cbc9c774ccef8c76cbc..9973d265b28f2bf218841e1972bb0988e470956a 100644 --- a/drivers/hwmon/pmbus/pmbus.h +++ b/drivers/hwmon/pmbus/pmbus.h @@ -125,6 +125,42 @@ #define PMBUS_MFR_DATE 0x9D #define PMBUS_MFR_SERIAL 0x9E +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading returns zero (used for detection), + * writing any value causes the associated history to be reset. + */ +#define PMBUS_VIRT_BASE 0x100 +#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 0) +#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 1) +#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 2) +#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 3) +#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 4) +#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 5) +#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 6) +#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 7) +#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 8) +#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 9) +#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 10) +#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 11) +#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 12) +#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 13) +#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 14) +#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 15) +#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 16) +#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 17) +#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 18) +#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 19) +#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 20) +#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 21) + /* * CAPABILITY */ diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index df3971f6414c8eb948137026c2712f884fa78af9..9baf119b64dbb1cd6a643a01e42393d584dc71fe 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -33,14 +33,18 @@ /* * Constants needed to determine number of sensors, booleans, and labels. */ -#define PMBUS_MAX_INPUT_SENSORS 11 /* 6*volt, 3*curr, 2*power */ -#define PMBUS_VOUT_SENSORS_PER_PAGE 5 /* input, min, max, lcrit, - crit */ -#define PMBUS_IOUT_SENSORS_PER_PAGE 4 /* input, min, max, crit */ +#define PMBUS_MAX_INPUT_SENSORS 22 /* 10*volt, 7*curr, 5*power */ +#define PMBUS_VOUT_SENSORS_PER_PAGE 9 /* input, min, max, lcrit, + crit, lowest, highest, avg, + reset */ +#define PMBUS_IOUT_SENSORS_PER_PAGE 8 /* input, min, max, crit, + lowest, highest, avg, + reset */ #define PMBUS_POUT_SENSORS_PER_PAGE 4 /* input, cap, max, crit */ #define PMBUS_MAX_SENSORS_PER_FAN 1 /* input */ -#define PMBUS_MAX_SENSORS_PER_TEMP 5 /* input, min, max, lcrit, - crit */ +#define PMBUS_MAX_SENSORS_PER_TEMP 8 /* input, min, max, lcrit, + crit, lowest, highest, + reset */ #define PMBUS_MAX_INPUT_BOOLEANS 7 /* v: min_alarm, max_alarm, lcrit_alarm, crit_alarm; @@ -80,7 +84,7 @@ struct pmbus_sensor { char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */ struct sensor_device_attribute attribute; u8 page; /* page number */ - u8 reg; /* register */ + u16 reg; /* register */ enum pmbus_sensor_classes class; /* sensor class */ bool update; /* runtime sensor update needed */ int data; /* Sensor data. @@ -237,6 +241,8 @@ static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg) if (status != -ENODATA) return status; } + if (reg >= PMBUS_VIRT_BASE) + return -EINVAL; return pmbus_read_word_data(client, page, reg); } @@ -318,7 +324,7 @@ bool pmbus_check_word_register(struct i2c_client *client, int page, int reg) int rv; struct pmbus_data *data = i2c_get_clientdata(client); - rv = pmbus_read_word_data(client, page, reg); + rv = _pmbus_read_word_data(client, page, reg); if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) rv = pmbus_check_status_cml(client); pmbus_clear_fault_page(client, -1); @@ -951,7 +957,8 @@ static void pmbus_find_max_attr(struct i2c_client *client, * and its associated alarm attribute. */ struct pmbus_limit_attr { - u8 reg; /* Limit register */ + u16 reg; /* Limit register */ + bool update; /* True if register needs updates */ const char *attr; /* Attribute name */ const char *alarm; /* Alarm attribute name */ u32 sbit; /* Alarm attribute status bit */ @@ -996,9 +1003,10 @@ static bool pmbus_add_limit_attrs(struct i2c_client *client, 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->reg, attr->class, + attr->update || l->update, false); - if (info->func[page] & attr->sfunc) { + if (l->sbit && (info->func[page] & attr->sfunc)) { if (attr->compare) { pmbus_add_boolean_cmp(data, name, l->alarm, index, @@ -1094,6 +1102,21 @@ static const struct pmbus_limit_attr vin_limit_attrs[] = { .attr = "crit", .alarm = "crit_alarm", .sbit = PB_VOLTAGE_OV_FAULT, + }, { + .reg = PMBUS_VIRT_READ_VIN_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_VIN_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_VIN_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_VIN_HISTORY, + .attr = "reset_history", }, }; @@ -1118,6 +1141,21 @@ static const struct pmbus_limit_attr vout_limit_attrs[] = { .attr = "crit", .alarm = "crit_alarm", .sbit = PB_VOLTAGE_OV_FAULT, + }, { + .reg = PMBUS_VIRT_READ_VOUT_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_VOUT_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_VOUT_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_VOUT_HISTORY, + .attr = "reset_history", } }; @@ -1164,6 +1202,21 @@ static const struct pmbus_limit_attr iin_limit_attrs[] = { .attr = "crit", .alarm = "crit_alarm", .sbit = PB_IIN_OC_FAULT, + }, { + .reg = PMBUS_VIRT_READ_IIN_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_IIN_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_IIN_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_IIN_HISTORY, + .attr = "reset_history", } }; @@ -1183,6 +1236,21 @@ static const struct pmbus_limit_attr iout_limit_attrs[] = { .attr = "crit", .alarm = "crit_alarm", .sbit = PB_IOUT_OC_FAULT, + }, { + .reg = PMBUS_VIRT_READ_IOUT_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_IOUT_MIN, + .update = true, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_IOUT_MAX, + .update = true, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_IOUT_HISTORY, + .attr = "reset_history", } }; @@ -1218,6 +1286,17 @@ static const struct pmbus_limit_attr pin_limit_attrs[] = { .attr = "max", .alarm = "alarm", .sbit = PB_PIN_OP_WARNING, + }, { + .reg = PMBUS_VIRT_READ_PIN_AVG, + .update = true, + .attr = "average", + }, { + .reg = PMBUS_VIRT_READ_PIN_MAX, + .update = true, + .attr = "input_highest", + }, { + .reg = PMBUS_VIRT_RESET_PIN_HISTORY, + .attr = "reset_history", } }; @@ -1266,6 +1345,39 @@ static const struct pmbus_sensor_attr power_attributes[] = { /* Temperature atributes */ static const struct pmbus_limit_attr temp_limit_attrs[] = { + { + .reg = PMBUS_UT_WARN_LIMIT, + .attr = "min", + .alarm = "min_alarm", + .sbit = PB_TEMP_UT_WARNING, + }, { + .reg = PMBUS_UT_FAULT_LIMIT, + .attr = "lcrit", + .alarm = "lcrit_alarm", + .sbit = PB_TEMP_UT_FAULT, + }, { + .reg = PMBUS_OT_WARN_LIMIT, + .attr = "max", + .alarm = "max_alarm", + .sbit = PB_TEMP_OT_WARNING, + }, { + .reg = PMBUS_OT_FAULT_LIMIT, + .attr = "crit", + .alarm = "crit_alarm", + .sbit = PB_TEMP_OT_FAULT, + }, { + .reg = PMBUS_VIRT_READ_TEMP_MIN, + .attr = "lowest", + }, { + .reg = PMBUS_VIRT_READ_TEMP_MAX, + .attr = "highest", + }, { + .reg = PMBUS_VIRT_RESET_TEMP_HISTORY, + .attr = "reset_history", + } +}; + +static const struct pmbus_limit_attr temp_limit_attrs23[] = { { .reg = PMBUS_UT_WARN_LIMIT, .attr = "min", @@ -1312,8 +1424,8 @@ static const struct pmbus_sensor_attr temp_attributes[] = { .sfunc = PMBUS_HAVE_STATUS_TEMP, .sbase = PB_STATUS_TEMP_BASE, .gbit = PB_STATUS_TEMPERATURE, - .limit = temp_limit_attrs, - .nlimit = ARRAY_SIZE(temp_limit_attrs), + .limit = temp_limit_attrs23, + .nlimit = ARRAY_SIZE(temp_limit_attrs23), }, { .reg = PMBUS_READ_TEMPERATURE_3, .class = PSC_TEMPERATURE, @@ -1324,8 +1436,8 @@ static const struct pmbus_sensor_attr temp_attributes[] = { .sfunc = PMBUS_HAVE_STATUS_TEMP, .sbase = PB_STATUS_TEMP_BASE, .gbit = PB_STATUS_TEMPERATURE, - .limit = temp_limit_attrs, - .nlimit = ARRAY_SIZE(temp_limit_attrs), + .limit = temp_limit_attrs23, + .nlimit = ARRAY_SIZE(temp_limit_attrs23), } };