[PATCH v4 1/4] hwmon: (pmbus) Add and export direct conversion calculation helpers
From: Stoyan Bogdanov
Date: Fri May 22 2026 - 04:25:49 EST
TPS25990 and upcoming TPS1689 need common computation APIs but
the current implementation is static to TPS25990. As a preparation for
TPS1689 support, split the math-only parts of pmbus_reg2data_direct() and
pmbus_data2reg_direct() into separate helper functions:
- pmbus_reg2data_direct_calc()
- pmbus_data2reg_direct_calc()
export them so the upcoming TPS1689 can use the same APIs.
This has no behavioral change on TPS25990 while allowing TPS1689
to use the same.
Signed-off-by: Stoyan Bogdanov <sbogdanov@xxxxxxxxxxxx>
---
drivers/hwmon/pmbus/pmbus.h | 2 ++
drivers/hwmon/pmbus/pmbus_core.c | 59 +++++++++++++++++++-------------
2 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
index 23e3eda58870..dd4fe7d9821d 100644
--- a/drivers/hwmon/pmbus/pmbus.h
+++ b/drivers/hwmon/pmbus/pmbus.h
@@ -578,5 +578,7 @@ DEFINE_GUARD(pmbus_lock, struct i2c_client *, pmbus_lock(_T), pmbus_unlock(_T))
int pmbus_update_fan(struct i2c_client *client, int page, int id,
u8 config, u8 mask, u16 command);
struct dentry *pmbus_get_debugfs_dir(struct i2c_client *client);
+s64 pmbus_reg2data_direct_calc(s64 val, s64 b, s32 m, s32 R);
+u16 pmbus_data2reg_direct_calc(s64 val, s64 b, s32 m, s32 R);
#endif /* PMBUS_H */
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index e8fdd799c71c..2eaac337eeab 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -817,6 +817,22 @@ static s64 pmbus_reg2data_linear(struct pmbus_data *data,
return val;
}
+s64 pmbus_reg2data_direct_calc(s64 val, s64 b, s32 m, s32 R)
+{
+ while (R > 0) {
+ val *= 10;
+ R--;
+ }
+ while (R < 0) {
+ val = div_s64(val + 5LL, 10L); /* round closest */
+ R++;
+ }
+
+ val = div_s64(val - b, m);
+ return val;
+}
+EXPORT_SYMBOL_NS_GPL(pmbus_reg2data_direct_calc, "PMBUS");
+
/*
* Convert direct sensor values to milli- or micro-units
* depending on sensor type.
@@ -824,7 +840,7 @@ static s64 pmbus_reg2data_linear(struct pmbus_data *data,
static s64 pmbus_reg2data_direct(struct pmbus_data *data,
struct pmbus_sensor *sensor)
{
- s64 b, val = (s16)sensor->data;
+ s64 b;
s32 m, R;
m = data->info->m[sensor->class];
@@ -848,17 +864,7 @@ static s64 pmbus_reg2data_direct(struct pmbus_data *data,
b *= 1000;
}
- while (R > 0) {
- val *= 10;
- R--;
- }
- while (R < 0) {
- val = div_s64(val + 5LL, 10L); /* round closest */
- R++;
- }
-
- val = div_s64(val - b, m);
- return val;
+ return pmbus_reg2data_direct_calc((s16)sensor->data, b, m, R);
}
/*
@@ -1057,6 +1063,23 @@ static u16 pmbus_data2reg_linear(struct pmbus_data *data,
return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
}
+u16 pmbus_data2reg_direct_calc(s64 val, s64 b, s32 m, s32 R)
+{
+ val = val * m + b;
+
+ while (R > 0) {
+ val *= 10;
+ R--;
+ }
+ while (R < 0) {
+ val = div_s64(val + 5LL, 10L); /* round closest */
+ R++;
+ }
+
+ return (u16)clamp_val(val, S16_MIN, S16_MAX);
+}
+EXPORT_SYMBOL_NS_GPL(pmbus_data2reg_direct_calc, "PMBUS");
+
static u16 pmbus_data2reg_direct(struct pmbus_data *data,
struct pmbus_sensor *sensor, s64 val)
{
@@ -1078,18 +1101,8 @@ static u16 pmbus_data2reg_direct(struct pmbus_data *data,
R -= 3; /* Adjust R and b for data in milli-units */
b *= 1000;
}
- val = val * m + b;
- while (R > 0) {
- val *= 10;
- R--;
- }
- while (R < 0) {
- val = div_s64(val + 5LL, 10L); /* round closest */
- R++;
- }
-
- return (u16)clamp_val(val, S16_MIN, S16_MAX);
+ return pmbus_data2reg_direct_calc(val, b, m, R);
}
static u16 pmbus_data2reg_vid(struct pmbus_data *data,
--
2.43.0