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

From: Alexis Czezar Torreno

Date: Mon Jun 29 2026 - 22:48:01 EST


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>
---
drivers/hwmon/pmbus/max20830.c | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)

diff --git a/drivers/hwmon/pmbus/max20830.c b/drivers/hwmon/pmbus/max20830.c
index cb3a39d747edee3aefb0fb4051ef957436b3c15b..a3abd24437e8e7560264aad55fc4f456d30ae235 100644
--- a/drivers/hwmon/pmbus/max20830.c
+++ b/drivers/hwmon/pmbus/max20830.c
@@ -8,6 +8,7 @@
#include <linux/errno.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
+#include <linux/math64.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/string.h>
@@ -15,6 +16,35 @@

#define MAX20830_IC_DEVICE_ID_LENGTH 9

+struct max20830_data {
+ struct pmbus_driver_info info;
+ u32 vout_rfb1;
+ u32 vout_rfb2;
+};
+
+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;
+
+ 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)
+ ret = DIV_ROUND_CLOSEST_ULL((u64)ret * (data->vout_rfb1 +
+ data->vout_rfb2), data->vout_rfb2);
+ return ret;
+ default:
+ return -ENODATA;
+ }
+}
+
static struct pmbus_driver_info max20830_info = {
.pages = 1,
.format[PSC_VOLTAGE_IN] = linear,
@@ -25,14 +55,26 @@ 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;
struct gpio_desc *enable_gpio;
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);
+
enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_HIGH);
if (IS_ERR(enable_gpio))
return dev_err_probe(&client->dev, PTR_ERR(enable_gpio),

--
2.34.1