Re: [PATCH v5 2/4] hwmon: (pmbus/max20830): add VOUT feedback resistor scaling support
Guenter Roeck <[email protected]> Wed, 29 Jul 2026 19:40:52 -0700
| Newsgroups | org.kernel.vger.linux-hwmon,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On Thu, Jul 30, 2026 at 09:03:34AM +0800, Alexis Czezar Torreno wrote: > Implement support for external voltage divider scaling using the > adi,vout-rfb1-ohms and adi,vout-rfb2-ohms device tree properties. > > When the desired output voltage exceeds VREF, a resistor divider > (RFB1 and RFB2) is used to scale down the feedback voltage. The > driver reads these resistor values from device tree and applies > the scaling formula: VOUT_actual = VOUT_measured à (1 + RFB1/RFB2) > > The properties are optional. If not specified, the driver assumes > no voltage divider is present and reports the raw VOUT reading. > > Signed-off-by: Alexis Czezar Torreno <[email protected]> Applied. Thanks, Guenter > --- > drivers/hwmon/pmbus/max20830.c | 65 +++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 64 insertions(+), 1 deletion(-) > > diff --git a/drivers/hwmon/pmbus/max20830.c b/drivers/hwmon/pmbus/max20830.c > index cb2c23672166d641852199ca07eb716924f4f286..ddead72a8db5d6f8491cbfbf356db0f8de64da03 100644 > --- a/drivers/hwmon/pmbus/max20830.c > +++ b/drivers/hwmon/pmbus/max20830.c > @@ -7,6 +7,7 @@ > > #include <linux/errno.h> > #include <linux/i2c.h> > +#include <linux/math64.h> > #include <linux/mod_devicetable.h> > #include <linux/module.h> > #include <linux/string.h> > @@ -14,6 +15,56 @@ > > #define MAX20830_IC_DEVICE_ID_LENGTH 9 > > +struct max20830_data { > + struct pmbus_driver_info info; > + u32 vout_rfb1; > + u32 vout_rfb2; > +}; > + > +/* > + * MAX20830 only supports READ_VOUT for VOUT monitoring. > + * > + * Limit registers (VOUT_OV_WARN_LIMIT, VOUT_OV_FAULT_LIMIT, etc.) are not > + * supported by this driver and return -ENODATA. This means sysfs attributes > + * like in1_max, in1_crit, etc. will not be available. Only in1_input (the > + * scaled output voltage) is supported. > + * > + * MAX20830 uses an external resistor divider for voltage sensing: > + * - VOUT_COMMAND and VOUT_MAX set the reference voltage at the feedback pin > + * - READ_VOUT reports the feedback voltage, which needs to be scaled for actual > + * output voltage > + * > + * Scaling formula: vout_actual = vout_fb à (1 + RFB1 / RFB2) > + * > + * If regulator support is added in the future, some adjustments are needed to > + * ensure correct feedback voltages are set. > + */ > +static int max20830_read_word_data(struct i2c_client *client, int page, > + int phase, int reg) > +{ > + const struct pmbus_driver_info *info = pmbus_get_driver_info(client); > + const struct max20830_data *data = container_of(info, struct max20830_data, info); > + int ret; > + u64 temp; > + > + switch (reg) { > + case PMBUS_READ_VOUT: > + ret = pmbus_read_word_data(client, page, phase, reg); > + if (ret < 0) > + return ret; > + > + /* Apply voltage divider scaling if resistors are non-zero */ > + if (data->vout_rfb1 && data->vout_rfb2) { > + temp = (u64)data->vout_rfb1 + (u64)data->vout_rfb2; > + temp = DIV_ROUND_CLOSEST_ULL((u64)ret * temp, data->vout_rfb2); > + ret = clamp_val(temp, 0, 0xFFFF); > + } > + return ret; > + default: > + return -ENODATA; > + } > +} > + > static struct pmbus_driver_info max20830_info = { > .pages = 1, > .format[PSC_VOLTAGE_IN] = linear, > @@ -24,13 +75,25 @@ static struct pmbus_driver_info max20830_info = { > PMBUS_HAVE_TEMP | > PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT | > PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP, > + .read_word_data = max20830_read_word_data, > }; > > static int max20830_probe(struct i2c_client *client) > { > u8 buf[I2C_SMBUS_BLOCK_MAX + 1] = {}; > + struct max20830_data *data; > int ret; > > + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); > + if (!data) > + return -ENOMEM; > + > + data->info = max20830_info; > + > + /* Read optional voltage divider resistor values */ > + device_property_read_u32(&client->dev, "adi,vout-rfb1-ohms", &data->vout_rfb1); > + device_property_read_u32(&client->dev, "adi,vout-rfb2-ohms", &data->vout_rfb2); > + > if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BLOCK_DATA) && > !i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) > return -ENODEV; > @@ -78,7 +141,7 @@ static int max20830_probe(struct i2c_client *client) > return dev_err_probe(&client->dev, -ENODEV, > "Unsupported device: '%s'\n", buf); > > - return pmbus_do_probe(client, &max20830_info); > + return pmbus_do_probe(client, &data->info); > } > > static const struct i2c_device_id max20830_id[] = {