[RFC PATCH v2 0/3] power: supply: read-only CellWise CW2017 monitor for Redmi Go

From: Kupreenko Danila

Date: Thu Oct 29 2026 - 15:35:08 EST


From: Kupreenko Danila <Keckerz@xxxxxxxxx>

Add a read-only power_supply driver for the CellWise CW2017 fuel gauge,
its Devicetree binding, and the Xiaomi Redmi Go (tiare) I2C node.

Unlike CW2015, CW2017 has a different register map and battery profile
protocol. The driver requires a gauge already initialized with a valid
battery profile; it reads voltage, integer SOC and temperature but never
writes CONFIG, changes the battery profile or resets the chip. Charging
status is unknown; presence is not inferred.

The CW2017 source is an independent implementation assisted by Codex
(GPT-6). Firefly was consulted later as a behavioral reference, not as
a source of copied code. AI assistance is disclosed in commit trailers.

Hardware testing on Xiaomi Redmi Go (tiare), postmarketOS, Linux
7.1.3-msm89x7, using the original pre-v2 driver source (R5):
- module auto-loaded and bound to I2C device 2-0063;
- running srcversion matched the locally built R5 module;
- capacity, voltage and temperature appeared in power_supply sysfs;
- three consecutive measurements remained accessible;
- udevadm monitor observed power_supply change events, including
voltage and temperature changes at roughly 30-second cadence.

The v2 change preserves the last completed sample across system suspend
instead of overwriting sample.error with a synthetic -ENODATA. Polling
is still cancelled synchronously during suspend and an immediate poll
is queued on resume. The new sample can therefore be compared against
the actual pre-suspend state.

Host regression tests reproduced three v1 issues: spurious change
notifications for unchanged measurements after resume, missing
availability notifications when the first post-resume I2C read failed,
and artificial -ENODATA on early thermal temperature reads.

All three cases pass after the fix. Further checks cover valid/invalid
transitions, temperature reads during a blocked post-resume poll, and
64 suspend cancellation and 64 teardown cycles in a threaded model.
ASan/UBSan, ThreadSanitizer, ARM64 PM/thermal build and MODPOST, a
no-PM build, and sparse checks also passed.

The R5 hardware results apply to the original driver source, not to
the modified v2 suspend path. The v2 suspend change has not been tested
on the phone. Mainline Linux 7.3 has not been booted on Redmi Go.
Hardware PM/unbind, power cost, calibration, temperature-source
provenance and induced I2C error recovery remain untested.

Early post-resume temperature reads may return a stale cached value
until the first poll completes. The driver remains a monitor, not a
battery safety controller.

Open review questions include policy for already-initialized gauges,
3-attempt probe retries, nominal 30-second polling and up to 300-second
backoff after failures, and event frequency with small voltage changes.

Changes since v1:
- Preserve the cached sample across suspend.
- Fix spurious resume notifications and missed availability changes.
- Avoid artificial -ENODATA for early thermal temperature reads.
- Add host PM regression and concurrency testing.
- Clarify the scope of R5 hardware validation.

Link: https://lore.kernel.org/r/179329639684.489944.6322623410181934358.cw2017-first-public-rfc@xxxxxxxxx

Kupreenko Danila (3):
dt-bindings: power: supply: add CellWise CW2017 fuel gauge
power: supply: add read-only CW2017 battery monitor
arm64: dts: qcom: tiare: describe CW2017 fuel gauge

.../power/supply/cellwise,cw2017.yaml | 52 +++
MAINTAINERS | 7 +
.../boot/dts/qcom/msm8917-xiaomi-tiare.dts | 9 +
drivers/power/supply/Kconfig | 14 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/cw2017_battery.c | 367 ++++++++++++++++++
6 files changed, 450 insertions(+)
create mode 100644 Documentation/devicetree/bindings/power/supply/cellwise,cw2017.yaml
create mode 100644 drivers/power/supply/cw2017_battery.c

Range-diff against v1:
1: 450435406 = 1: 450435406 dt-bindings: power: supply: add CellWise CW2017 fuel gauge
2: 9439176a8 ! 2: 6c76f0f28 power: supply: add read-only CW2017 battery monitor
@@ Commit message
reference. Host tests exercise the actual driver and mainline uevent
helpers with mocked kernel infrastructure.

- The same driver source was built for Linux 7.1.3-msm89x7 and tested
- on Xiaomi Redmi Go (R5). Module autoload, I2C binding, battery
- measurements and kernel power_supply change events were verified.
- The mainline kernel itself was not booted on this device.
- Hardware suspend/resume, teardown, calibration and energy use
- remain untested.
+ The pre-v2 driver source was built for Linux 7.1.3-msm89x7
+ and tested on Xiaomi Redmi Go (R5). Module autoload, I2C
+ binding, battery measurements and power_supply change events
+ were verified.
+
+ The v2 suspend change passed host PM regression tests, but
+ was not hardware-tested. The mainline kernel itself has not
+ been booted on Redmi Go. Hardware suspend/resume, teardown,
+ calibration and energy use remain untested.

Assisted-by: LLM sparse
Signed-off-by: Kupreenko Danila <keckerz@xxxxxxxxx>
@@ drivers/power/supply/cw2017_battery.c (new)
+ struct cw2017 *cw = dev_get_drvdata(dev);
+
+ cancel_delayed_work_sync(&cw->work);
-+ mutex_lock(&cw->lock);
-+ cw->sample.error = -ENODATA;
-+ mutex_unlock(&cw->lock);
+
+ return 0;
+}
3: 46d6f633f = 3: 1ceaa947d arm64: dts: qcom: tiare: describe CW2017 fuel gauge

base-commit: c339f4010dea8b0d754f84ace70cd1b089878ef8
--
2.56.0