- LBC supervisor v1..v4 (linux/patches/b10b3-lbc-supervisor-v3.patch + b10/b10b3/lbc-v3-to-v4-fault-clamp.diff): CHARGING 4.20 V/450 mA -> HOLD 4.05 V after 60 min CV -> battery -> new cycle on USB insert; FAULT = VDD_MAX 4.00 V clamp - RAM tests C/B/D/D2/D3/D4 (safety timer only ends fast charge), B10B-4 actuator audit (VDD_MAX works, USB_SUSP does not), B10B-5 FAULT clamp regression, production run, warm reboot via PON reboot reason - cache = B10B-5 c3732515 (HW EDL write, readback + full partition verify), class-A persistent validation - test-only hooks/images are not part of the production kernel; images with the AP PSK are not published
79 lines
3.8 KiB
Diff
79 lines
3.8 KiB
Diff
--- src-b10b3/drivers/power/supply/pm8916_lbc.c 2026-10-03 21:11:03.584000000 +0600
|
|
+++ src-b10b5/drivers/power/supply/pm8916_lbc.c 2026-10-04 20:07:45.456000000 +0600
|
|
@@ -298,7 +298,7 @@
|
|
|
|
|
|
/*
|
|
- * Aurora B10B-3 v3 charger supervisor: CHARGE -> HOLD -> (battery) -> CHARGE.
|
|
+ * Aurora B10B-3 v4 charger supervisor: CHARGE -> HOLD -> (battery) -> CHARGE (v4 = v3 + FAULT safe clamp, B10B-5).
|
|
* Facts it relies on (B10A/B10B-2/B10B-3 tests): CHG_STATUS 00 + USB path 01 is a latch, not an end-of-charge;
|
|
* no hardware EOC was seen with BOOT_DONE set; CHG_EN = 0 does not stop the charger; verified levers are VDD_MAX,
|
|
* IBAT_MAX and the CHG_CTRL 0x21 -> 0xa0 edge (releases the latch). All decisions use the calibrated VADC VBAT.
|
|
@@ -306,7 +306,10 @@
|
|
* CHARGING: entered on USB insert/probe: BOOT_DONE, VDD_MAX = charge level, IBAT_MAX, restart edge.
|
|
* -> HOLD after the CV loop with VBAT >= full-min lasted cv-hold-minutes; 00/01 latch -> restart, stay.
|
|
* HOLD: only VDD_MAX = hold level; 00/01 latch -> restart edge, VDD_MAX stays at the hold level.
|
|
- * FAULT: logical only (VBAT > 4.25 V or CHG_FAILED): no restarts. There is no verified software stop.
|
|
+ * FAULT: entered on VBAT > 4.25 V or CHG_FAILED; on entry only VDD_MAX = 0x00 (FAULT safe clamp to 4.00 V, B10B-4) +
|
|
+ * readback; no further charger writes, no restarts; left only by USB removal (-> NO_USB) or reboot.
|
|
+ * The clamp is NOT a guaranteed charge disconnect: with VBAT > 4.00 V charging stops and the board runs
|
|
+ * from the battery; with VBAT < 4.00 V the charger may still charge up to 4.00 V.
|
|
*/
|
|
static void lbc_supv_log(struct pm8916_lbc_charger *chg, int to, const char *why)
|
|
{
|
|
@@ -318,7 +321,7 @@
|
|
chg->log[i].vbat = chg->vbat_uv;
|
|
chg->log[i].why = why;
|
|
if (to == LBC_ST_FAULT)
|
|
- dev_crit(chg->dev, "supervisor %s -> FAULT (%s), vbat %d uV: restarts blocked, NO software stop available\n",
|
|
+ dev_crit(chg->dev, "supervisor %s -> FAULT (%s), vbat %d uV: restarts blocked, FAULT safe clamp to 4.00 V\n",
|
|
lbc_state_name[chg->state], why, chg->vbat_uv);
|
|
else
|
|
dev_info(chg->dev, "supervisor %s -> %s (%s), vbat %d uV\n", lbc_state_name[chg->state],
|
|
@@ -394,18 +397,36 @@
|
|
return true;
|
|
}
|
|
|
|
+/*
|
|
+ * FAULT safe clamp to 4.00 V (B10B-4): the only charger write on FAULT entry is VDD_MAX = 0x00 (lowest LBC step).
|
|
+ * Not a guaranteed charge disconnect - below 4.00 V the charger may still charge up to 4.00 V.
|
|
+ */
|
|
+static void lbc_fault_clamp(struct pm8916_lbc_charger *chg, const char *why)
|
|
+{
|
|
+ unsigned int old = 0xff, rb = 0xff;
|
|
+ int ret;
|
|
+
|
|
+ ret = regmap_read(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_VDD_MAX, &old);
|
|
+ ret = ret ?: regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_VDD_MAX, 0x00);
|
|
+ ret = ret ?: regmap_read(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_VDD_MAX, &rb);
|
|
+ dev_crit(chg->dev, "FAULT safe clamp to 4.00 V: cause %s, vbat %d uV, VDD_MAX old 0x%02x -> readback 0x%02x (ret %d)\n",
|
|
+ why, chg->vbat_uv, old, rb, ret);
|
|
+}
|
|
+
|
|
+static bool lbc_enter_fault(struct pm8916_lbc_charger *chg, int reason, const char *why)
|
|
+{
|
|
+ chg->fault_reason = reason;
|
|
+ lbc_fault_clamp(chg, why);
|
|
+ lbc_supv_log(chg, LBC_ST_FAULT, why);
|
|
+ return true;
|
|
+}
|
|
+
|
|
static bool lbc_check_fault(struct pm8916_lbc_charger *chg, unsigned int failed)
|
|
{
|
|
- if (failed & PM8916_LBC_CHGR_CHG_FAILED_BIT) {
|
|
- chg->fault_reason = LBC_FAULT_TIMER;
|
|
- lbc_supv_log(chg, LBC_ST_FAULT, "CHG_FAILED (safety timer)");
|
|
- return true;
|
|
- }
|
|
- if (chg->vbat_uv > PM8916_LBC_SUPV_OVP_UV) {
|
|
- chg->fault_reason = LBC_FAULT_OVP;
|
|
- lbc_supv_log(chg, LBC_ST_FAULT, "vbat > 4.25 V");
|
|
- return true;
|
|
- }
|
|
+ if (failed & PM8916_LBC_CHGR_CHG_FAILED_BIT)
|
|
+ return lbc_enter_fault(chg, LBC_FAULT_TIMER, "CHG_FAILED (safety timer)");
|
|
+ if (chg->vbat_uv > PM8916_LBC_SUPV_OVP_UV)
|
|
+ return lbc_enter_fault(chg, LBC_FAULT_OVP, "vbat > 4.25 V");
|
|
return false;
|
|
}
|
|
|