Skip to content

Commit 74e439d

Browse files
mkornreichclaude
andcommitted
fwk: lotus: clamp typec_safety_level in update_safety_power_limit()
In LEVEL_TYPEC_1_5A the Type-C safety sub-level was incremented and decremented without bounds, while the ladder only stepped down when the counter was exactly TYPEC_SAFETY_LEVEL_0 (and only stepped up when it was exactly TYPEC_SAFETY_LEVEL_3). The hard throttle applied in LEVEL_PROCHOT cuts the battery discharge current, so the first tick after entering LEVEL_TYPEC_1_5A is usually a decrease tick: the counter goes 0 -> -1 -> -2 ... and never equals TYPEC_SAFETY_LEVEL_0 again. safety_level then never returns to LEVEL_PROCHOT, so throttle_ap(THROTTLE_OFF, THROTTLE_HARD, THROTTLE_SRC_BAT_DISCHG_CURRENT) is never called and the APU stays hard throttled (~600 MHz) until the EC resets, on AC as well as battery. Every tick, cypd_update_safety_table() also indexes the 4-entry safety_table[] with the out-of-range level and passes the result to cypd_select_pdo(); the PD controllers reject it and the EC logs "SET CCG_SELECT_REG failed" about once a second. Clamp the counter to [TYPEC_SAFETY_LEVEL_0, TYPEC_SAFETY_LEVEL_3]. Fixes: 9ff6a96 ("fwk: 16-inch: Reduce the Type-C current once the battery exceed discharge current limit") BRANCH=fwk-tulip-29169 BUG=FrameworkComputer/SoftwareFirmwareIssueTracker#243 TEST=Host simulation of the LEVEL_PROCHOT..LEVEL_COUNT cases. Without this change, PROCHOT followed by 20 decrease ticks leaves the ladder at LEVEL_TYPEC_1_5A with the counter at -20 and the throttle on; with it, the ladder returns to LEVEL_NORMAL and releases the throttle. 1,000,000 random ticks keep the counter within [0, 3]. Not yet built or run on hardware. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent c6575ef commit 74e439d

1 file changed

Lines changed: 11 additions & 2 deletions

File tree

‎zephyr/program/framework/lotus/src/cpu_power.c‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,21 @@ static int update_safety_power_limit(int active_mpower)
250250
}
251251
break;
252252
case LEVEL_TYPEC_1_5A:
253+
/*
254+
* typec_safety_level indexes safety_table[TYPEC_SAFETY_LEVEL_COUNT]
255+
* in cypd_update_safety_table(), so keep it in [LEVEL_0, LEVEL_3].
256+
* Unclamped, a decrease right after entering this level drove it
257+
* negative: the ladder never stepped back to LEVEL_PROCHOT, so
258+
* THROTTLE_SRC_BAT_DISCHG_CURRENT was never released.
259+
*/
253260
if (level_increase) {
254-
typec_safety_level++;
261+
if (typec_safety_level < TYPEC_SAFETY_LEVEL_3)
262+
typec_safety_level++;
255263
if (typec_safety_level == TYPEC_SAFETY_LEVEL_3)
256264
safety_level++;
257265
} else {
258-
typec_safety_level--;
266+
if (typec_safety_level > TYPEC_SAFETY_LEVEL_0)
267+
typec_safety_level--;
259268
if (typec_safety_level == TYPEC_SAFETY_LEVEL_0)
260269
safety_level--;
261270
}

0 commit comments

Comments
 (0)