hwmon: (pmbus) Introduce and use cached vout margins
When setting a new voltage the voltage boundaries are read every time to check that the new voltage is within the proper range. Checking these voltage boundaries consists of reading one of PMBUS_MFR_VOUT_MIN/ PMBUS_VOUT_MARGIN_LOW registers and then PMBUS_MFR_VOUT_MAX/ PMBUS_VOUT_MARGIN_HIGH together with writing the PMBUS_CLEAR_FAULTS register. Since these boundaries are never being changed, it can be cached and thus saving unnecessary smbus transmissions. Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com> Link: https://lore.kernel.org/r/20220614093856.3470672-2-marten.lindahl@axis.com Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
parent
b674bcb13f
commit
07fb76273d
1 changed files with 61 additions and 17 deletions
|
@ -104,6 +104,9 @@ struct pmbus_data {
|
||||||
|
|
||||||
s16 currpage; /* current page, -1 for unknown/unset */
|
s16 currpage; /* current page, -1 for unknown/unset */
|
||||||
s16 currphase; /* current phase, 0xff for all, -1 for unknown/unset */
|
s16 currphase; /* current phase, 0xff for all, -1 for unknown/unset */
|
||||||
|
|
||||||
|
int vout_low[PMBUS_PAGES]; /* voltage low margin */
|
||||||
|
int vout_high[PMBUS_PAGES]; /* voltage high margin */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pmbus_debugfs_entry {
|
struct pmbus_debugfs_entry {
|
||||||
|
@ -2848,6 +2851,58 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pmbus_regulator_get_low_margin(struct i2c_client *client, int page)
|
||||||
|
{
|
||||||
|
struct pmbus_data *data = i2c_get_clientdata(client);
|
||||||
|
struct pmbus_sensor s = {
|
||||||
|
.page = page,
|
||||||
|
.class = PSC_VOLTAGE_OUT,
|
||||||
|
.convert = true,
|
||||||
|
.data = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!data->vout_low[page]) {
|
||||||
|
if (pmbus_check_word_register(client, page, PMBUS_MFR_VOUT_MIN))
|
||||||
|
s.data = _pmbus_read_word_data(client, page, 0xff,
|
||||||
|
PMBUS_MFR_VOUT_MIN);
|
||||||
|
if (s.data < 0) {
|
||||||
|
s.data = _pmbus_read_word_data(client, page, 0xff,
|
||||||
|
PMBUS_VOUT_MARGIN_LOW);
|
||||||
|
if (s.data < 0)
|
||||||
|
return s.data;
|
||||||
|
}
|
||||||
|
data->vout_low[page] = pmbus_reg2data(data, &s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data->vout_low[page];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pmbus_regulator_get_high_margin(struct i2c_client *client, int page)
|
||||||
|
{
|
||||||
|
struct pmbus_data *data = i2c_get_clientdata(client);
|
||||||
|
struct pmbus_sensor s = {
|
||||||
|
.page = page,
|
||||||
|
.class = PSC_VOLTAGE_OUT,
|
||||||
|
.convert = true,
|
||||||
|
.data = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!data->vout_high[page]) {
|
||||||
|
if (pmbus_check_word_register(client, page, PMBUS_MFR_VOUT_MAX))
|
||||||
|
s.data = _pmbus_read_word_data(client, page, 0xff,
|
||||||
|
PMBUS_MFR_VOUT_MAX);
|
||||||
|
if (s.data < 0) {
|
||||||
|
s.data = _pmbus_read_word_data(client, page, 0xff,
|
||||||
|
PMBUS_VOUT_MARGIN_HIGH);
|
||||||
|
if (s.data < 0)
|
||||||
|
return s.data;
|
||||||
|
}
|
||||||
|
data->vout_high[page] = pmbus_reg2data(data, &s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data->vout_high[page];
|
||||||
|
}
|
||||||
|
|
||||||
static int pmbus_regulator_get_voltage(struct regulator_dev *rdev)
|
static int pmbus_regulator_get_voltage(struct regulator_dev *rdev)
|
||||||
{
|
{
|
||||||
struct device *dev = rdev_get_dev(rdev);
|
struct device *dev = rdev_get_dev(rdev);
|
||||||
|
@ -2883,24 +2938,13 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv,
|
||||||
|
|
||||||
*selector = 0;
|
*selector = 0;
|
||||||
|
|
||||||
if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MIN))
|
low = pmbus_regulator_get_low_margin(client, s.page);
|
||||||
s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MIN);
|
if (low < 0)
|
||||||
if (s.data < 0) {
|
return low;
|
||||||
s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_LOW);
|
|
||||||
if (s.data < 0)
|
|
||||||
return s.data;
|
|
||||||
}
|
|
||||||
low = pmbus_reg2data(data, &s);
|
|
||||||
|
|
||||||
s.data = -1;
|
high = pmbus_regulator_get_high_margin(client, s.page);
|
||||||
if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MAX))
|
if (high < 0)
|
||||||
s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MAX);
|
return high;
|
||||||
if (s.data < 0) {
|
|
||||||
s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_VOUT_MARGIN_HIGH);
|
|
||||||
if (s.data < 0)
|
|
||||||
return s.data;
|
|
||||||
}
|
|
||||||
high = pmbus_reg2data(data, &s);
|
|
||||||
|
|
||||||
/* Make sure we are within margins */
|
/* Make sure we are within margins */
|
||||||
if (low > val)
|
if (low > val)
|
||||||
|
|
Loading…
Add table
Reference in a new issue