* [PATCH v6 0/3] Rework TPS25990 direct conversions and add TPS1689 support
@ 2026-08-05 9:03 Stoyan Bogdanov
2026-08-05 9:03 ` [PATCH v6 1/3] hwmon: (pmbus/tps25990): Rework driver for multi-device support Stoyan Bogdanov
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Stoyan Bogdanov @ 2026-08-05 9:03 UTC (permalink / raw)
To: jbrunet, linux, robh, krzk+dt, conor+dt, corbet, skhan
Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Stoyan Bogdanov
This series reworks the TPS25990 PMBus driver and adds TPS1689 support.
Both devices share most internal functionality, differing mainly in
supported voltage and current operating ranges.
Link to V5 at [3]
v6:
- Remove special-case conditioning for IIN_OCF so both TPS25990 and
TPS1689 use the same logic.
- Add scaling for TPS1689 VIN_OV_FAULT according to the datasheet
VIN_OV_FLT table, keep the existing behavior for TPS25990.
- Fix incorrect PMBus Direct format conversion coefficients (m, b, R)
for TPS1689 PSC_VOLTAGE_IN in struct pmbus_driver_info.
- Add missing PMBUS_HAVE_IOUT flag in pmbus_driver_info .func for TPS1689
- Restore the const qualifier on struct pmbus_driver_info, which was
removed unintentionally.
- Update i2c_device_id to follow I2C subsystem coding style by using the
.name and .driver_data initializers.
Link to V4 at [2]
v5:
- Simplify implementation and remove calculations from the driver, as
they are not needed and were implemented incorrectly. Thanks Guenter
for taking the time to explain.
- Drop pmbus API changes, as they are not actually needed.
- Add conditioning to separate TPS1689 and TPS25990 by chip_id in
tps25990_read_word_data() and tps25990_write_word_data() for
PMBUS_VIN_OV_FAULT_LIMIT and PMBUS_IIN_OC_FAULT_LIMIT. The TPS1689
value is not 4-bit, so it does not need adjusting. Keep the current
adjustment logic only for TPS25990.
Link to V3 at [1]
v4:
- Fix non-devicetree support as reported by Guenter Roeck
- Rework direct conversion handling to use exported PMBus core helpers
instead of driver-local implementations
- Update dt-bindings commit message and ti,tps25990.yaml
- Clarify commit messages to better reflect the final implementation
- Add and export direct conversion helpers from pmbus_core
- Eliminate duplicated conversion code in the driver
V3:
- Fix error detected from kernel test bot regarding division
Tests:
- Test builds for x86_64, arm64, i386
- Retest driver on arm64
- Validate driver direct conversion functions manualy
V2:
- Fix error detected from kernel test bot
- Add Acked-by to dt-bindings commit
- Drop "support" from dt-bindings commit subject
[1] https://lore.kernel.org/all/20260217081203.1792025-1-sbogdanov@baylibre.com/
[2] https://lore.kernel.org/all/20260522082349.2749970-1-sbogdanov@baylibre.com/
[3] https://lore.kernel.org/all/20260728015857.193890-1-sbogdanov@baylibre.com/
Stoyan Bogdanov (3):
hwmon: (pmbus/tps25990): Rework driver for multi-device support
dt-bindings: hwmon: pmbus/tps25990: Add TPS1689
hwmon: (pmbus/tps25990): Add TPS1689 support
.../bindings/hwmon/pmbus/ti,tps25990.yaml | 8 +-
Documentation/hwmon/tps25990.rst | 15 +-
drivers/hwmon/pmbus/tps25990.c | 227 +++++++++++++-----
3 files changed, 181 insertions(+), 69 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v6 1/3] hwmon: (pmbus/tps25990): Rework driver for multi-device support 2026-08-05 9:03 [PATCH v6 0/3] Rework TPS25990 direct conversions and add TPS1689 support Stoyan Bogdanov @ 2026-08-05 9:03 ` Stoyan Bogdanov 2026-08-05 9:09 ` sashiko-bot 2026-08-05 9:03 ` [PATCH v6 2/3] dt-bindings: hwmon: pmbus/tps25990: Add TPS1689 Stoyan Bogdanov 2026-08-05 9:03 ` [PATCH v6 3/3] hwmon: (pmbus/tps25990): Add TPS1689 support Stoyan Bogdanov 2 siblings, 1 reply; 8+ messages in thread From: Stoyan Bogdanov @ 2026-08-05 9:03 UTC (permalink / raw) To: jbrunet, linux, robh, krzk+dt, conor+dt, corbet, skhan Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Stoyan Bogdanov Rework existing implementation to allow adding support for new devices to the existing driver. chip_id is used to identify the current device and differentiate logic where needed. Changes include: - Add an enum listing supported chips - Add a structure to hold per-device m, b, R coefficients Signed-off-by: Stoyan Bogdanov <sbogdanov@baylibre.com> --- drivers/hwmon/pmbus/tps25990.c | 123 +++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 53 deletions(-) diff --git a/drivers/hwmon/pmbus/tps25990.c b/drivers/hwmon/pmbus/tps25990.c index 9d318e6509ab..7634ac743025 100644 --- a/drivers/hwmon/pmbus/tps25990.c +++ b/drivers/hwmon/pmbus/tps25990.c @@ -47,6 +47,15 @@ PK_MIN_AVG_RST_AVG | \ PK_MIN_AVG_RST_MIN) +enum chips { + tps25990, +}; + +struct tps25990_data { + struct pmbus_driver_info info; + enum chips chip_id; +}; + /* * Arbitrary default Rimon value: 1kOhm * This correspond to an overcurrent limit of 55A, close to the specified limit @@ -337,63 +346,65 @@ static const struct regulator_desc tps25990_reg_desc[] = { }; #endif -static const struct pmbus_driver_info tps25990_base_info = { - .pages = 1, - .format[PSC_VOLTAGE_IN] = direct, - .m[PSC_VOLTAGE_IN] = 5251, - .b[PSC_VOLTAGE_IN] = 0, - .R[PSC_VOLTAGE_IN] = -2, - .format[PSC_VOLTAGE_OUT] = direct, - .m[PSC_VOLTAGE_OUT] = 5251, - .b[PSC_VOLTAGE_OUT] = 0, - .R[PSC_VOLTAGE_OUT] = -2, - .format[PSC_TEMPERATURE] = direct, - .m[PSC_TEMPERATURE] = 140, - .b[PSC_TEMPERATURE] = 32100, - .R[PSC_TEMPERATURE] = -2, - /* - * Current and Power measurement depends on the ohm value - * of Rimon. m is multiplied by 1000 below to have an integer - * and -3 is added to R to compensate. - */ - .format[PSC_CURRENT_IN] = direct, - .m[PSC_CURRENT_IN] = 9538, - .b[PSC_CURRENT_IN] = 0, - .R[PSC_CURRENT_IN] = -6, - .format[PSC_POWER] = direct, - .m[PSC_POWER] = 4901, - .b[PSC_POWER] = 0, - .R[PSC_POWER] = -7, - .func[0] = (PMBUS_HAVE_VIN | - PMBUS_HAVE_VOUT | - PMBUS_HAVE_VMON | - PMBUS_HAVE_IIN | - PMBUS_HAVE_PIN | - PMBUS_HAVE_TEMP | - PMBUS_HAVE_STATUS_VOUT | - PMBUS_HAVE_STATUS_IOUT | - PMBUS_HAVE_STATUS_INPUT | - PMBUS_HAVE_STATUS_TEMP | - PMBUS_HAVE_SAMPLES), - .read_word_data = tps25990_read_word_data, - .write_word_data = tps25990_write_word_data, - .read_byte_data = tps25990_read_byte_data, - .write_byte_data = tps25990_write_byte_data, +static const struct pmbus_driver_info tps25990_base_info[] = { + [tps25990] = { + .pages = 1, + .format[PSC_VOLTAGE_IN] = direct, + .m[PSC_VOLTAGE_IN] = 5251, + .b[PSC_VOLTAGE_IN] = 0, + .R[PSC_VOLTAGE_IN] = -2, + .format[PSC_VOLTAGE_OUT] = direct, + .m[PSC_VOLTAGE_OUT] = 5251, + .b[PSC_VOLTAGE_OUT] = 0, + .R[PSC_VOLTAGE_OUT] = -2, + .format[PSC_TEMPERATURE] = direct, + .m[PSC_TEMPERATURE] = 140, + .b[PSC_TEMPERATURE] = 32100, + .R[PSC_TEMPERATURE] = -2, + /* + * Current and Power measurement depends on the ohm value + * of Rimon. m is multiplied by 1000 below to have an integer + * and -3 is added to R to compensate. + */ + .format[PSC_CURRENT_IN] = direct, + .m[PSC_CURRENT_IN] = 9538, + .b[PSC_CURRENT_IN] = 0, + .R[PSC_CURRENT_IN] = -6, + .format[PSC_POWER] = direct, + .m[PSC_POWER] = 4901, + .b[PSC_POWER] = 0, + .R[PSC_POWER] = -7, + .func[0] = (PMBUS_HAVE_VIN | + PMBUS_HAVE_VOUT | + PMBUS_HAVE_VMON | + PMBUS_HAVE_IIN | + PMBUS_HAVE_PIN | + PMBUS_HAVE_TEMP | + PMBUS_HAVE_STATUS_VOUT | + PMBUS_HAVE_STATUS_IOUT | + PMBUS_HAVE_STATUS_INPUT | + PMBUS_HAVE_STATUS_TEMP | + PMBUS_HAVE_SAMPLES), + .read_word_data = tps25990_read_word_data, + .write_word_data = tps25990_write_word_data, + .read_byte_data = tps25990_read_byte_data, + .write_byte_data = tps25990_write_byte_data, #if IS_ENABLED(CONFIG_SENSORS_TPS25990_REGULATOR) - .reg_desc = tps25990_reg_desc, - .num_regulators = ARRAY_SIZE(tps25990_reg_desc), + .reg_desc = tps25990_reg_desc, + .num_regulators = ARRAY_SIZE(tps25990_reg_desc), #endif + }, }; static const struct i2c_device_id tps25990_i2c_id[] = { - { .name = "tps25990" }, - { } + { .name = "tps25990", .driver_data = tps25990 }, + {} }; MODULE_DEVICE_TABLE(i2c, tps25990_i2c_id); static const struct of_device_id tps25990_of_match[] = { - { .compatible = "ti,tps25990" }, + { .compatible = "ti,tps25990", .data = (void *)tps25990 }, {} }; MODULE_DEVICE_TABLE(of, tps25990_of_match); @@ -401,8 +412,9 @@ MODULE_DEVICE_TABLE(of, tps25990_of_match); static int tps25990_probe(struct i2c_client *client) { struct device *dev = &client->dev; - struct pmbus_driver_info *info; + struct tps25990_data *data; const char *propname; + enum chips chip_id; u32 rimon; int ret; @@ -415,15 +427,20 @@ static int tps25990_probe(struct i2c_client *client) rimon = TPS25990_DEFAULT_RIMON; } - info = devm_kmemdup(dev, &tps25990_base_info, sizeof(*info), GFP_KERNEL); - if (!info) + chip_id = (enum chips)(unsigned long)i2c_get_match_data(client); + + data = devm_kzalloc(dev, sizeof(struct tps25990_data), GFP_KERNEL); + if (!data) return -ENOMEM; + data->info = tps25990_base_info[chip_id]; + data->chip_id = chip_id; + /* Adapt the current and power scale for each instance */ - tps25990_set_m(&info->m[PSC_CURRENT_IN], rimon); - tps25990_set_m(&info->m[PSC_POWER], rimon); + tps25990_set_m(&data->info.m[PSC_CURRENT_IN], rimon); + tps25990_set_m(&data->info.m[PSC_POWER], rimon); - return pmbus_do_probe(client, info); + return pmbus_do_probe(client, &data->info); } static struct i2c_driver tps25990_driver = { -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v6 1/3] hwmon: (pmbus/tps25990): Rework driver for multi-device support 2026-08-05 9:03 ` [PATCH v6 1/3] hwmon: (pmbus/tps25990): Rework driver for multi-device support Stoyan Bogdanov @ 2026-08-05 9:09 ` sashiko-bot 0 siblings, 0 replies; 8+ messages in thread From: sashiko-bot @ 2026-08-05 9:09 UTC (permalink / raw) To: Stoyan Bogdanov; +Cc: linux-hwmon, robh, conor+dt, devicetree > Rework existing implementation to allow adding support for new > devices to the existing driver. chip_id is used to identify the > current device and differentiate logic where needed. > > Changes include: > - Add an enum listing supported chips > - Add a structure to hold per-device m, b, R coefficients > > Signed-off-by: Stoyan Bogdanov <sbogdanov@baylibre.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260805090400.2059006-1-sbogdanov@baylibre.com?part=1 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 2/3] dt-bindings: hwmon: pmbus/tps25990: Add TPS1689 2026-08-05 9:03 [PATCH v6 0/3] Rework TPS25990 direct conversions and add TPS1689 support Stoyan Bogdanov 2026-08-05 9:03 ` [PATCH v6 1/3] hwmon: (pmbus/tps25990): Rework driver for multi-device support Stoyan Bogdanov @ 2026-08-05 9:03 ` Stoyan Bogdanov 2026-08-05 9:07 ` sashiko-bot 2026-08-05 9:03 ` [PATCH v6 3/3] hwmon: (pmbus/tps25990): Add TPS1689 support Stoyan Bogdanov 2 siblings, 1 reply; 8+ messages in thread From: Stoyan Bogdanov @ 2026-08-05 9:03 UTC (permalink / raw) To: jbrunet, linux, robh, krzk+dt, conor+dt, corbet, skhan Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Stoyan Bogdanov, Krzysztof Kozlowski Add device compatible support for TPS1689 Signed-off-by: Stoyan Bogdanov <sbogdanov@baylibre.com> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com> --- .../devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml index f4115870e450..63ccb67576df 100644 --- a/Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml +++ b/Documentation/devicetree/bindings/hwmon/pmbus/ti,tps25990.yaml @@ -5,18 +5,20 @@ $id: http://devicetree.org/schemas/hwmon/pmbus/ti,tps25990.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Texas Instruments TPS25990 Stackable eFuse +title: Texas Instruments Stackable eFuses maintainers: - Jerome Brunet <jbrunet@baylibre.com> description: - The TI TPS25990 is an integrated, high-current circuit + The TI TPS25990 and TPS1689 are integrated, high-current circuit protection and power management device with PMBUS interface properties: compatible: - const: ti,tps25990 + enum: + - ti,tps1689 + - ti,tps25990 reg: maxItems: 1 -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v6 2/3] dt-bindings: hwmon: pmbus/tps25990: Add TPS1689 2026-08-05 9:03 ` [PATCH v6 2/3] dt-bindings: hwmon: pmbus/tps25990: Add TPS1689 Stoyan Bogdanov @ 2026-08-05 9:07 ` sashiko-bot 0 siblings, 0 replies; 8+ messages in thread From: sashiko-bot @ 2026-08-05 9:07 UTC (permalink / raw) To: Stoyan Bogdanov; +Cc: devicetree, conor+dt, linux-hwmon, robh > Add device compatible support for TPS1689 > > Signed-off-by: Stoyan Bogdanov <sbogdanov@baylibre.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260805090400.2059006-1-sbogdanov@baylibre.com?part=2 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 3/3] hwmon: (pmbus/tps25990): Add TPS1689 support 2026-08-05 9:03 [PATCH v6 0/3] Rework TPS25990 direct conversions and add TPS1689 support Stoyan Bogdanov 2026-08-05 9:03 ` [PATCH v6 1/3] hwmon: (pmbus/tps25990): Rework driver for multi-device support Stoyan Bogdanov 2026-08-05 9:03 ` [PATCH v6 2/3] dt-bindings: hwmon: pmbus/tps25990: Add TPS1689 Stoyan Bogdanov @ 2026-08-05 9:03 ` Stoyan Bogdanov 2026-08-05 9:20 ` sashiko-bot 2 siblings, 1 reply; 8+ messages in thread From: Stoyan Bogdanov @ 2026-08-05 9:03 UTC (permalink / raw) To: jbrunet, linux, robh, krzk+dt, conor+dt, corbet, skhan Cc: linux-hwmon, devicetree, linux-doc, linux-kernel, Stoyan Bogdanov Extend the existing TPS25990 driver to support the TPS1689 eFuse, as both devices share the same command interface and functionality. Update the documentation to include TPS1689 support. Signed-off-by: Stoyan Bogdanov <sbogdanov@baylibre.com> --- Documentation/hwmon/tps25990.rst | 15 +++-- drivers/hwmon/pmbus/tps25990.c | 106 ++++++++++++++++++++++++++++--- 2 files changed, 107 insertions(+), 14 deletions(-) diff --git a/Documentation/hwmon/tps25990.rst b/Documentation/hwmon/tps25990.rst index 04faec780d26..e8bc9a550bda 100644 --- a/Documentation/hwmon/tps25990.rst +++ b/Documentation/hwmon/tps25990.rst @@ -9,26 +9,31 @@ Supported chips: Prefix: 'tps25990' - * Datasheet + Datasheet: Publicly available at Texas Instruments website: https://www.ti.com/lit/gpn/tps25990 - Publicly available at Texas Instruments website: https://www.ti.com/lit/gpn/tps25990 + * TI TPS1689 + + Prefix: 'tps1689' + + Datasheet: Publicly available at Texas Instruments website: https://www.ti.com/lit/gpn/tps1689 Author: Jerome Brunet <jbrunet@baylibre.com> + Stoyan Bogdanov <sbogdanov@baylibre.com> Description ----------- -This driver implements support for TI TPS25990 eFuse. +This driver implements support for TI TPS25990 and TI TPS1689 eFuse chips. This is an integrated, high-current circuit protection and power management device with PMBUS interface -Device compliant with: +Devices are compliant with: - PMBus rev 1.3 interface. -Device supports direct format for reading input voltages, +Devices supports direct format for reading input voltages, output voltage, input current, input power and temperature. Due to the specificities of the chip, all history reset attributes diff --git a/drivers/hwmon/pmbus/tps25990.c b/drivers/hwmon/pmbus/tps25990.c index 7634ac743025..a91ea8f33b29 100644 --- a/drivers/hwmon/pmbus/tps25990.c +++ b/drivers/hwmon/pmbus/tps25990.c @@ -47,7 +47,14 @@ PK_MIN_AVG_RST_AVG | \ PK_MIN_AVG_RST_MIN) +#define TPS1689_VIN_OV_RANGE_SEL_MASK GENMASK(7, 6) +#define TPS1689_VIN_VOV_MASK GENMASK(5, 0) +#define TPS1689_VIN_SCALING 251 +#define TPS1689_VIN_VOV_STEP_MV 250 +#define TPS1689_VIN_RANGE_SPAN_MV 16000 + enum chips { + tps1689, tps25990, }; @@ -105,6 +112,8 @@ static int tps25990_mfr_write_protect_get(struct i2c_client *client) static int tps25990_read_word_data(struct i2c_client *client, int page, int phase, int reg) { + const struct pmbus_driver_info *info = pmbus_get_driver_info(client); + struct tps25990_data *data = container_of(info, struct tps25990_data, info); int ret; switch (reg) { @@ -193,9 +202,18 @@ static int tps25990_read_word_data(struct i2c_client *client, ret = pmbus_read_word_data(client, page, phase, reg); if (ret < 0) break; - ret = DIV_ROUND_CLOSEST(ret * TPS25990_VIN_OVF_NUM, - TPS25990_VIN_OVF_DIV); - ret += TPS25990_VIN_OVF_OFF; + if (data->chip_id == tps25990) { + ret = DIV_ROUND_CLOSEST(ret * TPS25990_VIN_OVF_NUM, + TPS25990_VIN_OVF_DIV); + ret += TPS25990_VIN_OVF_OFF; + } else if (data->chip_id == tps1689) { + ret = DIV_ROUND_CLOSEST( + ((FIELD_GET(TPS1689_VIN_OV_RANGE_SEL_MASK, ret) + 1) * + TPS1689_VIN_RANGE_SPAN_MV) + + (FIELD_GET(TPS1689_VIN_VOV_MASK, ret) * + TPS1689_VIN_VOV_STEP_MV - TPS1689_VIN_RANGE_SPAN_MV), + TPS1689_VIN_SCALING); + } break; case PMBUS_IIN_OC_FAULT_LIMIT: @@ -208,7 +226,7 @@ static int tps25990_read_word_data(struct i2c_client *client, if (ret < 0) break; ret = DIV_ROUND_CLOSEST(ret * TPS25990_IIN_OCF_NUM, - TPS25990_IIN_OCF_DIV); + TPS25990_IIN_OCF_DIV); ret += TPS25990_IIN_OCF_OFF; break; @@ -238,6 +256,8 @@ static int tps25990_read_word_data(struct i2c_client *client, static int tps25990_write_word_data(struct i2c_client *client, int page, int reg, u16 value) { + const struct pmbus_driver_info *info = pmbus_get_driver_info(client); + struct tps25990_data *data = container_of(info, struct tps25990_data, info); int ret; switch (reg) { @@ -255,10 +275,23 @@ static int tps25990_write_word_data(struct i2c_client *client, break; case PMBUS_VIN_OV_FAULT_LIMIT: - value -= TPS25990_VIN_OVF_OFF; - value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_VIN_OVF_DIV, - TPS25990_VIN_OVF_NUM); - value = clamp_val(value, 0, 0xf); + if (data->chip_id == tps25990) { + value -= TPS25990_VIN_OVF_OFF; + value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_VIN_OVF_DIV, + TPS25990_VIN_OVF_NUM); + value = clamp_val(value, 0, 0xf); + } else if (data->chip_id == tps1689) { + u32 scaled_value = value * TPS1689_VIN_SCALING + TPS1689_VIN_RANGE_SPAN_MV; + u32 tmp_scaled_value = scaled_value; + u8 ov_rng_sel = 0; + u32 ov_set = 0; + + ov_rng_sel = tmp_scaled_value / TPS1689_VIN_RANGE_SPAN_MV; + ov_set = tmp_scaled_value - (TPS1689_VIN_RANGE_SPAN_MV * ov_rng_sel); + value = FIELD_PREP(TPS1689_VIN_OV_RANGE_SEL_MASK, ov_rng_sel - 1) | + FIELD_PREP(TPS1689_VIN_VOV_MASK, + (ov_set / TPS1689_VIN_VOV_STEP_MV)); + } ret = pmbus_write_word_data(client, page, reg, value); break; @@ -347,6 +380,60 @@ static const struct regulator_desc tps25990_reg_desc[] = { #endif static const struct pmbus_driver_info tps25990_base_info[] = { + [tps1689] = { + .pages = 1, + .format[PSC_VOLTAGE_IN] = direct, + .m[PSC_VOLTAGE_IN] = 3984, + .b[PSC_VOLTAGE_IN] = -63750, + .R[PSC_VOLTAGE_IN] = -3, + .format[PSC_VOLTAGE_OUT] = direct, + .m[PSC_VOLTAGE_OUT] = 1166, + .b[PSC_VOLTAGE_OUT] = 0, + .R[PSC_VOLTAGE_OUT] = -2, + .format[PSC_TEMPERATURE] = direct, + .m[PSC_TEMPERATURE] = 140, + .b[PSC_TEMPERATURE] = 32103, + .R[PSC_TEMPERATURE] = -2, + /* + * Current and Power measurement depends on the ohm value + * of Rimon. m is multiplied by 1000 below to have an integer + * and -3 is added to R to compensate. + */ + .format[PSC_CURRENT_IN] = direct, + .m[PSC_CURRENT_IN] = 9548, + .b[PSC_CURRENT_IN] = 0, + .R[PSC_CURRENT_IN] = -6, + .format[PSC_CURRENT_OUT] = direct, + .m[PSC_CURRENT_OUT] = 24347, + .b[PSC_CURRENT_OUT] = 0, + .R[PSC_CURRENT_OUT] = -3, + .format[PSC_POWER] = direct, + .m[PSC_POWER] = 2775, + .b[PSC_POWER] = 0, + .R[PSC_POWER] = -4, + .func[0] = (PMBUS_HAVE_VIN | + PMBUS_HAVE_VOUT | + PMBUS_HAVE_VMON | + PMBUS_HAVE_IIN | + PMBUS_HAVE_IOUT | + PMBUS_HAVE_PIN | + PMBUS_HAVE_TEMP | + PMBUS_HAVE_STATUS_VOUT | + PMBUS_HAVE_STATUS_IOUT | + PMBUS_HAVE_STATUS_INPUT | + PMBUS_HAVE_STATUS_TEMP | + PMBUS_HAVE_SAMPLES), + + .read_word_data = tps25990_read_word_data, + .write_word_data = tps25990_write_word_data, + .read_byte_data = tps25990_read_byte_data, + .write_byte_data = tps25990_write_byte_data, + +#if IS_ENABLED(CONFIG_SENSORS_TPS25990_REGULATOR) + .reg_desc = tps25990_reg_desc, + .num_regulators = ARRAY_SIZE(tps25990_reg_desc), +#endif + }, [tps25990] = { .pages = 1, .format[PSC_VOLTAGE_IN] = direct, @@ -389,7 +476,6 @@ static const struct pmbus_driver_info tps25990_base_info[] = { .write_word_data = tps25990_write_word_data, .read_byte_data = tps25990_read_byte_data, .write_byte_data = tps25990_write_byte_data, - #if IS_ENABLED(CONFIG_SENSORS_TPS25990_REGULATOR) .reg_desc = tps25990_reg_desc, .num_regulators = ARRAY_SIZE(tps25990_reg_desc), @@ -398,12 +484,14 @@ static const struct pmbus_driver_info tps25990_base_info[] = { }; static const struct i2c_device_id tps25990_i2c_id[] = { + { .name = "tps1689", .driver_data = tps1689 }, { .name = "tps25990", .driver_data = tps25990 }, {} }; MODULE_DEVICE_TABLE(i2c, tps25990_i2c_id); static const struct of_device_id tps25990_of_match[] = { + { .compatible = "ti,tps1689", .data = (void *)tps1689 }, { .compatible = "ti,tps25990", .data = (void *)tps25990 }, {} }; -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v6 3/3] hwmon: (pmbus/tps25990): Add TPS1689 support 2026-08-05 9:03 ` [PATCH v6 3/3] hwmon: (pmbus/tps25990): Add TPS1689 support Stoyan Bogdanov @ 2026-08-05 9:20 ` sashiko-bot 2026-08-05 15:28 ` Guenter Roeck 0 siblings, 1 reply; 8+ messages in thread From: sashiko-bot @ 2026-08-05 9:20 UTC (permalink / raw) To: Stoyan Bogdanov; +Cc: linux-hwmon, robh, devicetree, conor+dt Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: New issues: - [High] Incorrect scaling, missing boundary clamping, and unsigned wrap-around for TPS1689 PMBUS_VIN_OV_FAULT_LIMIT cause severely corrupted limits and bitfield overflows. - [High] The shared 8-bit warning limit write paths treat PMBus direct values as unsigned, breaking all warning limits for TPS1689. - [Medium] Missing scale adaptation for PSC_CURRENT_OUT in tps25990_probe leads to output current readings being off by a factor of 1000. - [Low] The intermediate expression in the read path for PMBUS_VIN_OV_FAULT_LIMIT unconditionally underflows in unsigned arithmetic, violating subsystem guidelines. Pre-existing issues: - [High] Writing a small voltage/current limit below the hardware offset for TPS25990 causes an unsigned integer underflow, wrapping around to configure the hardware with its maximum (weakest) protection limit. -- --- Patch [3]: [PATCH v6 3/3] hwmon: (pmbus/tps25990): Add TPS1689 support --- commit a29f74ffb1bc30041022deb0ab63b9dd79c1a779 Author: Stoyan Bogdanov <sbogdanov@baylibre.com> hwmon: (pmbus/tps25990): Add TPS1689 support Extend the existing TPS25990 driver to support the TPS1689 eFuse, as both devices share the same command interface and functionality. Update the documentation to include TPS1689 support. > diff --git a/drivers/hwmon/pmbus/tps25990.c b/drivers/hwmon/pmbus/tps25990.c > index 7634ac743025d..a91ea8f33b296 100644 > --- a/drivers/hwmon/pmbus/tps25990.c > +++ b/drivers/hwmon/pmbus/tps25990.c [ ... ] > @@ -193,9 +202,18 @@ static int tps25990_read_word_data(struct i2c_client *client, > ret = pmbus_read_word_data(client, page, phase, reg); > if (ret < 0) > break; > - ret = DIV_ROUND_CLOSEST(ret * TPS25990_VIN_OVF_NUM, > - TPS25990_VIN_OVF_DIV); > - ret += TPS25990_VIN_OVF_OFF; > + if (data->chip_id == tps25990) { > + ret = DIV_ROUND_CLOSEST(ret * TPS25990_VIN_OVF_NUM, > + TPS25990_VIN_OVF_DIV); > + ret += TPS25990_VIN_OVF_OFF; > + } else if (data->chip_id == tps1689) { > + ret = DIV_ROUND_CLOSEST( > + ((FIELD_GET(TPS1689_VIN_OV_RANGE_SEL_MASK, ret) + 1) * > + TPS1689_VIN_RANGE_SPAN_MV) + > + (FIELD_GET(TPS1689_VIN_VOV_MASK, ret) * > + TPS1689_VIN_VOV_STEP_MV - TPS1689_VIN_RANGE_SPAN_MV), [Severity: Low] Does this intermediate expression underflow in unsigned arithmetic? The maximum VOV is 63, so 63 * 250 = 15750, making the subtraction unconditionally negative. Due to the unsigned evaluation of FIELD_GET(), this underflows to a large positive integer before wrapping back correctly when added. Can this be simplified to RNG * 16000 + VOV * 250 to avoid the underflow? > + TPS1689_VIN_SCALING); > + } > break; [ ... ] > @@ -238,6 +256,8 @@ static int tps25990_read_word_data(struct i2c_client *client, > static int tps25990_write_word_data(struct i2c_client *client, > int page, int reg, u16 value) > { > + const struct pmbus_driver_info *info = pmbus_get_driver_info(client); > + struct tps25990_data *data = container_of(info, struct tps25990_data, info); > int ret; > > switch (reg) { [Severity: High] Does this newly added device support require updates to the warning limit logic? For TPS1689, standard voltages map to negative PMBus direct format values (e.g., -4). In tps25990_write_word_data(), the shared 8-bit warning limits perform a logical right shift: case PMBUS_VIN_UV_WARN_LIMIT: ... case PMBUS_PIN_OP_WARN_LIMIT: value >>= TPS25990_8B_SHIFT; value = clamp_val(value, 0, 0xff); Since value is an unsigned u16, will the right shift convert negative PMBus values to large positive numbers, causing standard voltage warning limits to be misconfigured as the maximum possible value? > @@ -255,10 +275,23 @@ static int tps25990_write_word_data(struct i2c_client *client, > break; > > case PMBUS_VIN_OV_FAULT_LIMIT: > - value -= TPS25990_VIN_OVF_OFF; > - value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_VIN_OVF_DIV, > - TPS25990_VIN_OVF_NUM); > - value = clamp_val(value, 0, 0xf); > + if (data->chip_id == tps25990) { > + value -= TPS25990_VIN_OVF_OFF; [Severity: High] This isn't a bug introduced by this patch, but does writing a small limit below the hardware offset cause an unsigned integer underflow? If a user writes a limit that converts to a PMBus value smaller than TPS25990_VIN_OVF_OFF (155) or TPS25990_IIN_OCF_OFF (157), value will underflow to a huge number. Since clamp_val() then clamps it to the absolute maximum limit index, will this completely defeat the hardware protection during an over-voltage or over-current event? > + value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_VIN_OVF_DIV, > + TPS25990_VIN_OVF_NUM); > + value = clamp_val(value, 0, 0xf); > + } else if (data->chip_id == tps1689) { > + u32 scaled_value = value * TPS1689_VIN_SCALING + TPS1689_VIN_RANGE_SPAN_MV; > + u32 tmp_scaled_value = scaled_value; > + u8 ov_rng_sel = 0; > + u32 ov_set = 0; > + > + ov_rng_sel = tmp_scaled_value / TPS1689_VIN_RANGE_SPAN_MV; > + ov_set = tmp_scaled_value - (TPS1689_VIN_RANGE_SPAN_MV * ov_rng_sel); > + value = FIELD_PREP(TPS1689_VIN_OV_RANGE_SEL_MASK, ov_rng_sel - 1) | [Severity: High] Does this calculation incorrectly scale the limit and overflow the bitfield? If a PMBus direct format value of -4 (65532 as unsigned u16) is passed in, scaling it by 251 generates an out-of-bounds ov_rng_sel. Since there is no clamping before FIELD_PREP(), will this silently truncate the value and configure the hardware with dangerously low over-voltage limits? > + FIELD_PREP(TPS1689_VIN_VOV_MASK, > + (ov_set / TPS1689_VIN_VOV_STEP_MV)); > + } > ret = pmbus_write_word_data(client, page, reg, value); > break; [ ... ] > @@ -347,6 +380,60 @@ static const struct regulator_desc tps25990_reg_desc[] = { > #endif > > static const struct pmbus_driver_info tps25990_base_info[] = { > + [tps1689] = { > + .pages = 1, [ ... ] > + .format[PSC_CURRENT_IN] = direct, > + .m[PSC_CURRENT_IN] = 9548, > + .b[PSC_CURRENT_IN] = 0, > + .R[PSC_CURRENT_IN] = -6, > + .format[PSC_CURRENT_OUT] = direct, > + .m[PSC_CURRENT_OUT] = 24347, > + .b[PSC_CURRENT_OUT] = 0, > + .R[PSC_CURRENT_OUT] = -3, [Severity: Medium] Does tps25990_probe() need to be updated to adapt the scale for PSC_CURRENT_OUT? While PSC_CURRENT_IN is dynamically scaled based on the rimon resistor value in tps25990_probe(): tps25990_set_m(&data->info.m[PSC_CURRENT_IN], rimon); tps25990_set_m(&data->info.m[PSC_POWER], rimon); PSC_CURRENT_OUT is omitted. Since the default rimon scaling multiplies m by 1000, will skipping this adaptation cause the reported output current telemetry to be off by a factor of 1000? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260805090400.2059006-1-sbogdanov@baylibre.com?part=3 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6 3/3] hwmon: (pmbus/tps25990): Add TPS1689 support 2026-08-05 9:20 ` sashiko-bot @ 2026-08-05 15:28 ` Guenter Roeck 0 siblings, 0 replies; 8+ messages in thread From: Guenter Roeck @ 2026-08-05 15:28 UTC (permalink / raw) To: sashiko-reviews, Stoyan Bogdanov; +Cc: linux-hwmon, robh, devicetree, conor+dt On 8/5/26 02:20, sashiko-bot@kernel.org wrote: > Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: > > New issues: > - [High] Incorrect scaling, missing boundary clamping, and unsigned wrap-around for TPS1689 PMBUS_VIN_OV_FAULT_LIMIT cause severely corrupted limits and bitfield overflows. > - [High] The shared 8-bit warning limit write paths treat PMBus direct values as unsigned, breaking all warning limits for TPS1689. > - [Medium] Missing scale adaptation for PSC_CURRENT_OUT in tps25990_probe leads to output current readings being off by a factor of 1000. > - [Low] The intermediate expression in the read path for PMBUS_VIN_OV_FAULT_LIMIT unconditionally underflows in unsigned arithmetic, violating subsystem guidelines. > Please address these issues. Thanks, Guenter ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-08-05 15:28 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-05 9:03 [PATCH v6 0/3] Rework TPS25990 direct conversions and add TPS1689 support Stoyan Bogdanov 2026-08-05 9:03 ` [PATCH v6 1/3] hwmon: (pmbus/tps25990): Rework driver for multi-device support Stoyan Bogdanov 2026-08-05 9:09 ` sashiko-bot 2026-08-05 9:03 ` [PATCH v6 2/3] dt-bindings: hwmon: pmbus/tps25990: Add TPS1689 Stoyan Bogdanov 2026-08-05 9:07 ` sashiko-bot 2026-08-05 9:03 ` [PATCH v6 3/3] hwmon: (pmbus/tps25990): Add TPS1689 support Stoyan Bogdanov 2026-08-05 9:20 ` sashiko-bot 2026-08-05 15:28 ` Guenter Roeck
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox