Re: [PATCH v5 3/3] hwmon: (pmbus/tps25990): Add TPS1689 support

[email protected] Tue, 28 Jul 2026 02:09:15 +0000
Newsgroups org.kernel.vger.linux-hwmon,org.kernel.vger.linux-devicetree
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] When writing the `PMBUS_IIN_OC_FAULT_LIMIT` for `tps1689`, the 16-bit `value` is passed directly to `pmbus_write_byte_data()` without clamping, causing silent integer truncation and incorrect hardware limits.
- [Medium] The `tps1689` configuration defines format and coefficients for `PSC_CURRENT_OUT`, but misses the required capability flag and scaling logic, leaving it completely unused and broken.

Pre-existing issues:
- [High] When a user requests a voltage or current limit lower than the base hardware offset, the unsigned 16-bit limit underflows, silently configuring the hardware to its absolute maximum limit.
--

--- Patch [3]: [PATCH v5 3/3] hwmon: (pmbus/tps25990): Add TPS1689 support ---
commit 3362ebf6e63c82cf07dc00cc00e78fd1761514ef
Author: Stoyan Bogdanov <[email protected]>

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 490dcd2a5fa51..7e2991a85da13 100644
> --- a/drivers/hwmon/pmbus/tps25990.c
> +++ b/drivers/hwmon/pmbus/tps25990.c

[ ... ]

> @@ -253,20 +262,23 @@ static int tps25990_write_word_data(struct i2c_client *client,
>  		value = clamp_val(value, 0, 0xff);
>  		ret = pmbus_write_word_data(client, page, reg, value);
>  		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);
> +		}

[Severity: High]
This is a pre-existing issue, but could this calculation underflow if the user
requests a limit lower than the base hardware offset?

If a limit is requested where the value is less than TPS25990_VIN_OVF_OFF (155),
wouldn't the u16 value silently underflow to a very large positive number when
subtracted?

Since this huge value is then scaled and passed to clamp_val() against 0xf,
would this result in setting the absolute maximum possible limit in the hardware
instead of the requested low limit, inadvertently bypassing the protections?

>  		ret = pmbus_write_word_data(client, page, reg, value);
>  		break;
>  
>  	case PMBUS_IIN_OC_FAULT_LIMIT:
> -		value -= TPS25990_IIN_OCF_OFF;
> -		value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_IIN_OCF_DIV,
> -					  TPS25990_IIN_OCF_NUM);
> -		value = clamp_val(value, 0, 0x3f);
> +		if (data->chip_id == tps25990) {
> +			value -= TPS25990_IIN_OCF_OFF;
> +			value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_IIN_OCF_DIV,
> +						  TPS25990_IIN_OCF_NUM);
> +			value = clamp_val(value, 0, 0x3f);
> +		}

[Severity: High]
This is also a pre-existing issue, but does this face the same underflow risk
if the requested limit is less than TPS25990_IIN_OCF_OFF?

>  		ret = pmbus_write_byte_data(client, page, TPS25990_VIREF, value);

[Severity: High]
When data->chip_id == tps1689, this code skips the scaling block and passes
the u16 value directly into pmbus_write_byte_data().

Does this silently truncate the 16-bit value into an 8-bit register write?

If a large limit is requested, could this truncation cause it to wrap around
to a very small limit, potentially causing the eFuse to prematurely cut power?

>  		break;

[ ... ]

> @@ -347,6 +359,59 @@ static const struct regulator_desc tps25990_reg_desc[] = {
>  #endif
>  
>  static struct pmbus_driver_info tps25990_base_info[] = {
> +	[tps1689] = {
> +		.pages = 1,

[ ... ]

> +		.format[PSC_CURRENT_OUT] = direct,
> +		.m[PSC_CURRENT_OUT] = 24347,
> +		.b[PSC_CURRENT_OUT] = 0,
> +		.R[PSC_CURRENT_OUT] = -3,

[ ... ]

> +		.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),

[Severity: Medium]
The configuration defines format and coefficients for PSC_CURRENT_OUT, however
the func[0] capability flags do not include PMBUS_HAVE_IOUT.

Does this mean the PMBus core will completely ignore the output current sensor?

Additionally, looking at tps25990_probe(), it appears dynamic scaling for the
rimon resistor is applied for PSC_CURRENT_IN and PSC_POWER, but not
PSC_CURRENT_OUT:

drivers/hwmon/pmbus/tps25990.c:tps25990_probe() {
    ...
	/* Adapt the current and power scale for each instance */
	tps25990_set_m(&data->info.m[PSC_CURRENT_IN], rimon);
	tps25990_set_m(&data->info.m[PSC_POWER], rimon);
    ...
}

Would this reading be incorrect even if the sensor capability were enabled?

-- 
Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=3