- 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
434 lines
16 KiB
Diff
434 lines
16 KiB
Diff
--- v2
|
|
+++ v3
|
|
@@ -61,9 +61,14 @@
|
|
|
|
/* Aurora B10B-3 recharge supervisor */
|
|
#define PM8916_LBC_SUPV_PERIOD_MS 30000
|
|
-#define PM8916_LBC_SUPV_DONE_POLLS 2
|
|
-#define PM8916_LBC_SUPV_LOW_POLLS 3
|
|
+#define PM8916_LBC_SUPV_LATCH_POLLS 2
|
|
+#define PM8916_LBC_SUPV_NOCV_POLLS 2
|
|
#define PM8916_LBC_SUPV_OVP_UV 4250000
|
|
+#define PM8916_LBC_CV_HOLD_DEFAULT_MIN 60
|
|
+#define PM8916_LBC_CHGR_CV_LOOP BIT(1)
|
|
+
|
|
+#define PM8916_LBC_MISC_BOOT_DONE 0x42
|
|
+#define PM8916_LBC_MISC_BOOT_DONE_BIT BIT(7)
|
|
#define PM8916_LBC_TIMEOUT_DEFAULT_MIN 512
|
|
#define PM8916_LBC_TIMEOUT_STEP_MIN 4
|
|
#define PM8916_LBC_TIMEOUT_MAX_MIN 512
|
|
@@ -92,19 +97,25 @@
|
|
unsigned int charge_current_max;
|
|
unsigned int charge_current_safe;
|
|
|
|
- /* recharge supervisor */
|
|
+ /* charger supervisor (Aurora B10B-3 v3) */
|
|
struct iio_channel *vbat_chan;
|
|
struct delayed_work supv_work;
|
|
struct mutex supv_lock;
|
|
int state;
|
|
int fault_reason;
|
|
- unsigned int recharge_uv; /* production threshold from monitored-battery */
|
|
+ unsigned int hold_uv; /* aurora,hold-voltage-microvolt, 0 = HOLD disabled */
|
|
+ unsigned int full_min_uv; /* aurora,full-min-voltage-microvolt */
|
|
+ unsigned int cv_hold_min; /* aurora,cv-hold-minutes */
|
|
+ unsigned int ibat_code; /* IBAT_MAX code programmed at probe */
|
|
unsigned int timeout_min;
|
|
int vbat_uv;
|
|
- int done_polls;
|
|
- int low_polls;
|
|
- unsigned int n_terminated;
|
|
- unsigned int n_recharge;
|
|
+ int latch_polls;
|
|
+ int nocv_polls;
|
|
+ time64_t cv_since; /* start of the current CV run, 0 = none */
|
|
+ bool supv_ready; /* set at the end of probe; IRQ kicks only after that */
|
|
+ unsigned int n_insert;
|
|
+ unsigned int n_hold;
|
|
+ unsigned int n_latch;
|
|
struct {
|
|
time64_t t;
|
|
int from, to, vbat;
|
|
@@ -118,7 +129,7 @@
|
|
LBC_ST_INIT = 0,
|
|
LBC_ST_NO_USB,
|
|
LBC_ST_CHARGING,
|
|
- LBC_ST_TERMINATED,
|
|
+ LBC_ST_HOLD,
|
|
LBC_ST_FAULT,
|
|
};
|
|
|
|
@@ -126,7 +137,7 @@
|
|
[LBC_ST_INIT] = "INIT",
|
|
[LBC_ST_NO_USB] = "NO_USB",
|
|
[LBC_ST_CHARGING] = "CHARGING",
|
|
- [LBC_ST_TERMINATED] = "TERMINATED",
|
|
+ [LBC_ST_HOLD] = "HOLD",
|
|
[LBC_ST_FAULT] = "FAULT",
|
|
};
|
|
|
|
@@ -154,7 +165,7 @@
|
|
LBC_MISC,
|
|
};
|
|
|
|
-static int pm8916_lbc_charger_configure(struct pm8916_lbc_charger *chg, bool set_ctrl)
|
|
+static int pm8916_lbc_charger_configure(struct pm8916_lbc_charger *chg, bool probe)
|
|
{
|
|
int ret = 0;
|
|
unsigned int tmp;
|
|
@@ -166,9 +177,12 @@
|
|
tmp /= PM8916_LBC_CHGR_VOLTAGE_STEP;
|
|
chg->charge_voltage_max = PM8916_LBC_CHGR_MIN_VOLTAGE + tmp * PM8916_LBC_CHGR_VOLTAGE_STEP;
|
|
|
|
- ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_VDD_MAX, tmp);
|
|
- if (ret)
|
|
- goto error;
|
|
+ /* after probe the supervisor owns VDD_MAX (charge level / hold level) */
|
|
+ if (probe) {
|
|
+ ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_VDD_MAX, tmp);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+ }
|
|
|
|
chg->charge_current_max = min(chg->charge_current_max, chg->charge_current_safe);
|
|
|
|
@@ -177,16 +191,17 @@
|
|
|
|
tmp = chg->charge_current_max / PM8916_LBC_CHGR_MIN_CURRENT - 1;
|
|
chg->charge_current_max = (tmp + 1) * PM8916_LBC_CHGR_MIN_CURRENT;
|
|
+ chg->ibat_code = tmp;
|
|
|
|
ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_IBAT_MAX, tmp);
|
|
if (ret)
|
|
goto error;
|
|
|
|
/*
|
|
- * CHG_CTRL is written only at probe. Afterwards the recharge supervisor owns CHG_EN, so a
|
|
- * constant_charge_current update must not re-enable charging in TERMINATED/FAULT.
|
|
+ * CHG_CTRL is written only at probe. Afterwards the supervisor owns CHG_EN, so a
|
|
+ * constant_charge_current update must not restart charging in HOLD/FAULT.
|
|
*/
|
|
- if (set_ctrl) {
|
|
+ if (probe) {
|
|
ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_CHG_CTRL,
|
|
PM8916_LBC_CHGR_CHG_EN | PM8916_LBC_CHGR_PSTG_EN);
|
|
if (ret)
|
|
@@ -212,7 +227,7 @@
|
|
case LBC_ST_CHARGING:
|
|
val->intval = POWER_SUPPLY_STATUS_CHARGING;
|
|
break;
|
|
- case LBC_ST_TERMINATED:
|
|
+ case LBC_ST_HOLD:
|
|
val->intval = POWER_SUPPLY_STATUS_FULL;
|
|
break;
|
|
case LBC_ST_NO_USB:
|
|
@@ -249,8 +264,15 @@
|
|
|
|
switch (prop) {
|
|
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
|
|
+ {
|
|
+ int ret;
|
|
+
|
|
+ mutex_lock(&chg->supv_lock);
|
|
chg->charge_current_max = val->intval;
|
|
- return pm8916_lbc_charger_configure(chg, false);
|
|
+ ret = pm8916_lbc_charger_configure(chg, false);
|
|
+ mutex_unlock(&chg->supv_lock);
|
|
+ return ret;
|
|
+ }
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
@@ -276,14 +298,15 @@
|
|
|
|
|
|
/*
|
|
- * Aurora B10B-3 recharge supervisor.
|
|
- * The LBC ends a charge cycle in hardware (end-of-charge latch: CHG_STATUS 00, USB path 01, USB input ~0) and then
|
|
- * stays off until software gives CHG_EN a 0 -> 1 edge (downstream qpnp-linear-charger did this from BMS SOC /
|
|
- * VBAT_DET IRQ). Verified on Aurora (B10B-3 ram1): CHG_CTRL 0x21 -> 0xa0 releases the latch.
|
|
- * Also verified: writing CHG_EN = 0 does NOT stop the charger (USB input stays ~0.36 A), so the supervisor never
|
|
- * uses CHG_CTRL to "turn charging off"; TERMINATED is only the hardware latch, observed after CHARGING.
|
|
- * The supervisor polls the VADC VBAT every 30 s and restarts charging when VBAT stays below the monitored-battery
|
|
- * re-charge-voltage-microvolt for 3 consecutive polls.
|
|
+ * Aurora B10B-3 v3 charger supervisor: CHARGE -> HOLD -> (battery) -> CHARGE.
|
|
+ * 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.
|
|
+ * NO_USB: nothing is written.
|
|
+ * 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.
|
|
*/
|
|
static void lbc_supv_log(struct pm8916_lbc_charger *chg, int to, const char *why)
|
|
{
|
|
@@ -294,14 +317,17 @@
|
|
chg->log[i].to = to;
|
|
chg->log[i].vbat = chg->vbat_uv;
|
|
chg->log[i].why = why;
|
|
- dev_info(chg->dev, "supervisor %s -> %s (%s), vbat %d uV\n", lbc_state_name[chg->state],
|
|
- lbc_state_name[to], why, chg->vbat_uv);
|
|
+ if (to == LBC_ST_FAULT)
|
|
+ dev_crit(chg->dev, "supervisor %s -> FAULT (%s), vbat %d uV: restarts blocked, NO software stop available\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],
|
|
+ lbc_state_name[to], why, chg->vbat_uv);
|
|
chg->state = to;
|
|
}
|
|
|
|
static int lbc_charge_enable(struct pm8916_lbc_charger *chg, bool en)
|
|
{
|
|
- /* stock-style: enabled = CHG_EN, disabled = FORCE_BATT_ON */
|
|
return regmap_update_bits(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_CHG_CTRL,
|
|
PM8916_LBC_CHGR_EN_MASK,
|
|
en ? PM8916_LBC_CHGR_CHG_EN : PM8916_LBC_CHGR_FORCE_BATT_ON);
|
|
@@ -325,10 +351,69 @@
|
|
return lbc_charge_enable(chg, true);
|
|
}
|
|
|
|
+static int lbc_set_vdd_max(struct pm8916_lbc_charger *chg, unsigned int uv)
|
|
+{
|
|
+ uv = clamp_t(u32, uv, PM8916_LBC_CHGR_MIN_VOLTAGE, chg->charge_voltage_safe);
|
|
+ return regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_VDD_MAX,
|
|
+ (uv - PM8916_LBC_CHGR_MIN_VOLTAGE) / PM8916_LBC_CHGR_VOLTAGE_STEP);
|
|
+}
|
|
+
|
|
+/* USB insert / probe with USB: start a full cycle at the charge level */
|
|
+static int lbc_enter_charging(struct pm8916_lbc_charger *chg)
|
|
+{
|
|
+ unsigned int v;
|
|
+ int ret;
|
|
+
|
|
+ ret = regmap_update_bits(chg->regmap, chg->reg[LBC_MISC] + PM8916_LBC_MISC_BOOT_DONE,
|
|
+ PM8916_LBC_MISC_BOOT_DONE_BIT, PM8916_LBC_MISC_BOOT_DONE_BIT);
|
|
+ ret = ret ?: lbc_set_vdd_max(chg, chg->charge_voltage_max);
|
|
+ ret = ret ?: regmap_read(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_IBAT_MAX, &v);
|
|
+ if (!ret && v != chg->ibat_code)
|
|
+ ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_IBAT_MAX, chg->ibat_code);
|
|
+ ret = ret ?: lbc_charge_restart(chg, true);
|
|
+ chg->latch_polls = 0;
|
|
+ chg->nocv_polls = 0;
|
|
+ chg->cv_since = 0;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/* 00/01 latch with USB valid: count polls; restart with the verified edge (VDD_MAX untouched) */
|
|
+static bool lbc_handle_latch(struct pm8916_lbc_charger *chg, unsigned int sts, unsigned int path)
|
|
+{
|
|
+ if (sts == 0 && !(path & PM8916_LBC_USB_PATH_ON))
|
|
+ chg->latch_polls++;
|
|
+ else
|
|
+ chg->latch_polls = 0;
|
|
+ if (chg->latch_polls < PM8916_LBC_SUPV_LATCH_POLLS)
|
|
+ return false;
|
|
+ chg->latch_polls = 0;
|
|
+ chg->n_latch++;
|
|
+ if (!lbc_charge_restart(chg, false))
|
|
+ dev_warn(chg->dev, "supervisor: 00/01 latch in %s (vbat %d uV) -> restart edge #%u\n",
|
|
+ lbc_state_name[chg->state], chg->vbat_uv, chg->n_latch);
|
|
+ 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;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
static void lbc_supv_work(struct work_struct *work)
|
|
{
|
|
struct pm8916_lbc_charger *chg = container_of(work, struct pm8916_lbc_charger, supv_work.work);
|
|
unsigned int usb_rt, sts, path, failed;
|
|
+ time64_t now = ktime_get_seconds();
|
|
int ret, uv;
|
|
|
|
mutex_lock(&chg->supv_lock);
|
|
@@ -347,7 +432,6 @@
|
|
chg->vbat_uv = -1;
|
|
|
|
if (!(usb_rt & PM8916_LBC_USB_USBIN_VALID)) {
|
|
- /* CHG_CTRL untouched; the next insert restarts with the verified edge */
|
|
if (chg->state != LBC_ST_NO_USB) {
|
|
chg->fault_reason = LBC_FAULT_NONE;
|
|
lbc_supv_log(chg, LBC_ST_NO_USB, "usb removed");
|
|
@@ -358,58 +442,50 @@
|
|
switch (chg->state) {
|
|
case LBC_ST_INIT:
|
|
case LBC_ST_NO_USB:
|
|
- /* probe or USB insert: always start a cycle, like stock's usbin path */
|
|
- chg->done_polls = 0;
|
|
- chg->low_polls = 0;
|
|
chg->fault_reason = LBC_FAULT_NONE;
|
|
- if (!lbc_charge_restart(chg, true))
|
|
+ chg->n_insert++;
|
|
+ if (!lbc_enter_charging(chg))
|
|
lbc_supv_log(chg, LBC_ST_CHARGING,
|
|
chg->state == LBC_ST_INIT ? "probe, usb present" : "usb inserted");
|
|
break;
|
|
|
|
case LBC_ST_CHARGING:
|
|
- /*
|
|
- * Safety timer expiry: the hardware stops and sets CHG_FAILED. Latch FAULT so the supervisor never
|
|
- * restarts; no register write (CHG_EN = 0 is not a verified way to stop the charger).
|
|
- */
|
|
- 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)");
|
|
+ if (lbc_check_fault(chg, failed))
|
|
+ break;
|
|
+ if (lbc_handle_latch(chg, sts, path)) {
|
|
+ chg->cv_since = 0;
|
|
+ chg->nocv_polls = 0;
|
|
break;
|
|
}
|
|
- if (chg->vbat_uv > PM8916_LBC_SUPV_OVP_UV) {
|
|
- /* defence only: VDD_MAX regulates in hardware; latch FAULT = no further restarts */
|
|
- chg->fault_reason = LBC_FAULT_OVP;
|
|
- lbc_supv_log(chg, LBC_ST_FAULT, "vbat > 4.25 V");
|
|
+ if (!chg->hold_uv || chg->vbat_uv < 0)
|
|
break;
|
|
+ /* CV run: CV loop bit with VBAT >= full-min; tolerate one poll without the bit (05/07 interleave) */
|
|
+ if ((unsigned int)chg->vbat_uv < chg->full_min_uv) {
|
|
+ chg->cv_since = 0;
|
|
+ chg->nocv_polls = 0;
|
|
+ break;
|
|
+ }
|
|
+ if (sts & PM8916_LBC_CHGR_CV_LOOP) {
|
|
+ chg->nocv_polls = 0;
|
|
+ if (!chg->cv_since)
|
|
+ chg->cv_since = now;
|
|
+ } else if (++chg->nocv_polls >= PM8916_LBC_SUPV_NOCV_POLLS) {
|
|
+ chg->cv_since = 0;
|
|
}
|
|
- /* TERMINATED = hardware end-of-charge latch only; CHG_CTRL is not changed */
|
|
- if (sts == 0 && !(path & PM8916_LBC_USB_PATH_ON))
|
|
- chg->done_polls++;
|
|
- else
|
|
- chg->done_polls = 0;
|
|
- if (chg->done_polls >= PM8916_LBC_SUPV_DONE_POLLS) {
|
|
- chg->n_terminated++;
|
|
- chg->low_polls = 0;
|
|
- lbc_supv_log(chg, LBC_ST_TERMINATED, "hardware end of charge");
|
|
+ if (chg->cv_since && now - chg->cv_since >= (time64_t)chg->cv_hold_min * 60) {
|
|
+ if (!lbc_set_vdd_max(chg, chg->hold_uv)) {
|
|
+ chg->n_hold++;
|
|
+ chg->latch_polls = 0;
|
|
+ lbc_supv_log(chg, LBC_ST_HOLD, "CV time reached, VDD_MAX -> hold level");
|
|
+ }
|
|
}
|
|
break;
|
|
|
|
- case LBC_ST_TERMINATED:
|
|
- if (!chg->recharge_uv || chg->vbat_uv < 0)
|
|
+ case LBC_ST_HOLD:
|
|
+ if (lbc_check_fault(chg, failed))
|
|
break;
|
|
- if ((unsigned int)chg->vbat_uv < chg->recharge_uv)
|
|
- chg->low_polls++;
|
|
- else
|
|
- chg->low_polls = 0;
|
|
- if (chg->low_polls >= PM8916_LBC_SUPV_LOW_POLLS) {
|
|
- chg->done_polls = 0;
|
|
- chg->low_polls = 0;
|
|
- if (!lbc_charge_restart(chg, false)) {
|
|
- chg->n_recharge++;
|
|
- lbc_supv_log(chg, LBC_ST_CHARGING, "recharge");
|
|
- }
|
|
- }
|
|
+ /* keep the board on USB: a 00/01 latch gets the restart edge, VDD_MAX stays at the hold level */
|
|
+ lbc_handle_latch(chg, sts, path);
|
|
break;
|
|
|
|
case LBC_ST_FAULT:
|
|
@@ -439,15 +515,18 @@
|
|
{ "USB_PATH", LBC_USB, PM8916_LBC_USB_PATH_STS },
|
|
{ "USB_RT", LBC_USB, PM8916_INT_RT_STS },
|
|
{ "BAT_RT", LBC_BAT_IF, PM8916_INT_RT_STS },
|
|
+ { "BOOT_DONE", LBC_MISC, PM8916_LBC_MISC_BOOT_DONE },
|
|
};
|
|
+ time64_t now = ktime_get_seconds();
|
|
unsigned int i, v;
|
|
|
|
mutex_lock(&chg->supv_lock);
|
|
seq_printf(s, "state %s fault %s vbat_uv %d\n", lbc_state_name[chg->state],
|
|
lbc_fault_name[chg->fault_reason], chg->vbat_uv);
|
|
- seq_printf(s, "recharge_uv %u done_polls %d low_polls %d timeout_min %u\n",
|
|
- chg->recharge_uv, chg->done_polls, chg->low_polls, chg->timeout_min);
|
|
- seq_printf(s, "n_terminated %u n_recharge %u\n", chg->n_terminated, chg->n_recharge);
|
|
+ seq_printf(s, "charge_uv %u hold_uv %u full_min_uv %u cv_hold_min %u cv_s %lld nocv %d timeout_min %u\n",
|
|
+ chg->charge_voltage_max, chg->hold_uv, chg->full_min_uv, chg->cv_hold_min,
|
|
+ chg->cv_since ? now - chg->cv_since : -1LL, chg->nocv_polls, chg->timeout_min);
|
|
+ seq_printf(s, "n_insert %u n_hold %u n_latch %u\n", chg->n_insert, chg->n_hold, chg->n_latch);
|
|
for (i = 0; i < ARRAY_SIZE(regs); i++) {
|
|
if (regmap_read(chg->regmap, chg->reg[regs[i].blk] + regs[i].off, &v))
|
|
v = 0xffff;
|
|
@@ -485,7 +564,7 @@
|
|
|
|
power_supply_changed(chg->charger);
|
|
|
|
- if (chg->vbat_chan)
|
|
+ if (READ_ONCE(chg->supv_ready))
|
|
mod_delayed_work(system_freezable_wq, &chg->supv_work, 0);
|
|
|
|
return IRQ_HANDLED;
|
|
@@ -584,6 +663,7 @@
|
|
return -ENOMEM;
|
|
|
|
chg->dev = dev;
|
|
+ mutex_init(&chg->supv_lock);
|
|
|
|
chg->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
|
if (!chg->regmap)
|
|
@@ -649,14 +729,13 @@
|
|
if (IS_ERR(chg->vbat_chan))
|
|
return dev_err_probe(dev, PTR_ERR(chg->vbat_chan), "no VADC vbat channel\n");
|
|
|
|
- {
|
|
- struct device_node *bat = of_parse_phandle(dev->of_node, "monitored-battery", 0);
|
|
-
|
|
- if (!bat || of_property_read_u32(bat, "re-charge-voltage-microvolt", &chg->recharge_uv))
|
|
- dev_warn(dev, "no re-charge-voltage-microvolt: automatic recharge disabled\n");
|
|
- of_node_put(bat);
|
|
+ chg->cv_hold_min = PM8916_LBC_CV_HOLD_DEFAULT_MIN;
|
|
+ device_property_read_u32(dev, "aurora,cv-hold-minutes", &chg->cv_hold_min);
|
|
+ if (device_property_read_u32(dev, "aurora,hold-voltage-microvolt", &chg->hold_uv) ||
|
|
+ device_property_read_u32(dev, "aurora,full-min-voltage-microvolt", &chg->full_min_uv)) {
|
|
+ chg->hold_uv = 0;
|
|
+ dev_warn(dev, "no aurora,hold-voltage/full-min-voltage: HOLD disabled\n");
|
|
}
|
|
- mutex_init(&chg->supv_lock);
|
|
ret = devm_delayed_work_autocancel(dev, &chg->supv_work, lbc_supv_work);
|
|
if (ret)
|
|
return ret;
|
|
@@ -696,9 +775,17 @@
|
|
if (ret)
|
|
return ret;
|
|
|
|
- dev_info(dev, "recharge supervisor: threshold %u uV, %d x %d ms below, ovp %d uV\n",
|
|
- chg->recharge_uv, PM8916_LBC_SUPV_LOW_POLLS, PM8916_LBC_SUPV_PERIOD_MS,
|
|
- PM8916_LBC_SUPV_OVP_UV);
|
|
+ if (chg->hold_uv && (chg->hold_uv < PM8916_LBC_CHGR_MIN_VOLTAGE ||
|
|
+ chg->hold_uv >= chg->charge_voltage_max ||
|
|
+ chg->full_min_uv > chg->charge_voltage_max)) {
|
|
+ dev_warn(dev, "invalid hold %u / full-min %u for charge level %u: HOLD disabled\n",
|
|
+ chg->hold_uv, chg->full_min_uv, chg->charge_voltage_max);
|
|
+ chg->hold_uv = 0;
|
|
+ }
|
|
+ dev_info(dev, "supervisor v3: charge %u uV, hold %u uV, full-min %u uV, cv %u min, IBAT_MAX code %u, ovp %d uV\n",
|
|
+ chg->charge_voltage_max, chg->hold_uv, chg->full_min_uv, chg->cv_hold_min,
|
|
+ chg->ibat_code, PM8916_LBC_SUPV_OVP_UV);
|
|
+ WRITE_ONCE(chg->supv_ready, true);
|
|
queue_delayed_work(system_freezable_wq, &chg->supv_work, 0);
|
|
|
|
return 0;
|