public inbox for linux-hwmon@vger.kernel.org
 help / color / mirror / Atom feed
From: "Nuno Sá" <noname.nuno@gmail.com>
To: Guenter Roeck <linux@roeck-us.net>
Cc: "Nuno Sá" <nuno.sa@analog.com>,
	linux-gpio@vger.kernel.org, linux-hwmon@vger.kernel.org,
	devicetree@vger.kernel.org, linux-doc@vger.kernel.org,
	"Rob Herring" <robh@kernel.org>,
	"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
	"Conor Dooley" <conor+dt@kernel.org>,
	"Jonathan Corbet" <corbet@lwn.net>,
	"Linus Walleij" <linusw@kernel.org>,
	"Bartosz Golaszewski" <brgl@kernel.org>
Subject: Re: [PATCH v8 2/3] hwmon: ltc4283: Add support for the LTC4283 Swap Controller
Date: Tue, 31 Mar 2026 10:48:43 +0100	[thread overview]
Message-ID: <acuLynb1hRFJRcEf@nsa> (raw)
In-Reply-To: <e0c96f38-6742-4b86-8938-64e4e6063119@roeck-us.net>

On Mon, Mar 30, 2026 at 08:47:32AM -0700, Guenter Roeck wrote:
> On 3/30/26 02:28, Nuno Sá wrote:
> > Hi Guenter, Regarding AI review, I think most of the points were
> > discussed in previous revisions, but there are two valid.
> > 
> > On Fri, Mar 27, 2026 at 05:26:15PM +0000, Nuno Sá wrote:
> > > Support the LTC4283 Hot Swap Controller. The device features programmable
> > > current limit with foldback and independently adjustable inrush current to
> > > optimize the MOSFET safe operating area (SOA). The SOA timer limits MOSFET
> > > temperature rise for reliable protection against overstresses.
> > > 
> > > An I2C interface and onboard ADC allow monitoring of board current,
> > > voltage, power, energy, and fault status.
> > > 
> > > Signed-off-by: Nuno Sá <nuno.sa@analog.com>
> > > ---
> > >   Documentation/hwmon/index.rst   |    1 +
> > >   Documentation/hwmon/ltc4283.rst |  266 ++++++
> > >   MAINTAINERS                     |    1 +
> > >   drivers/hwmon/Kconfig           |   12 +
> > >   drivers/hwmon/Makefile          |    1 +
> > >   drivers/hwmon/ltc4283.c         | 1796 +++++++++++++++++++++++++++++++++++++++
> > >   6 files changed, 2077 insertions(+)
> > > 
> > 
> > ...
> > 
> > > +static int ltc4283_read_in_alarm(struct ltc4283_hwmon *st, u32 channel,
> > > +				 bool max_alm, long *val)
> > > +{
> > > +	if (channel == LTC4283_VPWR)
> > > +		return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_1,
> > > +					  BIT(2 + max_alm), val);
> > > +
> > > +	if (channel >= LTC4283_CHAN_ADI_1 && channel <= LTC4283_CHAN_ADI_4) {
> > > +		u32 bit = (channel - LTC4283_CHAN_ADI_1) * 2;
> > > +		/*
> > > +		 * Lower channels go to higher bits. We also want to go +1 down
> > > +		 * in the min_alarm case.
> > > +		 */
> > > +		return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_2,
> > > +					  BIT(7 - bit - !max_alm), val);
> > > +	}
> > > +
> > > +	if (channel >= LTC4283_CHAN_ADIO_1 && channel <= LTC4283_CHAN_ADIO_4) {
> > > +		u32 bit = (channel - LTC4283_CHAN_ADIO_1) * 2;
> > > +
> > > +		return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_3,
> > > +					  BIT(7 - bit - !max_alm), val);
> > > +	}
> > > +
> > > +	if (channel >= LTC4283_CHAN_ADIN12 && channel <= LTC4283_CHAN_ADIN34) {
> > > +		u32 bit = (channel - LTC4283_CHAN_ADIN12) * 2;
> > > +
> > > +		return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_5,
> > > +					  BIT(7 - bit - !max_alm), val);
> > > +	}
> > 
> > "Will this condition handle the ADIO12 and ADIO34 differential channels?
> > It looks like channels 14 and 15 fall through to the default return intended
> > for the DRAIN channel. Since reading the alarm implicitly clears the register
> > bits, could reading these ADIO alarms unintentionally clear actual DRAIN
> > alarms? Should the upper bound be LTC4283_CHAN_ADIO34?"
> > 
> > Good catch and should be:
> > 
> > -       if (channel >= LTC4283_CHAN_ADIN12 && channel <= LTC4283_CHAN_ADIN34) {
> > +       if (channel >= LTC4283_CHAN_ADIN12 && channel <= LTC4283_CHAN_ADIO34) {
> > 
> > > +
> > > +	if (channel == LTC4283_CHAN_DRNS)
> > > +		return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_4,
> > > +					  BIT(6 + max_alm), val);
> > > +
> > > +	return ltc4283_read_alarm(st, LTC4283_ADC_ALM_LOG_4, BIT(4 + max_alm),
> > > +				  val);
> > > +}
> > 
> > ...
> > 
> > > +
> > > +static int ltc4283_probe(struct i2c_client *client)
> > > +{
> > > +	struct device *dev = &client->dev, *hwmon;
> > > +	struct auxiliary_device *adev;
> > > +	struct ltc4283_hwmon *st;
> > > +	int ret;
> > > +
> > > +	st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
> > > +	if (!st)
> > > +		return -ENOMEM;
> > > +
> > > +	if (!i2c_check_functionality(client->adapter,
> > > +				     I2C_FUNC_SMBUS_BYTE_DATA |
> > > +				     I2C_FUNC_SMBUS_WORD_DATA |
> > > +				     I2C_FUNC_SMBUS_READ_I2C_BLOCK))
> > > +		return -EOPNOTSUPP;
> > > +
> > > +	st->client = client;
> > > +	st->map = devm_regmap_init(dev, &ltc4283_regmap_bus, client,
> > > +				   &ltc4283_regmap_config);
> > > +	if (IS_ERR(st->map))
> > > +		return dev_err_probe(dev, PTR_ERR(st->map),
> > > +				     "Failed to create regmap\n");
> > > +
> > > +	ret = ltc4283_setup(st, dev);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	hwmon = devm_hwmon_device_register_with_info(dev, "ltc4283", st,
> > > +						     &ltc4283_chip_info, NULL);
> > > +
> > > +	if (IS_ERR(hwmon))
> > > +		return PTR_ERR(hwmon);
> > > +
> > > +	ltc4283_debugfs_init(st, client);
> > > +
> > > +	if (!st->gpio_mask)
> > > +		return 0;
> > > +
> > > +	adev = devm_auxiliary_device_create(dev, "gpio", &st->gpio_mask);
> > > +	if (!adev)
> > > +		return dev_err_probe(dev, -ENODEV, "Failed to add GPIO device\n");
> > 
> > "Does this allow multiple LTC4283 chips to probe successfully?
> > Without allocating a unique ID per I2C instance, it seems the first probed
> > chip takes the generic name. If a second chip is present, it might attempt
> > to register with the exact same name, resulting in a failure in device_add()
> > and aborting the probe."
> > 
> > Also looks valid and I suspect is one of those that a quick look will
> > find more "offenders". I would purpose:
> > 
> > -       adev = devm_auxiliary_device_create(dev, "gpio", &st->gpio_mask);
> > +       adev = __devm_auxiliary_device_create(dev, KBUILD_MODNAME, "gpio",
> > +                                             &st->gpio_mask, client->addr);
> > 
> 
> That would still fail if there are multiple chips at the same I2C address
> on multiple I2C busses. Check drivers/gpu/drm/bridge/ti-sn65dsi86.c which has
> the same problem.

I did looked at that one but totally forgot the multiple busses
scenario.

> 
> > If there's nothing else and you agree with the above, is this something
> > you can tweak while applying or should I spin a new version?
> > 
> 
> Please respin. Also, regarding the other concerns:
> 
>   Can BIT(8) * st->rsense wrap to zero on 32-bit architectures?
>   BIT(8) is a 32-bit unsigned long and st->rsense is a u32. If a user sets a
>   very large sense resistor value via the device tree, the multiplication could
>   wrap to 0, causing a division-by-zero kernel panic. Should the divisor use
>   BIT_ULL(8)?
> 
> Unless I am missing something, this _can_ overflow. Try to provide a sense
> resistor value of 1677721600. Yes, it is unreasonable to specify such large
> rsense values, but why not just limit it such that it does not overflow ?

Yes, that's pretty much my reasoning (regarding the unreasonable
rsense). I could just make BIT_ULL() and be done with it. I can also
also cap rsense to a max value but i'm not 100% what that value would
be. Maybe 1 ohm is already more than reasonable. I can also ask internally. Any
preference on this one?

> 
> Also, for the overflow concerns, if you are sure they can not happen, I'll
> really need to write the unit test code to make sure that this is indeed
> the case.
>

Hmm, for the val * MILLI case, well it should not happen but given it
depends on user input, better if I clamp it before passing the
value to ltc4283_write_in_byte(). Yes, we clamp again inside the
write_bytes() API but not a big deal.

For the st->power_max is again one of those cases where the values would
not make sense (I think - the combination of vsense_max and rsense). Just looking
at the code, it can overflow but this one I'm not really sure how we could handle it.
Maybe clamp power_max to U8_MAX and have a warning message in ltc4283_read_power_byte() if
we overflow long in which case we need a power64 attr?

But even clamping does not make much sense here. The power limit register
is 8 bits, so if our design (rsense + vsense_max) overflows that,
there's nothing we can do other that erroring out.

- Nuno Sá

> Thanks,
> Guenter
> 

  reply	other threads:[~2026-03-31  9:48 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-27 17:26 [PATCH v8 0/3] hwmon: Add support for the LTC4283 Hot Swap Controller Nuno Sá via B4 Relay
2026-03-27 17:26 ` [PATCH v8 1/3] dt-bindings: hwmon: Document the LTC4283 " Nuno Sá via B4 Relay
2026-03-27 17:26 ` [PATCH v8 2/3] hwmon: ltc4283: Add support for " Nuno Sá via B4 Relay
2026-03-30  9:28   ` Nuno Sá
2026-03-30 15:47     ` Guenter Roeck
2026-03-31  9:48       ` Nuno Sá [this message]
2026-03-31 13:31         ` Guenter Roeck
2026-04-02 17:12           ` Nuno Sá
2026-03-27 17:26 ` [PATCH v8 3/3] gpio: gpio-ltc4283: " Nuno Sá via B4 Relay

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=acuLynb1hRFJRcEf@nsa \
    --to=noname.nuno@gmail.com \
    --cc=brgl@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=corbet@lwn.net \
    --cc=devicetree@vger.kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=linusw@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=nuno.sa@analog.com \
    --cc=robh@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox