Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Chris Morgan" <macroalpha82@gmail.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH 3/3] arm64: dts: rockchip: Add Battery Gauge to Anbernic Vita-Pro
Date: Tue, 27 Oct 2026 13:32:01 +0000	[thread overview]
Message-ID: <sashiko-outbox-186624@kernel.org> (raw)
In-Reply-To: <20261027131751.1724448-4-macroalpha82@gmail.com>

Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] power: supply: cw2217: 1000x unit error in shunt-resistor-micro-ohms
- [High] power: supply: cw2217: wrong temperature units in cw2217_get_temp()
- [High] power: supply: cw2217: NULL deref when battery-profile is omitted
- [Medium] power: supply: cw2217: missing psy_cfg.fwnode in cw2217_probe()
- [Medium] power: supply: cw2217: unsynchronized work cancel in cw2217_bat_suspend()
- [Low] arm64: dts: rockchip: cw2217 fuel gauge node named charger@64
--

commit b2629263398e52e8a7a0c66b2ac2935fa26ad154
Author: Chris Morgan <macromorgan@hotmail.com>

arm64: dts: rockchip: Add Battery Gauge to Anbernic Vita-Pro

This commit adds the Devicetree node for the Cellwise CW2217 battery fuel
gauge on the Anbernic RG Vita Pro.

> diff --git a/arch/arm64/boot/dts/rockchip/rk3576-anbernic-rg-vita-pro.dts b/arch/arm64/boot/dts/rockchip/rk3576-anbernic-rg-vita-pro.dts
> index 358dea43f9b66..6a730499148db 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3576-anbernic-rg-vita-pro.dts
> +++ b/arch/arm64/boot/dts/rockchip/rk3576-anbernic-rg-vita-pro.dts
> @@ -954,7 +954,26 @@ hym8563: rtc@51 {
>  		wakeup-source;
>  	};
>  
> -	/* cellwise,cw221X battery manager at 0x64 */
> +	cw2217: charger@64 {

[Severity: Low]
Since the CW2217 is a battery fuel gauge (registered as
POWER_SUPPLY_TYPE_BATTERY) and this I2C bus already has a separate charger
node (sgm41542: charger@3b), should this node be named fuel-gauge@64 or
battery@64 instead of charger@64?

> +		compatible = "cellwise,cw2217";
> +		reg = <0x64>;

[Severity: High]
In the underlying driver for cellwise,cw2217
(drivers/power/supply/cw2217_battery.c), cw2217_update_data() calls
cw2217_get_temp(), which computes:

	cw_bat->temp = ((int)reg / 2) - 40;

and cw2217_battery_get_property() returns that value directly for
POWER_SUPPLY_PROP_TEMP:

	case POWER_SUPPLY_PROP_TEMP:
		val->intval = cw_bat->temp;
		break;

The power_supply class ABI expects POWER_SUPPLY_PROP_TEMP in tenths of a
degree Celsius (for example, power_supply_read_temp() in
drivers/power/supply/power_supply_core.c multiplies val.intval by 100 to
convert to millidegrees Celsius):

	/* Convert tenths of degree Celsius to milli degree Celsius. */
	*temp = val.intval * 100;

Since the CW2217 temperature register has a 0.5 degree Celsius step with a
-40 degree Celsius offset, doesn't reporting ((int)reg / 2) - 40 instead of
(int)reg * 5 - 400 cause all temperature readings to be 10x too low and
discard the 0.5 degree resolution?

[Severity: Medium]
Also in drivers/power/supply/cw2217_battery.c, cw2217_probe() allocates
cw_bat->battery_workqueue without WQ_FREEZABLE, and cw2217_bat_suspend()
cancels the polling work asynchronously:

	cancel_delayed_work(&cw_bat->battery_delay_work);
	return 0;

while cw2217_bat_work() performs I2C reads and unconditionally re-queues
itself:

	ret = cw2217_update_data(cw_bat);
	if (ret)
		dev_err(cw_bat->dev, "i2c read error when update data");

	queue_delayed_work(cw_bat->battery_workqueue,
			   &cw_bat->battery_delay_work,
			   msecs_to_jiffies(cw_bat->poll_interval_ms));

If cw2217_bat_work() is already running when cw2217_bat_suspend() executes,
won't it race with I2C controller suspend and re-arm battery_delay_work
while the system is suspended unless cancel_delayed_work_sync() is used?

> +		cellwise,battery-profile = /bits/ 8 <
> +			0x5a 0x00 0x00 0x00 0x00 0x00 0x00 0x00
> +			0xab 0xb5 0xae 0xc0 0xa9 0xa4 0xcf 0xaf
> +			0x96 0xff 0xff 0xd7 0x9a 0x83 0x70 0x69
> +			0x65 0x65 0x65 0xb8 0x81 0xd9 0xaf 0xd9
> +			0xd2 0xce 0xcd 0xcb 0xca 0xc7 0xc8 0xc5
> +			0xc2 0xba 0xa8 0x96 0x8a 0x85 0x7d 0x7a
> +			0x7f 0x88 0x92 0x93 0x94 0xd3 0xff 0x5f
> +			0x20 0x00 0xab 0x10 0x00 0x91 0x68 0x00
> +			0x00 0x00 0x64 0x3c 0xa0 0x89 0x00 0x00
> +			0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xb2
> +		>;

[Severity: High]
While this board provides cellwise,battery-profile, the property is optional
in Documentation/devicetree/bindings/power/supply/cw2015_battery.yaml, and
cw2217_parse_properties() in drivers/power/supply/cw2217_battery.c leaves
cw_bat->bat_profile as NULL when it is absent:

	length = device_property_count_u8(dev, "cellwise,battery-profile");
	if (length < 0) {
		dev_warn(cw_bat->dev,
			 "No battery-profile found, using current flash contents\n");
	} else if (length != CW2217_PROFILE_SZ) {

However, cw2217_init() unconditionally calls cw2217_check_profile(), which
either passes cw_bat->bat_profile to memcmp():

	if (memcmp(bat_info, cw_bat->bat_profile, CW2217_PROFILE_SZ)) {
		dev_warn(cw_bat->dev, "Replacing stored battery profile\n");
		cw_bat->update_profile = true;
	}

or sets cw_bat->update_profile = true, causing cw2217_init() ->
cw2217_update_config() to pass cw_bat->bat_profile to regmap_raw_write():

	/* update new battery info */
	ret = regmap_raw_write(cw_bat->regmap, CW2217_BAT_PROFILE,
			       cw_bat->bat_profile, CW2217_PROFILE_SZ);

Won't probing a node without cellwise,battery-profile trigger a NULL pointer
dereference on cw_bat->bat_profile?

> +		monitored-battery = <&battery>;
> +		power-supplies = <&sgm41542>;

[Severity: Medium]
Does power-supplies = <&sgm41542> take effect with the current cw2217 driver?

In drivers/power/supply/cw2217_battery.c, cw2217_probe() registers the power
supply without setting psy_cfg.fwnode:

	psy_cfg.drv_data = cw_bat;
	cw_bat->cw_bat = devm_power_supply_register(&client->dev,
						    &cw2217_bat_desc, &psy_cfg);

When __power_supply_register() calls power_supply_check_supplies() in
drivers/power/supply/power_supply_core.c, it checks:

	/* No device node found, nothing to do */
	if (!psy->dev.fwnode)
		return 0;

Without psy_cfg.fwnode = dev_fwnode(cw_bat->dev), won't
power_supply_check_supplies() return early, ignoring the power-supplies
phandle and skipping probe deferral if sgm41542 has not probed yet?

> +		shunt-resistor-micro-ohms = <2000000>;

[Severity: High]
Is shunt-resistor-micro-ohms scaled by an extra factor of 1000 (nano-ohms
instead of micro-ohms) here, in the binding schema, and in the driver?

A 2 mOhm sense resistor is 2,000 micro-ohms, whereas <2000000> micro-ohms is
2 Ohms.

In Documentation/devicetree/bindings/power/supply/cw2015_battery.yaml, the
range for a 1 mOhm to 50 mOhm shunt resistor is also specified 1000x too
high (1 Ohm to 50 Ohms):

  shunt-resistor-micro-ohms:
    description: |
      The value, in micro-ohms, of the shunt resistor used for sampling
      the battery current.
    minimum: 1000000
    maximum: 50000000

And in drivers/power/supply/cw2217_battery.c, CW2217_USER_RSENSE is defined
as 1500 (1.5 mOhm in micro-ohms), but cw2217_parse_properties() clamps
cw_bat->user_rsense to 1000000..50000000 (which also overwrites the 1500
fallback to 1000000 whenever the property is omitted):

	ret = device_property_read_u32(dev,
				       "shunt-resistor-micro-ohms",
				       &cw_bat->user_rsense);
	if (ret) {
		cw_bat->user_rsense = CW2217_USER_RSENSE;
		dev_warn(cw_bat->dev,
			 "Using default resistor value, reported mA may be wrong\n");
	}

	/* Clamp, but also warn we're clamping due to out of range. */
	if ((cw_bat->user_rsense < 1000000) || (cw_bat->user_rsense > 50000000)) {
		cw_bat->user_rsense = clamp(cw_bat->user_rsense, 1000000, 50000000);
		dev_warn(cw_bat->dev, "Shunt resistor value out of range, setting to %d",
			 cw_bat->user_rsense);
	}

followed by cw2217_get_current() dividing cw_bat->user_rsense by 1000:

	case CW2215_ID:
	case CW2217_ID:
		cw_current = (cw_current * 1600) / (cw_bat->user_rsense / 1000);
		cw_bat->cw_current = cw_current * 1000;
		break;
	case CW2218_ID:
		cw_current = (cw_current * 3815) / (cw_bat->user_rsense / 1000);
		cw_bat->cw_current = cw_current * 1000;
		break;

Should shunt-resistor-micro-ohms use actual micro-ohms (2000 in this DT node,
and 1000..50000 in the schema and driver)?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261027131751.1724448-1-macroalpha82@gmail.com?part=3

      reply	other threads:[~2026-10-27 13:32 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-27 13:17 [PATCH 0/3] Add Cellwise CW2217 Chris Morgan
2026-10-27 13:17 ` [PATCH 1/3] dt-bindings: power: cw2015: add cw2215, cw2217, and cw2218 Chris Morgan
2026-10-27 13:22   ` sashiko-bot
2026-10-27 15:57   ` Krzysztof Kozlowski
2026-10-27 13:17 ` [PATCH 2/3] power: supply: cw2217: Add support for Cellwise cw2217 Chris Morgan
2026-10-27 13:31   ` sashiko-bot
2026-10-27 13:34   ` Shawn Lin
2026-10-27 15:46     ` Chris Morgan
2026-10-29  6:24   ` kernel test robot
2026-10-27 13:17 ` [PATCH 3/3] arm64: dts: rockchip: Add Battery Gauge to Anbernic Vita-Pro Chris Morgan
2026-10-27 13:32   ` sashiko-bot [this message]

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=sashiko-outbox-186624@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=macroalpha82@gmail.com \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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