google_cpm: check condition to disable DC
DC charging is re-enabled for the session when vbatt drops under
vbatt_high and on disconnect.
Bug: 192496480
Signed-off-by: AleX Pelosi <[email protected]>
Change-Id: I5981a4ab999a65d8c7efed6cc767e6fa0bc23017
diff --git a/google_cpm.c b/google_cpm.c
index 472ecdf..6aea215 100644
--- a/google_cpm.c
+++ b/google_cpm.c
@@ -44,6 +44,7 @@
/* Non DC Charger is the default */
#define GCPM_DEFAULT_CHARGER 0
/* TODO: handle capabilities based on index number */
+#define GCPM_INDEX_DC_DISABLE -1
#define GCPM_INDEX_DC_ENABLE 1
#define GCPM_MAX_CHARGERS 4
@@ -526,14 +527,13 @@
}
/*
- * Select the DC charger using the thermal policy. DC charging is enabled
- * when demand is over dc_limit (default 0) and vbatt > vbatt_min (default
- * 3.6V or device tree). DC is stopped when vbatt is over vbatt_max (4.4V,
- * or DT) and not started when vbatt is over vbatt_high (default 200mV under
- * vbatt_max or DT). DC charging is not stopped after start unless vbatt
- * falls under vbatt_low.
+ * Select the DC charger using the thermal policy.
+ * DC charging is enabled when demand is over dc_limit (default 0) and
+ * vbatt > vbatt_min (default or device tree). DC is not disabled when
+ * vbatt is over vbat low.
+ * DC is stopped when vbatt is over vbatt_max (default or DT) and not started
+ * when vbatt is over vbatt_high (some default 200mV under vbatt_max).
* NOTE: program target before enabling chaging.
- * call holding mutex_lock(&gcpm->chg_psy_lock);
*/
enum gcpm_dc_ctl_t {
GCPM_DC_CTL_DEFAULT = 0,
@@ -547,8 +547,6 @@
{
struct power_supply *chg_psy;
bool use_dc_limits = gcpm->pps_index == PPS_INDEX_WLC;
- const int vbatt_min = gcpm->dc_limit_vbatt_min;
- const int vbatt_max = gcpm->dc_limit_vbatt_max;
int batt_demand, index = GCPM_DEFAULT_CHARGER;
int cc_min = gcpm->dc_limit_cc_min;
int cc_max = gcpm->cc_max;
@@ -597,7 +595,7 @@
cc_max = gcpm->dc_fcc_limit;
}
- /* keep on default charger until we have valid charging parameters */
+ /* keeps on default charger until we have valid charging parameters */
if (cc_max <= 0 || gcpm->fv_uv <= 0)
return GCPM_DEFAULT_CHARGER;
@@ -622,11 +620,17 @@
/* TODO: add debounce on demand */
- /* could select different modes here depending on capabilities */
+ /*
+ * min and max are hard limits, low and high are debounce.
+ * low < MIN < high < MAX
+ * TODO: factor to a separate function, pass vbatt in
+ * NOTE: check the current charger, should check battery?
+ */
chg_psy = gcpm_chg_get_default(gcpm);
- if (chg_psy && (vbatt_max || vbatt_min)) {
+ if (chg_psy) {
+ const int vbatt_min = gcpm->dc_limit_vbatt_min;
+ const int vbatt_max = gcpm->dc_limit_vbatt_max;
const int vbatt_high = gcpm->dc_limit_vbatt_high;
- const int vbatt_low = gcpm->dc_limit_vbatt_low;
/* NOTE: check the current charger, should check battery? */
vbatt = GPSY_GET_PROP(chg_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW);
@@ -635,24 +639,43 @@
return gcpm->dc_index;
}
- if (vbatt_low && vbatt < vbatt_low)
- return -EAGAIN;
+ /*
+ * re-enable DC_ICL if it was disabled by taper control.
+ * TODO: Move to gcpm_chg_select_work() next to the taper
+ * control logic.
+ * NOTE: the check in gcpm_chg_dc_check_source() prevents this
+ * from retrying to enable DC while on NON PPS adapters.
+ */
+ if (vbatt < vbatt_high && gcpm->dc_state == DC_DISABLED)
+ gcpm->dc_state = DC_IDLE;
- /* Hard limits */
- if (vbatt_min && vbatt < vbatt_min)
- index = gcpm->dc_index == GCPM_DEFAULT_CHARGER ?
- -EAGAIN : gcpm->dc_index; /* debounce? */
- else if (vbatt_max && vbatt > vbatt_max)
- index = GCPM_DEFAULT_CHARGER; /* disable */
- else if (vbatt_high && vbatt > vbatt_high)
- index = gcpm->dc_index; /* debounce */
- else if (vbatt_min && vbatt < vbatt_min)
- index = GCPM_DEFAULT_CHARGER;
+ /*
+ * Need to keep checking when vbatt is under low to make sure
+ * that DC starts at min. No keeps the current
+ */
+ if (vbatt_max || vbatt_min) {
+ const int vbatt_low = gcpm->dc_limit_vbatt_low;
- /* demand decides DC unless under vmin */
- pr_debug("%s: index=%d->%d vbatt=%d: low=%d min=%d high=%d max=%d\n",
- __func__, gcpm->dc_index, index, vbatt, vbatt_low, vbatt_min,
- vbatt_high, vbatt_max);
+ /* -EAGAIN will check for it */
+ if (vbatt_low && vbatt < vbatt_low)
+ return gcpm->dc_index == GCPM_DEFAULT_CHARGER ?
+ -EAGAIN : gcpm->dc_index; /* debounce */
+
+ if (vbatt_min && vbatt < vbatt_min)
+ index = gcpm->dc_index == GCPM_DEFAULT_CHARGER ?
+ -EAGAIN : gcpm->dc_index; /* debounce? */
+ else if (vbatt_max && vbatt > vbatt_max)
+ index = GCPM_DEFAULT_CHARGER; /* disable */
+ else if (vbatt_high && vbatt > vbatt_high)
+ index = gcpm->dc_index; /* debounce */
+ else if (vbatt_min && vbatt < vbatt_min)
+ index = GCPM_DEFAULT_CHARGER;
+
+ /* demand decides DC unless under vmin */
+ pr_debug("%s: index=%d->%d vbatt=%d: low=%d min=%d high=%d max=%d\n",
+ __func__, gcpm->dc_index, index, vbatt, vbatt_low, vbatt_min,
+ vbatt_high, vbatt_max);
+ }
}
if (index >= gcpm->chg_psy_count) {
@@ -964,40 +987,44 @@
mutex_lock(&gcpm->chg_psy_lock);
+ pr_debug("%s: on=%d dc_state=%d dc_index=%d\n", __func__,
+ gcpm->dc_init_complete, gcpm->dc_state, gcpm->dc_index);
+
if (!gcpm->dc_init_complete) {
const int interval = 5; /* 5 seconds */
mod_delayed_work(system_wq, &gcpm->select_work,
msecs_to_jiffies(interval * 1000));
- mutex_unlock(&gcpm->chg_psy_lock);
- return;
+ goto unlock_done;
}
index = gcpm_chg_select(gcpm);
if (index < 0) {
const int interval = 5; /* 5 seconds */
- /* TODO: force to default after 3 faults? */
+ pr_debug("%s: index=%d dc_state=%d dc_index=%d\n",
+ __func__, index, gcpm->dc_state, gcpm->dc_index);
- pr_debug("CHG_CHK: reschedule in %d seconds\n", interval);
- mod_delayed_work(system_wq, &gcpm->select_work,
- msecs_to_jiffies(interval * 1000));
- mutex_unlock(&gcpm->chg_psy_lock);
- return;
+ /* -EAGAIN is used between low and min */
+ if (index == -EAGAIN)
+ mod_delayed_work(system_wq, &gcpm->select_work,
+ msecs_to_jiffies(interval * 1000));
+
+ goto unlock_done;
}
- /*
- * taper control while in dc_ena might knock down fv_uv by a little
- * and will reduce cc_max every gcpm->taper_step_interval by a fixed
- * amount seconds for gcpm->taper_step_count seconds.
- */
+ /* will not try to enable if the source cannot do PPS */
dc_ena = gcpm_chg_dc_check_source(gcpm, index);
if (dc_ena && gcpm->dc_fcc_hold) {
- pr_debug("%s: CPM_THERM_DC_FCC hold from limit\n",
- __func__);
+ pr_debug("%s: CPM_THERM_DC_FCC hold from limit\n", __func__);
dc_ena = false;
}
+ /*
+ * taper control reduces cc_max every gcpm->taper_step_interval seconds
+ * by a fixed amount for gcpm->taper_step_count seconds. fv_uv might
+ * also be lowered by a fixed amount.
+ */
if (dc_ena && gcpm->taper_step > 0) {
const int interval = msecs_to_jiffies(gcpm->taper_step_interval * 1000);
@@ -1007,12 +1034,18 @@
gcpm->taper_step -= 1;
}
- pr_debug("CHG_CHK: taper_step=%d done=%d\n", gcpm->taper_step, dc_done);
+ pr_debug("%s: taper_step=%d done=%d\n", __func__,
+ gcpm->taper_step, dc_done);
} else if (gcpm->taper_step != 0) {
gcpm_taper_ctl(gcpm, 0);
+
+ /*
+ * TODO: move the reset of DC state to DC_ENABLE when vbatt
+ * fall under vbatt_high here.
+ */
}
- pr_debug("CHG_CHK: DC dc_ena=%d dc_state=%d dc_index=%d->%d\n",
+ pr_debug("%s: DC dc_ena=%d dc_state=%d dc_index=%d->%d\n", __func__,
dc_ena, gcpm->dc_state, gcpm->dc_index, index);
/*
@@ -1026,13 +1059,17 @@
pr_info("CHG_CHK: dc_ena=%d dc_done=%d stop PPS_Work for dc_index=%d\n",
dc_ena, dc_done, gcpm->dc_index);
- /* dc_done prevents DC to restart for the session */
- gcpm->dc_index = dc_done ? -1 : GCPM_DEFAULT_CHARGER;
+ /*
+ * dc_done will prevent DC to restart until disconnect
+ * or voltage goes over _high.
+ */
+ gcpm->dc_index = dc_done ? GCPM_INDEX_DC_DISABLE :
+ GCPM_DEFAULT_CHARGER;
gcpm_taper_ctl(gcpm, 0);
schedule_pps_interval = 0;
}
} else if (gcpm->dc_state == DC_DISABLED) {
- pr_debug("CHG_CHK: PPS_Work disabled for the session\n");
+ pr_debug("%s: PPS_Work disabled for the session\n", __func__);
} else if (gcpm->dc_state == DC_IDLE) {
pr_info("CHG_CHK: start PPS_Work for dc_index=%d\n", index);
@@ -1049,12 +1086,14 @@
}
if (schedule_pps_interval >= 0) {
- pr_debug("CHG_CHK: DC schedule pps_work in %ds\n",
+ pr_debug("%s: DC schedule pps_work in %ds\n", __func__,
schedule_pps_interval / 1000);
+
mod_delayed_work(system_wq, &gcpm->pps_work,
msecs_to_jiffies(schedule_pps_interval));
}
+unlock_done:
mutex_unlock(&gcpm->chg_psy_lock);
}
@@ -1214,17 +1253,23 @@
struct pd_pps_data *pps_data;
int ret, pps_ui = -ENODEV;
+ pr_debug("%s: ok=%d dc_index=%d dc_state=%d\n", __func__,
+ gcpm->resume_complete && gcpm->init_complete,
+ gcpm->dc_index, gcpm->dc_state);
+
/* spurious during init */
mutex_lock(&gcpm->chg_psy_lock);
if (!gcpm->resume_complete || !gcpm->init_complete) {
- mutex_unlock(&gcpm->chg_psy_lock);
- return;
+ /* TODO: should probably reschedule */
+ goto pps_dc_done;
}
/* disconnect, gcpm_chg_check() and most errors reset ->dc_index */
if (gcpm->dc_index <= 0) {
const int active_index = gcpm->chg_psy_active; /* will change */
+ const bool dc_disable = gcpm->dc_index == GCPM_INDEX_DC_DISABLE;
+ /* will leave gcpm->dc_state in DC_DISABLED */
ret = gcpm_pps_wlc_dc_restart_default(gcpm);
if (ret < 0) {
pr_warn("PPS_Work: retry restart elap=%lld dc_state=%d %d->%d (%d)\n",
@@ -1236,7 +1281,7 @@
}
/* Re-enable DC if just switching to the default charger */
- if (gcpm->dc_index == GCPM_DEFAULT_CHARGER)
+ if (!dc_disable)
gcpm->dc_state = DC_IDLE;
logbuffer_prlog(gcpm, LOGLEVEL_INFO,
@@ -1419,11 +1464,11 @@
pps_dc_reschedule:
if (pps_ui <= 0) {
- pr_debug("PPS_Work: pps_ui=%d dc_state=%d",
- pps_ui, gcpm->dc_state);
+ pr_debug("PPS_Work: pps_ui=%d dc_index=%d dc_state=%d",
+ pps_ui, gcpm->dc_index, gcpm->dc_state);
} else {
- pr_debug("PPS_Work: reschedule in %d dc_state=%d (%d:%d)",
- pps_ui, gcpm->dc_state, gcpm->out_uv, gcpm->out_ua);
+ pr_debug("PPS_Work: reschedule in %d dc_index=%d dc_state=%d (%d:%d)",
+ pps_ui, gcpm->dc_index, gcpm->dc_state, gcpm->out_uv, gcpm->out_ua);
schedule_delayed_work(&gcpm->pps_work, msecs_to_jiffies(pps_ui));
}
@@ -1515,7 +1560,7 @@
/* google_charger send this on disconnect and input_suspend. */
pr_info("%s: ChargeDisable value=%d dc_index=%d dc_state=%d\n",
__func__, pval->intval, gcpm->dc_index, gcpm->dc_state);
- ta_check = true;
+
if (pval->intval) {
/*
* more or less the same as gcpm_pps_wlc_dc_work() when
@@ -1524,8 +1569,9 @@
* TODO: factor the code with gcpm_pps_wlc_dc_work().
*/
- /* No op if the current source is not DC, ->dc_state
- * will be DC_DISABLED if this actually disabled.
+ /*
+ * No op if the current source is not DC, ->dc_state
+ * will be DC_DISABLED if this was actually disabled.
*/
ret = gcpm_dc_stop(gcpm, gcpm->chg_psy_active);
if (ret == -EAGAIN) {
@@ -1538,7 +1584,7 @@
pr_debug("%s: fail 2 offline pps, dc_state=%d (%d)\n",
__func__, gcpm->dc_state, ret);
- /* disable DC, and clear taper */
+ /* reset to the default charger, and clear taper */
gcpm->dc_index = GCPM_DEFAULT_CHARGER;
gcpm_taper_ctl(gcpm, 0);
@@ -1551,19 +1597,38 @@
pr_err("%s: cannot start default (%d)\n",
__func__, ret);
+ pr_info("%s: ChargeDisable value=%d dc_index=%d dc_state=%d\n",
+ __func__, pval->intval, gcpm->dc_index, gcpm->dc_state);
+
/*
- * route = true so active will get the property. No
- * need to re-check the TA selection on disable.
+ * route = true so active will get the property.
+ * No need to re-check the TA selection on disable.
*/
ta_check = false;
} else if (gcpm->dc_state <= DC_IDLE) {
+ /*
+ * ->dc_state will be DC_DISABLED if DC was disabled
+ * via GBMS_PROP_CHARGE_DISABLE(1) of from other
+ * conditions such as taper control.
+ */
+ if (gcpm->dc_state == DC_DISABLED)
+ gcpm->dc_state = DC_IDLE;
+
+ pr_info("%s: ChargeDisable value=%d dc_index=%d dc_state=%d\n",
+ __func__, pval->intval, gcpm->dc_index, gcpm->dc_state);
+
gcpm_pps_online(gcpm);
+ ta_check = true;
}
break;
case POWER_SUPPLY_PROP_ONLINE:
+ pr_info("%s: ONLINE value=%d dc_index=%d dc_state=%d\n",
+ __func__, pval->intval, gcpm->dc_index,
+ gcpm->dc_state);
ta_check = true;
break;
+
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
psp = POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX;
/* compat, fall through */