RK3326/RK3566: battery, SD card and suspend/resume fixes - #3220
RK3326/RK3566: battery, SD card and suspend/resume fixes#3220Jacob-Matthew-Cook wants to merge 1 commit into
Conversation
8b6ad76 to
f716dd8
Compare
d215a68 to
35932a7
Compare
678a2bd to
c1b525f
Compare
e603e5b to
0f03187
Compare
749e0c6 to
4fc0dec
Compare
1d99dc2 to
a2e35d8
Compare
5e33dd7 to
19160d9
Compare
|
Just to comment on this. I feel that rk817 and mmc patches should be done in alignment with upstream. For rk817 macromorgan is upstream. For mmc, I feel uneasy having custom patches. It would be good hear what kernel maintainers say about these. The other stuff looks good to me, though I'd ask someone with experience of batteryplus to review that. |
You make a good point. We can keep this as a draft if you'd like while those changes are reported upstream. Regarding the mainline kernel SD card patches:
I fully respect the opinions/decisions from the senior devs/maintainers. If folks prefer I leave this as a draft, that is fine with me. Lastly, if you would like me to report these mainline kernel issues upstream now, I can do that. However, I am not sure what we should do in the meantime, nor am I confident they will accept these changes. |
5d90dbd to
91d152a
Compare
|
Patch 0008 empirically proven on the original failing hardware. GKD Pixel2, 20260824 test build, the same SD512 461 GiB boot card that produced the original hard wedge; kernel log streamed off-device over the USB gadget network during the test so no evidence could be lost to a storage stall. Eight rapid suspend/resume cycles reproduced the failure twice; both recovered: Post-recovery checks, all clean: no |
91d152a to
542c69f
Compare
|
Two (unrelated to this PR's original scope) kernel regressions found & fixed while testing this branch: dwc2 crashes on system sleep Both come from the same root cause: the current kernel's new dwc2 PM code backs up/restores the controller's registers across system sleep, and it trusts controller state that a never-fully-activated controller doesn't have. Found on the GKD Pixel 2 (RK3326/PX30); both were root-caused from pstore/ramoops captures and both fixes are verified on the previously 100%-reproducing hardware. The patches apply cleanly to both kernels this branch ships (7.1.2 RK3326, 7.0.2 RK3566). Bug 1 — NULL deref on resume ( Bug 2 — hard hang on suspend entry after boot with no cable ( This PR is now a draft pending upstream submission: both patches are in |
Fuel gauge: final design (v3, The core hardware finding, refined by instrumented testing: the RK817 coulomb counter is erratic across suspend (measured 69% capture of a metered charge on one sleep, ~139% on another) while counting reliably through powered-off charging — and every corrective signal the driver could read live ( The shipped series corrects from persisted evidence, never live observation:
Hardware validation (all on RG353M, kernel values via SSH, not the UI):
Design docs (current): plain-terms overview · findings · three-lane flow chart. @macromorgan the series (your two patches as revised + the sleep-correction third) is upstream-formatted with these measurements in the commit messages — ready for your read whenever suits. |
a91bd1e to
45cf054
Compare
|
Good news on the dwc2 crashes: released builds are not affected. I tested the latest stable (20260901) on the Pixel 2 — no crashes, even though it ships the exact same 7.1.2 dwc2 code with none of the fixes. The reason: both bugs need the USB controller sitting in gadget/device mode while unplugged, and the only thing that puts it there is this PR's own USB role management (the ID-follow fix for the stuck-5V OTG port). Upstream's simpler usbgadget never configures the controller that way, so stable never steps on the landmines. What that means: the kernel bugs are real but latent outside this PR, the exposure and the fixes ship together here (no window where a build has one without the other), and there's no urgency for stable. Cc: stable still applies upstream — any system that binds a USB gadget with no cable attached and then suspends on battery can hit these. |
45cf054 to
f01ce97
Compare
|
Fuel gauge: v4 ( Chris asked for a boot ladder he could understand and support, and for The whole design in three sentences: the coulomb counter is the source; a rested voltage corrects it; sleep gets a time × current credit.
Why not voltage-first after a power-off: Verification: applies at zero fuzz on 7.1.2 and 7.0.2, compiles clean, checkpatch clean. Every case recorded in v1–v3 resolves to the same value under v4 (in each of them v3 ended up taking the counter anyway). Pending on this build: off-charge boot, a sleep-charge from ~40% (no taper or full-cap flattery), one unplugged overnight sleep, warm-reboot continuity. Follow-up (same day), on @macromorgan's point that Docs rewritten to v4, same links: plain-terms overview · findings · three-lane flow chart. Builds for both devices are running now; the pre-release assets will be swapped in place when they finish and I will note it here. @macromorgan the 002 subject is now "Resolve boot state of charge from the columb counter"; your From line and DCO chain are unchanged, and |
rk817_charger: carry Chris Morgan's series (developed jointly) plus a sleep correction, mirroring the BSP driver. Boot: on a first boot (BAT_CON) estimate from PWRON_VOL as before; otherwise take the columb counter, which keeps counting while the system is off (an RG353M saved at 74% and charged 1.5h powered off booted at full), falling back to the nvram-saved soc only when the counter reads invalid. PWRON_VOL is no longer consulted after a power-off: a plugged power-on samples it under charge current (above the RG353M pack's maximum), and an RG DS held 2.63V in it while running. FG_INIT and OFF_CNT are not read. Awake, the relax pair is re-read every 8 seconds and reseeds the counter on >5% divergence. Across sleep, where the counter is erratic (69% and 139% of a metered charge captured on two sleeps), suspend stamps boottime, charge state and current and clears the relax flags; resume recomputes soc from the counter, recalibrates from a pair latched during that sleep, else credits elapsed*current where a charging sleep fell short, saturating at full. PWRON_VOL is exposed as POWER_SUPPLY_PROP_VOLTAGE_BOOT and the current rested pair as POWER_SUPPLY_PROP_VOLTAGE_OCV (-ENODATA while none is available), and the saved soc's sanity check no longer clamps every restored charge to 10%. Add "factoryreset rk817-fuelgauge" with a quirk exporting DEVICE_RK817_FUEL_GAUGE (listed in 999-export so ES sees it) for the matching menu entry - ROCKNIX/emulationstation-next#30. The reset powers off rather than rebooting: PWRON_VOL only refreshes on a real power-on, so the post-reset estimate needs one. dwc2: two system-sleep crashes from the PM register save/restore trusting state a never-activated controller does not have, both root-caused from pstore captures on a GKD Pixel2. Resuming on battery after the USB power domain shuts off dereferenced eps_in[i] without a NULL check (PX30 has no ep2in - guaranteed oops mid-resume); booting with no cable leaves the core soft reset timed out and ignored, and suspend's register backup then stalls the AHB on the clock-dead core - a hard hang only a watchdog can recover. Guard the desc-DMA workaround per direction, and track the failed reset so the PM callbacks leave the controller alone until a later successful reset (cable plug-in) revives it. GKD Pixel2: power off on measured voltage_avg, not the gauge percent. batteryplus: replace the S922X-only wiring with a BATTERYPLUS_SUPPORT option (S922X, RK3326, RK3566), teach it voltage_avg, and point RetroArch's battery display at /tmp/battery.percent. Its anchors now come from the battery's own DT data rather than assuming a 4.2V pack, so the Pixel2's 4.35V cell no longer reads 100% across the top third of its range. The full anchor is only seeded, never overwritten, so the daemon still learns. GKD Pixel2 USB-OTG: usbgadget follows the extcon ID pin, and dwc2 releases vbus-supply when a role switch leaves host. Mainline never drops it, so the port kept sourcing 5V and could not charge. mmc: an optional cache-enable failure no longer aborts card init, and a failed resume is retried after a power cycle. Both removed a mounted card - ext4 replays its journal, exFAT is left corrupted, and on a boot medium the machine wedges. 99-automount.rules now handles ACTION=="remove" so a card that comes back is remounted instead of leaving /storage/roms empty until reboot. RK3566 GPU: apply RK3326's mali-bifrost regulator-balance patch, and keep mali_kbase the sole owner of the GPU clocks. input_sense: get_devices() never retried (RETRY started at its own limit) and appended duplicates, so a restart could attach to an incomplete set and lose the volume keys. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
f01ce97 to
876e5c2
Compare
Summary
Battery, SD-card and suspend/resume fixes for the RK817-based RK3326/RK3566 handhelds, plus two mmc fixes that apply to every device.
RELAX_STS,CHARGE_FINISH) gone again before the monitor runs after wake; the BSP driver's resume-time compensations exist for exactly this. The fix is @macromorgan's series extended to correct from persisted evidence: at boot, counter corroborating the saved soc within fcc/10 wins, divergence is arbitrated by measured voltage (rested relax pair, elseOFF_CNT-proven-freshPWRON_VOL, else the counter per the BSP's halt handling), and after a genuine off interval voltage overrides even an agreeing counter — a blind counter agrees with a stale save. Across sleep: suspend stamps time/charge-state/current and clears the relax flags; resume recalibrates from a pair latched during that sleep, else credits elapsed × current, saturating at full. Full write-up: findings / flow chart. Also fixes the saved-soc sanity clamp (10%→100%).factoryreset rk817-fuelgaugepowers off so the next power-on samplesPWRON_VOLfresh (gated ES entry; companion: GuiMenu: add RK817 fuel gauge reset entry emulationstation-next#30). Pixel2 powers off on measuredvoltage_avgrather than the gauge.eps_in[i]without a NULL check; on dedicated-direction-endpoint cores (PX30: no ep2in) that's a guaranteed oops mid-resume — frozen screen, dead device. (2) Booted with no cable, the PHY never starts its clock, the core soft reset at gadget bind times out and the error is ignored; suspend's register backup then stalls the AHB on the clock-dead core — hard hang, no oops, only a hardware watchdog recovers. Both root-caused from pstore/ramoops captures (in the commit messages), both fixes verified on the reproducing hardware.BATTERYPLUS_SUPPORToption (S922X/RK3326/RK3566); acceptsvoltage_avg(RK817 has novoltage_now); RetroArch reads/tmp/battery.percent. Its voltage anchors now come from the battery's own DT data (ocv-capacity-table-0, falling back tovoltage_{min,max}_design) rather than assuming a 4.2V pack, so the GKD Pixel2's 4.35V cell no longer reads 100% across the top third of its range. The full anchor is seeded only when absent, so the daemon's own learning still wins.usbgadgetfollows the extcon ID pin; dwc2 releasesvbus-supplyon host→device, which mainline never does.99-automount.ruleshandlesremove, so a card that returns is remounted instead of leaving/storage/romsempty until reboot. Note the two interact: a card that fails cache-enable now runs cache-less rather than being re-initialised by the resume retry.mali_kbasesole owner of the GPU clocks.get_devices()never retried (RETRYstarted at its own limit) and appended duplicates, so a restart could attach to an incomplete set and lose the volume keys.Testing
Built and tested on a GKD Pixel2 (RK3326) and an RG353M (RK3566).
dwc2_resumereturning 0 in ~11 ms per cycle (the restore path executing, not skipped).unbalanced disables for vdd_gpufired on every suspend before the mali-bifrost patch; 9 cycles after it: zero warnings, GPU healthy.voltage_ocvsemantics confirmed on hardware by @macromorgan; suspend/resume confirmed under Rockchip BL31; the sleep-blindness, dead relax gate, invisibleCHARGE_FINISH, and reboot-at-full re-anchor all measured on RG353M. Kernel patches apply at strict zero fuzz (-F0) to both consumer kernels of the shared Rockchip tree (7.0.2 RK3566/76, 7.1.2 RK3326); the mmc patches additionally to 6.18.45 (RK3399) and 7.2 (H700/SM6115/SM8xxx).slept chargingdmesg line and a corrected percentage), overnight rest (recalibration at wake), off-charge boot (off-time voltage overrides), and the reset tool'sBAT_CONset direction.45cf0548a0, kernel marker strings verified present.Additional Context
Affects every RK817 handheld booting the mainline u-boots (RG353x/RG503, RG-DS, Powkiddy X55/RGB30/RK2023, GKD Pixel2, odroid-go, RG351, GameForce Chi). The gauge fix is kernel-side and a mainline candidate, so it covers stock bootloaders too —
odroid-go2,anbernic-rgxx3andpinetab2-rk3566defconfigs all enable the plug-in shutdown.DEVICE_USB_ROLE_FOLLOW_IDis Pixel2-only.BATTERYPLUS_SUPPORTis opt-in per device, but note the anchor change does alter reported percentages on every device that enables it: measured against each board's own OCV table, worst-case error drops from +54 to +12 points on the Pixel2 and from +39 to +17 on odroid-go2, since the stock 3250/4000 anchors were not right for 4.2V packs either.AI Usage
Did you use AI tools to help write this code? YES
🤖 Generated with Claude Code