On Tue, Jun 14, 2022 at 11:38:54AM +0200, Mårten Lindahl wrote: > 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@xxxxxxxx> Applied to hwmon-next. Thanks, Guenter > --- > drivers/hwmon/pmbus/pmbus_core.c | 78 +++++++++++++++++++++++++------- > 1 file changed, 61 insertions(+), 17 deletions(-) > > diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c > index 02912022853d..5e0d16512fa6 100644 > --- a/drivers/hwmon/pmbus/pmbus_core.c > +++ b/drivers/hwmon/pmbus/pmbus_core.c > @@ -104,6 +104,9 @@ struct pmbus_data { > > s16 currpage; /* current page, -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 { > @@ -2636,6 +2639,58 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned > 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) > { > struct device *dev = rdev_get_dev(rdev); > @@ -2671,24 +2726,13 @@ static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv, > > *selector = 0; > > - if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MIN)) > - s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MIN); > - if (s.data < 0) { > - 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); > + low = pmbus_regulator_get_low_margin(client, s.page); > + if (low < 0) > + return low; > > - s.data = -1; > - if (pmbus_check_word_register(client, s.page, PMBUS_MFR_VOUT_MAX)) > - s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_MFR_VOUT_MAX); > - 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); > + high = pmbus_regulator_get_high_margin(client, s.page); > + if (high < 0) > + return high; > > /* Make sure we are within margins */ > if (low > val)