On Tue, May 03, 2022 at 12:46:31PM +0200, Mårten Lindahl wrote: > The pmbus core does not have operations for getting or setting voltage. > Add functions get/set voltage for the dynamic regulator framework. > > Signed-off-by: Mårten Lindahl <marten.lindahl@xxxxxxxx> > --- > drivers/hwmon/pmbus/pmbus_core.c | 66 ++++++++++++++++++++++++++++++++ > 1 file changed, 66 insertions(+) > > diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c > index bd143ca0c320..f2cf0439da37 100644 > --- a/drivers/hwmon/pmbus/pmbus_core.c > +++ b/drivers/hwmon/pmbus/pmbus_core.c > @@ -2563,11 +2563,77 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned > return 0; > } > > +static int pmbus_regulator_get_voltage(struct regulator_dev *rdev) > +{ > + struct device *dev = rdev_get_dev(rdev); > + struct i2c_client *client = to_i2c_client(dev->parent); > + struct pmbus_data *data = i2c_get_clientdata(client); > + struct pmbus_sensor s = { > + .page = rdev_get_id(rdev), > + .class = PSC_VOLTAGE_OUT, > + .convert = true, > + }; > + > + s.data = _pmbus_read_word_data(client, s.page, 0xff, PMBUS_READ_VOUT); > + if (s.data < 0) > + return s.data; > + > + return (int)pmbus_reg2data(data, &s) * 1000; /* unit is uV */ > +} > + > +static int pmbus_regulator_set_voltage(struct regulator_dev *rdev, int min_uv, > + int max_uv, unsigned int *selector) Multi-line alignment is off. > +{ > + struct device *dev = rdev_get_dev(rdev); > + struct i2c_client *client = to_i2c_client(dev->parent); > + struct pmbus_data *data = i2c_get_clientdata(client); > + struct pmbus_sensor s = { > + .page = rdev_get_id(rdev), > + .class = PSC_VOLTAGE_OUT, > + .convert = true, > + .data = -1, > + }; > + int val = DIV_ROUND_CLOSEST(min_uv, 1000); /* convert to mV */ > + int low, high; There should be an empty line here. Interesting, checkpatch doesn't complain. No need to resend, I'll apply and fix it up. Thanks, Guenter > + *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); > + 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); > + > + /* Make sure we are within margins */ > + if (low > val) > + val = low; > + if (high < val) > + val = high; > + > + val = pmbus_data2reg(data, &s, val); > + > + return _pmbus_write_word_data(client, s.page, PMBUS_VOUT_COMMAND, (u16)val); > +} > + > const struct regulator_ops pmbus_regulator_ops = { > .enable = pmbus_regulator_enable, > .disable = pmbus_regulator_disable, > .is_enabled = pmbus_regulator_is_enabled, > .get_error_flags = pmbus_regulator_get_error_flags, > + .get_voltage = pmbus_regulator_get_voltage, > + .set_voltage = pmbus_regulator_set_voltage, > }; > EXPORT_SYMBOL_NS_GPL(pmbus_regulator_ops, PMBUS); >