Skip to content

power: enable 30 W charging on Pocket EVO via direct-charge policy - #258

Open
jesherman wants to merge 1 commit into
armada-os:mainfrom
jesherman:codex/pocket-evo-hl7139-charging
Open

power: enable 30 W charging on Pocket EVO via direct-charge policy#258
jesherman wants to merge 1 commit into
armada-os:mainfrom
jesherman:codex/pocket-evo-hl7139-charging

Conversation

@jesherman

@jesherman jesherman commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

power: enable 30 W charging on Pocket EVO via direct-charge policy

Adds the Pocket EVO userspace charging policy for armada-os/armada-packages#35.

The kernel support exposes the required controls, but the charge pumps still need a sequenced handoff. This service:

  • runs only when both EVO HL7139 supplies are present
  • quiesces the Qualcomm charger (13 mA input-current vote), requests a safe PPS voltage, and enables the master and slave pumps
  • watches battery and pump current, voltage, temperature, health, and state of charge
  • tapers near the factory voltage limit and restores ordinary charging whenever the session ends
  • re-establishes a session only after its full eligibility re-check — so a session interrupted by suspend (pumps are disabled by the kernel on suspend, see armada-packages#35) is not blindly resumed

Tier 1: raises the PPS target cap to 10.5 V with matching VIN guards, so a 3 A PD contract delivers ~31 W instead of ~26 W. Software-only — no kernel rebuild (the driver's 10 V VIN enable gate is checked only at enable time, and pumps are enabled at <=9.2 V; the ramp to 10.5 V never re-triggers it).

Measured results (Pocket EVO, kernel 7.2.0-rc7, 3 A PD contract)

  • Stock Armada: 9.6 V × 1.87 A ≈ 17.9 W at the wall
  • Previous (9.9 V cap): ~25.9 W at the wall
  • Tier 1 (10.5 V cap): ~30.5 W at the wall, 32.1 W source, 27–28 W at the pump inputs, ~1.53/1.52 A pump balance, ~3.0 A combined input
  • Sustained 20+ minutes under game load (75–90% SOC): no guard trips, no faults, battery 28–30 °C, pump die 62–63 °C and flat
  • Idle at 89% SOC: battery pulls ~5.1 A at 10.2 V with no ramp stall, die 53–56 °C
  • Cold-boot verified previously: the policy auto-starts a session after boot (no manual intervention), ramps through the inrush window

Key calibration finding

The HL7139 pump ADC over-reads current by ~4% (wall meter 2.93 A vs 3.05 A sysfs at 9.85 V). The 3 A PD contract therefore reads ~3.12 A in sysfs. The combined-input guard (3.12 A, 3-sample debounce) and the ramp/back-step band (3.08 A) are calibrated against that offset — the original 3.05 A guard fired on sysfs noise and never let the ramp pass ~9.9 V.

Notes

  • Without this PR charging remains capped at ~18 W (9 V / 2 A plateau)
  • The suspend interaction is handled by the kernel driver (pumps off on suspend) + this policy's eligibility re-check on resume
  • The PPS voltage restore in cleanup() writes unconditionally: the firmware reports USB protocol type SDP even when its separate adapter type is PD-PPS, so a usb_type grep gate could never match. The kernel setter checks the raw adapter type and rejects non-PPS adapters itself

@jesherman jesherman changed the title power: add Pocket EVO direct-charge policy power: enable 28w charging on Pocket EVO via direct-charge policy Aug 16, 2026
@jesherman

Copy link
Copy Markdown
Contributor Author

im going to move this back to draft - there is definitely a driver dependency but performance seems intermittent maybe from policy changes. need to test more.

@jesherman

jesherman commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

Independent verification + hybrid hardening (2026-08-18)

Tested on a Pocket EVO with the hybrid build: this policy + the kernel pieces from armada-os/armada-packages#35 (0901 + 0063 + 0903 + 0904). Full cycle run from a 10% SOC start, including an 11-minute deep suspend.

Confirmed working

  • Pumps auto-bind from DT at boot, policy auto-starts a direct-charge session once SOC ≥ 10%
  • 25.9 W source / 24.4 W at the pump inputs at 15-18% SOC, balanced 1.47/1.45 A pump load, healthy temps (44-45 °C die), no kernel faults
  • ICL handoff verified: 13 mA vote drops USB input current 1.87 A → 0 A, battery goes from charging to discharging at ~4.9 A, readback frozen at negotiated 3 A
  • Unplug mid-session: guard trips instantly, pumps off, Qualcomm restored; policy re-establishes after the 60 s backoff
  • Deep suspend (mem): kernel disables both pumps on PM_SUSPEND_PREPARE (0903), pumps stay off the entire suspend, policy re-establishes fresh after resume
  • Battery STATUS=Charging during direct charge (0904) — UPower/SteamOS show the correct icon; previously the firmware reported Discharging because it only tracks its own (quiesced) buck

Fixes this test run found (now in the PR branches)

  1. PPS voltage restore in cleanup() never firedgrep '\[PD_PPS\]' usb_type can never match: firmware reports protocol type SDP even when adapter type is PD-PPS (usb_type is a static capability list). Now writes unconditionally; the kernel setter validates the adapter type.
  2. Low-SOC startup -ERANGE — 8.2 V min PPS target left VIN too close to the driver's 8.0 V enable floor; master pump sags VIN to ~7.98 V → slave enable rejected. Raised clamp to 8.8 V.
  3. Enable inrush tripped per-pump current guard — watch loop sampled immediately after enable, caught a 2.68 A transient; added 3 s settle.
  4. Battery icon said Discharging while charging (kernel, 0904) — see above.

Honest numbers

  • Stock Armada: ~17.9 W at the wall (9.6 V × 1.87 A)
  • With this PR set: 25-26 W at the pump inputs; 3.05 A combined-input guard is conservative (tripped once at 3.06 A; sustained run sits 2.89-2.93 A)
  • All figures are source/request and device/pump-input power; the wall meter reads ~1 W higher than sysfs device

Remaining

  • Taper at 4.45 V and 88% SOC session end verify naturally as the battery climbs (blocking nothing)

@jesherman
jesherman marked this pull request as ready for review August 18, 2026 11:09
@jesherman
jesherman force-pushed the codex/pocket-evo-hl7139-charging branch 2 times, most recently from 4bdd526 to dd6db44 Compare August 18, 2026 11:37
@jesherman

Copy link
Copy Markdown
Contributor Author

Guard debounce added after cold-boot verification (2026-08-18)

During a cold-boot test the policy auto-started a session and ramped normally (2.43 → 2.89 → 3.02 A), then a single 0.5 s sample at 3.058 A (8 mA, ~0.3 % over the 3.05 A combined-input guard) ended the session — the controller was already pulling the PPS target back at that point. The 3.05 A guard value is correct (it must sit above the 2.88–2.95 A control band and below the 3 A PD contract), but a one-sample tripwire is too trigger-happy for a settling ramp.

The guard now requires 3 consecutive out-of-range samples (~1.5 s) before tearing down; a sustained overdraw still ends the session immediately. Verified on-device: the restart ramp crossed the same window and held ~26 W without a trip.

Adds the Pocket EVO userspace charging policy for armada-os/armada-packages#35.

The kernel support exposes the required controls, but the charge pumps still
need a sequenced handoff. This service:

- runs only when both EVO HL7139 supplies are present
- quiesces the Qualcomm charger (13 mA input-current vote), requests a safe
  PPS voltage, and enables the master and slave pumps
- watches battery and pump current, voltage, temperature, health, and state
  of charge
- tapers near the factory voltage limit and restores ordinary charging
  whenever the session ends
- re-establishes a session only after its full eligibility re-check — so a
  session interrupted by suspend (pumps are disabled by the kernel on
  suspend, see armada-packages#35) is not blindly resumed

Tier 1: raises the PPS target cap to 10.5 V with matching VIN guards, so a
3 A PD contract delivers ~31 W instead of ~26 W.

Measured results (Pocket EVO, kernel 7.2.0-rc7, 3 A PD contract):

- Stock Armada: 9.6 V x 1.87 A ~= 17.9 W at the wall
- Previous (9.9 V cap): 25.9 W source / ~26 W at the wall
- Tier 1 (10.5 V cap): ~30.5 W at the wall, 32.1 W source, 27-28 W at the
  pump inputs, ~3.0 A combined pump input, ~1.53/1.52 A pump balance
- Sustained 20+ minutes at 75-90% SOC under game load with no guard trips,
  no faults; battery 28-30 C, die 62-63 C and flat
- Idle at 89% SOC: battery pulls ~5.1 A at 10.2 V (no stall), die 53-56 C

Key calibration finding: the HL7139 pump ADC over-reads current by ~4%
(wall meter 2.93 A vs 3.05 A sysfs at 9.85 V), so the 3 A contract reads
~3.12 A in sysfs. The combined-input guard (3.12 A, 3-sample debounce) and
the ramp/back-step band (3.08 A) are calibrated against that offset — the
original 3.05 A guard fired on sysfs noise and never let the ramp pass
9.9 V.

Notes:
- Without this PR charging remains capped at ~18 W (9 V / 2 A plateau)
- The suspend interaction is handled by the kernel driver (pumps off on
  suspend) + this policy's eligibility re-check on resume
- The PPS voltage restore in cleanup() writes unconditionally: the firmware
  reports USB protocol type SDP even when its separate adapter type is
  PD-PPS, so a `usb_type` grep gate could never match. The kernel setter
  checks the raw adapter type and rejects non-PPS adapters itself
@jesherman
jesherman force-pushed the codex/pocket-evo-hl7139-charging branch from dd6db44 to 70667ae Compare August 18, 2026 19:06
@jesherman jesherman changed the title power: enable 28w charging on Pocket EVO via direct-charge policy power: enable 30 W charging on Pocket EVO via direct-charge policy Aug 18, 2026
@jesherman

Copy link
Copy Markdown
Contributor Author

Tier 1 update — 30.5 W at the wall, validated on-device (2026-08-18)

Raised the PPS target cap to 10.5 V with matching VIN guards. Software-only: the driver's 10 V VIN enable gate in armada-packages#35 is checked only at enable time, and this policy enables the pumps at ≤9.2 V, so no kernel rebuild was needed.

Measured (3 A PD contract, kernel 7.2.0-rc7):

  • Sustained 20+ min under game load (75–90% SOC): ~30.5 W wall / 32.1 W source / 27–28 W at pump inputs, ~3.0 A combined input, 1.53/1.52 A balance, battery 28–30 °C, die 62–63 °C flat, no guard trips
  • Idle at 89% SOC: battery pulls ~5.1 A at 10.2 V with no ramp stall, die 53–56 °C
  • Session ends cleanly at the 90% SOC guard; unplug teardown is clean

Key calibration finding: the HL7139 pump ADC over-reads current by ~4% (wall meter 2.93 A vs 3.05 A sysfs at 9.85 V). The 3 A contract reads ~3.12 A in sysfs, so the combined-input guard (3.12 A, 3-sample debounce) and ramp band (3.08 A) are calibrated to the meter, not the raw sysfs value — the original 3.05 A guard fired on sysfs noise and capped the ramp at ~9.9 V.

Battery-current ramp gates (back-step 5.5 → 6.5 A, ramp 5.0 → 6.5 A) were raised to match Tier 1's ~6.2–6.5 A idle battery draw; the old gates would stall the ramp at ~29 W when the device is idle and the battery wants full current.

Note: an idle low-SOC (below ~70%) soak at 10.5 V is still outstanding — current data covers loaded (75–90%) and idle (89%) states.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant