Re: [PATCH v5 2/4] hwmon: (pmbus/max20830): add VOUT feedback resistor scaling support

From: Guenter Roeck

Date: Wed Jul 29 2026 - 22:45:28 EST


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 <alexisczezar.torreno@xxxxxxxxxx>

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[] = {