google_battery: Add voltage tier at 100p/fix AC deadline
This calculates time after full charge.
This also ensures that no algorithm disable can be set after
A/C has already been completed
Bug: 168980587
Bug: 161000427
Signed-off-by: Stephane Lee <[email protected]>
Change-Id: I2c126cb8419d92428d7fa8bad61fd5c14b766812
Signed-off-by: Ken Tsou <[email protected]>
(cherry picked from commit b6e2b16083675a57f5e0e69644a7462c3ce56119)
diff --git a/google_battery.c b/google_battery.c
index 27eef68..57fb89f 100644
--- a/google_battery.c
+++ b/google_battery.c
@@ -363,6 +363,7 @@
#define SSOC_SPOOF 95
#define SSOC_FULL 100
#define UICURVE_BUF_SZ (UICURVE_MAX * 15 + 1)
+#define SSOC_HIGH_SOC 90
enum ssoc_uic_type {
SSOC_UIC_TYPE_DSG = -1,
@@ -960,6 +961,14 @@
ce_data->health_stats.vtier_idx = GBMS_STATS_AC_TI_INVALID;
ce_data->health_stats.temp_idx = -1;
ce_data->health_stats.soc_in = -1;
+
+ ce_data->full_charge_stats.vtier_idx = GBMS_STATS_AC_TI_FULL_CHARGE;
+ ce_data->full_charge_stats.temp_idx = -1;
+ ce_data->full_charge_stats.soc_in = -1;
+
+ ce_data->high_soc_stats.vtier_idx = GBMS_STATS_AC_TI_HIGH_SOC;
+ ce_data->high_soc_stats.temp_idx = -1;
+ ce_data->high_soc_stats.soc_in = -1;
}
static void batt_chg_stats_start(struct batt_drv *batt_drv)
@@ -1043,45 +1052,13 @@
ce_data->last_soc = index;
}
-/* call holding stats_lock */
-static void batt_chg_stats_update(struct batt_drv *batt_drv,
- int temp_idx, int tier_idx,
- int ibatt_ma, int temp, ktime_t elap)
+static void batt_chg_stats_update_tier(const struct batt_drv *const batt_drv,
+ int temp_idx, int ibatt_ma, int temp,
+ ktime_t elap, int cc,
+ struct gbms_ce_tier_stats *tier)
{
- const uint16_t icl_settled = batt_drv->chg_state.f.icl;
const int msc_state = batt_drv->msc_state;
- struct gbms_ce_tier_stats *tier;
- int cc;
-
- if (elap == 0)
- return;
-
- /* TODO: read at start of tier and update cc_total of previous */
- cc = GPSY_GET_PROP(batt_drv->fg_psy, POWER_SUPPLY_PROP_CHARGE_COUNTER);
- if (cc < 0) {
- pr_debug("MSC_STAT cannot read cc=%d\n", cc);
- return;
- }
- cc = cc / 1000;
-
- /* works because msc_logic books the time BEFORE updating msc_state */
- if (msc_state == MSC_HEALTH) {
- tier = &batt_drv->ce_data.health_stats;
-
- /* tier used for TTF during HC, check msc_logic_health() */
- } else {
- const qnum_t soc = ssoc_get_capacity_raw(&batt_drv->ssoc_state);
-
- /* book to previous soc unless discharging */
- if (msc_state != MSC_DSG) {
-
- /* TODO: should I use ssoc instead? */
- batt_chg_stats_soc_update(&batt_drv->ce_data, soc, elap,
- tier_idx, cc);
- }
-
- tier = &batt_drv->ce_data.tier_stats[tier_idx];
- }
+ const uint16_t icl_settled = batt_drv->chg_state.f.icl;
/* book to previous state */
batt_chg_stats_tier(tier, msc_state, elap);
@@ -1156,6 +1133,63 @@
tier->sample_count += 1;
}
+/* call holding stats_lock */
+static void batt_chg_stats_update(struct batt_drv *batt_drv, int temp_idx,
+ int tier_idx, int ibatt_ma, int temp,
+ ktime_t elap)
+{
+ const int msc_state = batt_drv->msc_state;
+ struct gbms_ce_tier_stats *tier;
+ int cc;
+ int soc_real = ssoc_get_real(&batt_drv->ssoc_state);
+
+ if (elap == 0)
+ return;
+
+ /* TODO: read at start of tier and update cc_total of previous */
+ cc = GPSY_GET_PROP(batt_drv->fg_psy, POWER_SUPPLY_PROP_CHARGE_COUNTER);
+ if (cc < 0) {
+ pr_debug("MSC_STAT cannot read cc=%d\n", cc);
+ return;
+ }
+ cc = cc / 1000;
+
+ if (batt_drv->batt_full) {
+ /* Override regular charge tiers when fully charged */
+ tier = &batt_drv->ce_data.full_charge_stats;
+
+ } else if (msc_state == MSC_HEALTH) {
+ /*
+ * works because msc_logic books the time BEFORE updating
+ * msc_state
+ */
+
+ /* tier used for TTF during HC, check msc_logic_health() */
+ tier = &batt_drv->ce_data.health_stats;
+
+ } else {
+ const qnum_t soc = ssoc_get_capacity_raw(&batt_drv->ssoc_state);
+
+ /* book to previous soc unless discharging */
+ if (msc_state != MSC_DSG) {
+ /* TODO: should I use ssoc instead? */
+ batt_chg_stats_soc_update(&batt_drv->ce_data, soc, elap,
+ tier_idx, cc);
+ }
+
+ tier = &batt_drv->ce_data.tier_stats[tier_idx];
+ }
+
+ batt_chg_stats_update_tier(batt_drv, temp_idx, ibatt_ma, temp, elap, cc,
+ tier);
+
+ /* Update this charge tier in parallel */
+ if (soc_real >= SSOC_HIGH_SOC) {
+ batt_chg_stats_update_tier(batt_drv, temp_idx, ibatt_ma, temp,
+ elap, cc,
+ &batt_drv->ce_data.high_soc_stats);
+ }
+}
static int batt_chg_health_vti(const struct batt_chg_health *chg_health)
{
@@ -1368,9 +1402,8 @@
}
/* End of charging: close stats, qualify event publish data */
-static void batt_chg_stats_pub(struct batt_drv *batt_drv,
- char *reason,
- bool force)
+static void batt_chg_stats_pub(struct batt_drv *batt_drv, char *reason,
+ bool force, bool skip_uevent)
{
bool publish;
@@ -1380,7 +1413,8 @@
ttf_stats_update(&batt_drv->ttf_stats,
&batt_drv->ce_qual, false);
- kobject_uevent(&batt_drv->device->kobj, KOBJ_CHANGE);
+ if (skip_uevent == false)
+ kobject_uevent(&batt_drv->device->kobj, KOBJ_CHANGE);
}
bat_log_chg_stats(batt_drv->ttf_stats.ttf_log, &batt_drv->ce_data);
@@ -1532,12 +1566,25 @@
len += batt_chg_tier_stats_cstr(&buff[len], size - len,
&ce_data->tier_stats[i],
verbose);
+
if (soc_next)
len += ttf_soc_cstr(&buff[len], size - len,
&ce_data->soc_stats,
soc_in, soc_next);
}
+ if (ce_data->full_charge_stats.soc_in != -1) {
+ len += batt_chg_tier_stats_cstr(&buff[len], size - len,
+ &ce_data->full_charge_stats,
+ verbose);
+ }
+
+ if (ce_data->high_soc_stats.soc_in != -1) {
+ len += batt_chg_tier_stats_cstr(&buff[len], size - len,
+ &ce_data->high_soc_stats,
+ verbose);
+ }
+
return len;
}
@@ -1969,9 +2016,12 @@
} else if (deadline_s == 0) {
new_deadline = chg_health->rest_deadline != deadline_s;
/* ->rest_deadline will be reset to 0 on disconnect */
- chg_health->rest_state = CHG_HEALTH_USER_DISABLED;
- /* enabled from any previous state */
+ /* Don't disable A/C if already done */
+ if (chg_health->rest_state != CHG_HEALTH_DONE)
+ chg_health->rest_state = CHG_HEALTH_USER_DISABLED;
+
+ /* enabled from any previous state */
} else {
const ktime_t rest_deadline = get_boot_sec() + deadline_s;
@@ -2381,7 +2431,7 @@
goto msc_logic_exit;
/* here on: disconnect */
- batt_chg_stats_pub(batt_drv, "disconnect", false);
+ batt_chg_stats_pub(batt_drv, "disconnect", false, false);
batt_res_state_set(&batt_drv->res_state, false);
/* change curve before changing the state */
@@ -2441,8 +2491,10 @@
} else if (batt_drv->batt_full) {
changed = batt_rl_enter(&batt_drv->ssoc_state,
BATT_RL_STATUS_RECHARGE);
+
+ /* We can skip the uevent because we have volt tiers >= 100 */
if (changed)
- batt_chg_stats_pub(batt_drv, "100%", false);
+ batt_chg_stats_pub(batt_drv, "100%", false, true);
}
err = msc_logic(batt_drv);
@@ -3164,7 +3216,7 @@
switch (buf[0]) {
case 'p': /* publish data to qual */
case 'P': /* force publish data to qual */
- batt_chg_stats_pub(batt_drv, "debug cmd", buf[0] == 'P');
+ batt_chg_stats_pub(batt_drv, "debug cmd", buf[0] == 'P', false);
break;
default:
count = -EINVAL;