From a5e8818e17226de35a093bd959b8471d6858668f Mon Sep 17 00:00:00 2001 From: tyeth Date: Tue, 20 Oct 2026 23:56:11 +0100 Subject: [PATCH] fwk: epr: restore standing contract when the buck transition is abandoned On boards with the RAA489300 3-level buck (tulip), enter_epr_mode() / exit_epr_mode() first collapse the charger input current to 0mA (learn mode on) and assert the PMF transition throttle, then hand off to buck_ready_for_epr() to sequence the buck mode change before the CCG EPR command is sent. If the buck readiness check exhausts its retries, the handler reverts the buck mode and goes idle - but the CCG command is never sent, so no EPR event ever arrives, and because epr_flow_pending_deferred() is only scheduled from handle_pd_epr_mode() (after buck ready), the event-loss backstop never runs either. The pd_epr_in_progress port bits, the collapsed input current and the transition throttle are all left standing: a second independent route into the latched slow state that otherwise only a physical AC removal clears. Give the abandonment branch the same cleanup the retry-exhausted branch of epr_flow_pending_deferred() already performs: clear the in-progress port bits (keeping the process flags so the existing restore block in cypd_update_port_state() runs), release the ENTER/EXIT transition throttle events, and refresh the active charge port so the input current limit is restored from the standing contract. The buck mode revert, retry count and timing are unchanged; on an abandoned exit the standing contract is the still-active EPR contract and epr_active stays 1, so a later exit attempt remains possible. This stacks on "fwk: epr: make a failed EPR transition recoverable without AC removal" (the two compose: that change covers the failure paths after the CCG command is sent, this one covers the flow being abandoned before it is sent). Issue: https://github.com/tyeth/framework-system/issues/1 Telemetry/data: https://github.com/tyeth/fw16-gpu-watchdog Compile-untested: no Zephyr build environment was available; the change uses only symbols already used in this file and was verified by read-through. Co-Authored-By: Claude Fable 5 --- zephyr/program/framework/src/cypd_ccg8.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/zephyr/program/framework/src/cypd_ccg8.c b/zephyr/program/framework/src/cypd_ccg8.c index c4026e7780..f239d41df0 100644 --- a/zephyr/program/framework/src/cypd_ccg8.c +++ b/zephyr/program/framework/src/cypd_ccg8.c @@ -583,6 +583,8 @@ static void buck_ready_for_epr(void) /* Retry mechanism */ if (++epr_buck_ctx.retry_count > 4) { + int charge_port = get_active_charge_pd_port(); + if (is_enter_epr) { CPRINTS("3Level-Buck enter epr failed, reverting to SPR mode"); board_set_buck_mode(LEVEL_BUCK_SPR); @@ -592,6 +594,16 @@ static void buck_ready_for_epr(void) } epr_buck_ctx.retry_count = 0; epr_buck_ctx.phase = BUCK_PHASE_IDLE; + /* the transition ended, restore the standing contract state */ + pd_epr_in_progress &= EPR_PROCESS_MASK; + update_pmf_events(BIT(PD_PROGRESS_ENTER_EPR_MODE), 0); + update_pmf_events(BIT(PD_PROGRESS_EXIT_EPR_MODE), 0); + if (charge_port != -1) { + int controller = PORT_TO_CONTROLLER(charge_port); + int port = PORT_TO_CONTROLLER_PORT(charge_port); + + cypd_update_port_state(controller, port); + } return; }