power: qpnp-fg-gen3: prepare for QNOVO TTF

Micro resolution and 64-bit division is unnecessary; use milli
resolution instead. Measuring the IBATT and VBATT periodically during
sleep is necessary for accuracy. Don't clear the IBATT and VBATT buffers
on suspend to account for the higher charge current during suspend.
Prime the IBATT and VBATT buffers with 10 samples to get a more accurate
first estimate. Introduce a ttf mode to separate the differences in the
QNOVO version of TTF.

Change-Id: Ibc591dd5d38d4bbb712d8906755040d59181f008
Signed-off-by: Nicholas Troast <ntroast@codeaurora.org>
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index af15467..b6774e5 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -1173,6 +1173,42 @@
 	return true;
 }
 
+static bool usb_psy_initialized(struct fg_chip *chip)
+{
+	if (chip->usb_psy)
+		return true;
+
+	chip->usb_psy = power_supply_get_by_name("usb");
+	if (!chip->usb_psy)
+		return false;
+
+	return true;
+}
+
+static bool pc_port_psy_initialized(struct fg_chip *chip)
+{
+	if (chip->pc_port_psy)
+		return true;
+
+	chip->pc_port_psy = power_supply_get_by_name("pc_port");
+	if (!chip->pc_port_psy)
+		return false;
+
+	return true;
+}
+
+static bool dc_psy_initialized(struct fg_chip *chip)
+{
+	if (chip->dc_psy)
+		return true;
+
+	chip->dc_psy = power_supply_get_by_name("dc");
+	if (!chip->dc_psy)
+		return false;
+
+	return true;
+}
+
 static bool is_parallel_charger_available(struct fg_chip *chip)
 {
 	if (!chip->parallel_psy)
@@ -2133,19 +2169,65 @@
 	return 0;
 }
 
-static void fg_batt_avg_update(struct fg_chip *chip)
+static void fg_ttf_update(struct fg_chip *chip)
 {
-	if (chip->charge_status == chip->prev_charge_status)
+	int rc;
+	int delay_ms;
+	union power_supply_propval prop = {0, };
+	int online = 0;
+
+	if (usb_psy_initialized(chip)) {
+		rc = power_supply_get_property(chip->usb_psy,
+			POWER_SUPPLY_PROP_ONLINE, &prop);
+		if (rc < 0) {
+			pr_err("Couldn't read usb ONLINE prop rc=%d\n", rc);
+			return;
+		}
+
+		online = online || prop.intval;
+	}
+
+	if (pc_port_psy_initialized(chip)) {
+		rc = power_supply_get_property(chip->pc_port_psy,
+			POWER_SUPPLY_PROP_ONLINE, &prop);
+		if (rc < 0) {
+			pr_err("Couldn't read pc_port ONLINE prop rc=%d\n", rc);
+			return;
+		}
+
+		online = online || prop.intval;
+	}
+
+	if (dc_psy_initialized(chip)) {
+		rc = power_supply_get_property(chip->dc_psy,
+			POWER_SUPPLY_PROP_ONLINE, &prop);
+		if (rc < 0) {
+			pr_err("Couldn't read dc ONLINE prop rc=%d\n", rc);
+			return;
+		}
+
+		online = online || prop.intval;
+	}
+
+
+	if (chip->online_status == online)
 		return;
 
-	cancel_delayed_work_sync(&chip->batt_avg_work);
-	fg_circ_buf_clr(&chip->ibatt_circ_buf);
-	fg_circ_buf_clr(&chip->vbatt_circ_buf);
+	chip->online_status = online;
+	if (online)
+		/* wait 35 seconds for the input to settle */
+		delay_ms = 35000;
+	else
+		/* wait 5 seconds for current to settle during discharge */
+		delay_ms = 5000;
 
-	if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING ||
-			chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING)
-		schedule_delayed_work(&chip->batt_avg_work,
-							msecs_to_jiffies(2000));
+	vote(chip->awake_votable, TTF_PRIMING, true, 0);
+	cancel_delayed_work_sync(&chip->ttf_work);
+	mutex_lock(&chip->ttf.lock);
+	fg_circ_buf_clr(&chip->ttf.ibatt);
+	fg_circ_buf_clr(&chip->ttf.vbatt);
+	mutex_unlock(&chip->ttf.lock);
+	schedule_delayed_work(&chip->ttf_work, msecs_to_jiffies(delay_ms));
 }
 
 static void status_change_work(struct work_struct *work)
@@ -2223,7 +2305,7 @@
 				rc);
 	}
 
-	fg_batt_avg_update(chip);
+	fg_ttf_update(chip);
 
 out:
 	fg_dbg(chip, FG_POWER_SUPPLY, "charge_status:%d charge_type:%d charge_done:%d\n",
@@ -2733,45 +2815,16 @@
 
 module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644);
 
-#define BATT_AVG_POLL_PERIOD_MS	10000
-static void batt_avg_work(struct work_struct *work)
-{
-	struct fg_chip *chip = container_of(work, struct fg_chip,
-					    batt_avg_work.work);
-	int rc, ibatt_now, vbatt_now;
-
-	mutex_lock(&chip->batt_avg_lock);
-	rc = fg_get_battery_current(chip, &ibatt_now);
-	if (rc < 0) {
-		pr_err("failed to get battery current, rc=%d\n", rc);
-		goto reschedule;
-	}
-
-	rc = fg_get_battery_voltage(chip, &vbatt_now);
-	if (rc < 0) {
-		pr_err("failed to get battery voltage, rc=%d\n", rc);
-		goto reschedule;
-	}
-
-	fg_circ_buf_add(&chip->ibatt_circ_buf, ibatt_now);
-	fg_circ_buf_add(&chip->vbatt_circ_buf, vbatt_now);
-
-reschedule:
-	mutex_unlock(&chip->batt_avg_lock);
-	schedule_delayed_work(&chip->batt_avg_work,
-			      msecs_to_jiffies(BATT_AVG_POLL_PERIOD_MS));
-}
-
 #define HOURS_TO_SECONDS	3600
 #define OCV_SLOPE_UV		10869
 #define MILLI_UNIT		1000
 #define MICRO_UNIT		1000000
-static int fg_get_time_to_full(struct fg_chip *chip, int *val)
+#define NANO_UNIT		1000000000
+static int fg_get_time_to_full_locked(struct fg_chip *chip, int *val)
 {
-	int rc, ibatt_avg, vbatt_avg, rbatt, msoc, ocv_cc2cv, full_soc,
-		act_cap_uah;
-	s32 i_cc2cv, soc_cc2cv, ln_val, centi_tau_scale;
-	s64 t_predicted_cc = 0, t_predicted_cv = 0;
+	int rc, ibatt_avg, vbatt_avg, rbatt, msoc, full_soc, act_cap_mah,
+		i_cc2cv = 0, soc_cc2cv, tau, divisor, iterm,
+		t_predicted_cv, t_predicted = 0;
 
 	if (chip->bp.float_volt_uv <= 0) {
 		pr_err("battery profile is not loaded\n");
@@ -2790,48 +2843,39 @@
 	}
 	fg_dbg(chip, FG_TTF, "msoc=%d\n", msoc);
 
+	/* the battery is considered full if the SOC is 100% */
 	if (msoc >= 100) {
 		*val = 0;
 		return 0;
 	}
 
-	mutex_lock(&chip->batt_avg_lock);
-	rc = fg_circ_buf_avg(&chip->ibatt_circ_buf, &ibatt_avg);
-	if (rc < 0) {
-		/* try to get instantaneous current */
-		rc = fg_get_battery_current(chip, &ibatt_avg);
-		if (rc < 0) {
-			mutex_unlock(&chip->batt_avg_lock);
-			pr_err("failed to get battery current, rc=%d\n", rc);
-			return rc;
-		}
+	/* at least 10 samples are required to produce a stable IBATT */
+	if (chip->ttf.ibatt.size < 10) {
+		*val = -1;
+		return 0;
 	}
 
-	rc = fg_circ_buf_avg(&chip->vbatt_circ_buf, &vbatt_avg);
+	rc = fg_circ_buf_median(&chip->ttf.ibatt, &ibatt_avg);
 	if (rc < 0) {
-		/* try to get instantaneous voltage */
-		rc = fg_get_battery_voltage(chip, &vbatt_avg);
-		if (rc < 0) {
-			mutex_unlock(&chip->batt_avg_lock);
-			pr_err("failed to get battery voltage, rc=%d\n", rc);
-			return rc;
-		}
+		pr_err("failed to get IBATT AVG rc=%d\n", rc);
+		return rc;
 	}
 
-	mutex_unlock(&chip->batt_avg_lock);
-	fg_dbg(chip, FG_TTF, "vbatt_avg=%d\n", vbatt_avg);
+	rc = fg_circ_buf_median(&chip->ttf.vbatt, &vbatt_avg);
+	if (rc < 0) {
+		pr_err("failed to get VBATT AVG rc=%d\n", rc);
+		return rc;
+	}
 
-	/* clamp ibatt_avg to -150mA */
-	if (ibatt_avg > -150000)
-		ibatt_avg = -150000;
+	ibatt_avg = -ibatt_avg / MILLI_UNIT;
+	vbatt_avg /= MILLI_UNIT;
+
+	/* clamp ibatt_avg to iterm */
+	if (ibatt_avg < abs(chip->dt.sys_term_curr_ma))
+		ibatt_avg = abs(chip->dt.sys_term_curr_ma);
+
 	fg_dbg(chip, FG_TTF, "ibatt_avg=%d\n", ibatt_avg);
-
-	/* reverse polarity to be consistent with unsigned current settings */
-	ibatt_avg = abs(ibatt_avg);
-
-	/* estimated battery current at the CC to CV transition */
-	i_cc2cv = div_s64((s64)ibatt_avg * vbatt_avg, chip->bp.float_volt_uv);
-	fg_dbg(chip, FG_TTF, "i_cc2cv=%d\n", i_cc2cv);
+	fg_dbg(chip, FG_TTF, "vbatt_avg=%d\n", vbatt_avg);
 
 	rc = fg_get_battery_resistance(chip, &rbatt);
 	if (rc < 0) {
@@ -2839,19 +2883,14 @@
 		return rc;
 	}
 
-	/* clamp rbatt to 50mOhms */
-	if (rbatt < 50000)
-		rbatt = 50000;
-
+	rbatt /= MILLI_UNIT;
 	fg_dbg(chip, FG_TTF, "rbatt=%d\n", rbatt);
 
-	rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_uah);
+	rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
 	if (rc < 0) {
 		pr_err("failed to get ACT_BATT_CAP rc=%d\n", rc);
 		return rc;
 	}
-	act_cap_uah *= MILLI_UNIT;
-	fg_dbg(chip, FG_TTF, "actual_capacity_uah=%d\n", act_cap_uah);
 
 	rc = fg_get_sram_prop(chip, FG_SRAM_FULL_SOC, &full_soc);
 	if (rc < 0) {
@@ -2860,69 +2899,97 @@
 	}
 	full_soc = DIV_ROUND_CLOSEST(((u16)full_soc >> 8) * FULL_CAPACITY,
 								FULL_SOC_RAW);
-	fg_dbg(chip, FG_TTF, "full_soc=%d\n", full_soc);
+	act_cap_mah = full_soc * act_cap_mah / 100;
+	fg_dbg(chip, FG_TTF, "act_cap_mah=%d\n", act_cap_mah);
+
+	/* estimated battery current at the CC to CV transition */
+	switch (chip->ttf.mode) {
+	case TTF_MODE_NORMAL:
+		i_cc2cv = ibatt_avg * vbatt_avg /
+			max(MILLI_UNIT, chip->bp.float_volt_uv / MILLI_UNIT);
+		break;
+	default:
+		pr_err("TTF mode %d is not supported\n", chip->ttf.mode);
+		break;
+	}
+	fg_dbg(chip, FG_TTF, "i_cc2cv=%d\n", i_cc2cv);
 
 	/* if we are already in CV state then we can skip estimating CC */
 	if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER)
-		goto skip_cc_estimate;
+		goto cv_estimate;
 
-	/* if the charger is current limited then use power approximation */
-	if (ibatt_avg > chip->bp.fastchg_curr_ma * MILLI_UNIT - 50000)
-		ocv_cc2cv = div_s64((s64)rbatt * ibatt_avg, MICRO_UNIT);
-	else
-		ocv_cc2cv = div_s64((s64)rbatt * i_cc2cv, MICRO_UNIT);
-	ocv_cc2cv = chip->bp.float_volt_uv - ocv_cc2cv;
-	fg_dbg(chip, FG_TTF, "ocv_cc2cv=%d\n", ocv_cc2cv);
-
-	soc_cc2cv = div_s64(chip->bp.float_volt_uv - ocv_cc2cv, OCV_SLOPE_UV);
 	/* estimated SOC at the CC to CV transition */
+	soc_cc2cv = DIV_ROUND_CLOSEST(rbatt * i_cc2cv, OCV_SLOPE_UV);
 	soc_cc2cv = 100 - soc_cc2cv;
 	fg_dbg(chip, FG_TTF, "soc_cc2cv=%d\n", soc_cc2cv);
 
-	/* the esimated SOC may be lower than the current SOC */
-	if (soc_cc2cv - msoc <= 0)
-		goto skip_cc_estimate;
+	switch (chip->ttf.mode) {
+	case TTF_MODE_NORMAL:
+		if (soc_cc2cv - msoc <= 0)
+			goto cv_estimate;
 
-	t_predicted_cc = div_s64((s64)full_soc * act_cap_uah, 100);
-	t_predicted_cc = div_s64(t_predicted_cc * (soc_cc2cv - msoc), 100);
-	t_predicted_cc *= HOURS_TO_SECONDS;
-	t_predicted_cc = div_s64(t_predicted_cc, (ibatt_avg + i_cc2cv) / 2);
+		divisor = max(100, (ibatt_avg + i_cc2cv) / 2 * 100);
+		t_predicted = div_s64((s64)act_cap_mah * (soc_cc2cv - msoc) *
+						HOURS_TO_SECONDS, divisor);
+		break;
+	default:
+		pr_err("TTF mode %d is not supported\n", chip->ttf.mode);
+		break;
+	}
 
-skip_cc_estimate:
-	fg_dbg(chip, FG_TTF, "t_predicted_cc=%lld\n", t_predicted_cc);
+cv_estimate:
+	fg_dbg(chip, FG_TTF, "t_predicted_cc=%d\n", t_predicted);
 
-	/* CV estimate starts here */
-	if (chip->charge_type >= POWER_SUPPLY_CHARGE_TYPE_TAPER)
-		ln_val = ibatt_avg / (abs(chip->dt.sys_term_curr_ma) + 200);
+	iterm = max(100, abs(chip->dt.sys_term_curr_ma) + 200);
+	fg_dbg(chip, FG_TTF, "iterm=%d\n", iterm);
+
+	if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER)
+		tau = max(MILLI_UNIT, ibatt_avg * MILLI_UNIT / iterm);
 	else
-		ln_val = i_cc2cv / (abs(chip->dt.sys_term_curr_ma) + 200);
+		tau = max(MILLI_UNIT, i_cc2cv * MILLI_UNIT / iterm);
 
-	if (msoc < 95)
-		centi_tau_scale = 100;
-	else
-		centi_tau_scale = 20 * (100 - msoc);
+	rc = fg_lerp(fg_ln_table, ARRAY_SIZE(fg_ln_table), tau, &tau);
+	if (rc < 0) {
+		pr_err("failed to interpolate tau rc=%d\n", rc);
+		return rc;
+	}
 
-	fg_dbg(chip, FG_TTF, "ln_in=%d\n", ln_val);
-	rc = fg_lerp(fg_ln_table, ARRAY_SIZE(fg_ln_table), ln_val, &ln_val);
-	fg_dbg(chip, FG_TTF, "ln_out=%d\n", ln_val);
-	t_predicted_cv = div_s64((s64)act_cap_uah * rbatt, MICRO_UNIT);
-	t_predicted_cv = div_s64(t_predicted_cv * centi_tau_scale, 100);
-	t_predicted_cv = div_s64(t_predicted_cv * ln_val, MILLI_UNIT);
-	t_predicted_cv = div_s64(t_predicted_cv * HOURS_TO_SECONDS, MICRO_UNIT);
-	fg_dbg(chip, FG_TTF, "t_predicted_cv=%lld\n", t_predicted_cv);
-	*val = t_predicted_cc + t_predicted_cv;
+	/* tau is scaled linearly from 95% to 100% SOC */
+	if (msoc >= 95)
+		tau = tau * 2 * (100 - msoc) / 10;
+
+	fg_dbg(chip, FG_TTF, "tau=%d\n", tau);
+	t_predicted_cv = div_s64((s64)act_cap_mah * rbatt * tau *
+						HOURS_TO_SECONDS, NANO_UNIT);
+	fg_dbg(chip, FG_TTF, "t_predicted_cv=%d\n", t_predicted_cv);
+	t_predicted += t_predicted_cv;
+
+	/* clamp the ttf to 0 */
+	if (t_predicted < 0)
+		t_predicted = 0;
+
+	fg_dbg(chip, FG_TTF, "t_predicted=%d\n", t_predicted);
+	*val = t_predicted;
 	return 0;
 }
 
+static int fg_get_time_to_full(struct fg_chip *chip, int *val)
+{
+	int rc;
+
+	mutex_lock(&chip->ttf.lock);
+	rc = fg_get_time_to_full_locked(chip, val);
+	mutex_unlock(&chip->ttf.lock);
+	return rc;
+}
+
 #define CENTI_ICORRECT_C0	105
 #define CENTI_ICORRECT_C1	20
 static int fg_get_time_to_empty(struct fg_chip *chip, int *val)
 {
-	int rc, ibatt_avg, msoc, act_cap_uah;
-	s32 divisor;
-	s64 t_predicted;
+	int rc, ibatt_avg, msoc, full_soc, act_cap_mah, divisor;
 
-	rc = fg_circ_buf_avg(&chip->ibatt_circ_buf, &ibatt_avg);
+	rc = fg_circ_buf_median(&chip->ttf.ibatt, &ibatt_avg);
 	if (rc < 0) {
 		/* try to get instantaneous current */
 		rc = fg_get_battery_current(chip, &ibatt_avg);
@@ -2932,16 +2999,10 @@
 		}
 	}
 
-	/* clamp ibatt_avg to 150mA */
-	if (ibatt_avg < 150000)
-		ibatt_avg = 150000;
-
-	rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_uah);
-	if (rc < 0) {
-		pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
-		return rc;
-	}
-	act_cap_uah *= MILLI_UNIT;
+	ibatt_avg /= MILLI_UNIT;
+	/* clamp ibatt_avg to 100mA */
+	if (ibatt_avg < 100)
+		ibatt_avg = 100;
 
 	rc = fg_get_prop_capacity(chip, &msoc);
 	if (rc < 0) {
@@ -2949,14 +3010,25 @@
 		return rc;
 	}
 
-	t_predicted = div_s64((s64)msoc * act_cap_uah, 100);
-	t_predicted *= HOURS_TO_SECONDS;
-	divisor = CENTI_ICORRECT_C0 * 100 + CENTI_ICORRECT_C1 * msoc;
-	divisor = div_s64((s64)divisor * ibatt_avg, 10000);
-	if (divisor > 0)
-		t_predicted = div_s64(t_predicted, divisor);
+	rc = fg_get_sram_prop(chip, FG_SRAM_ACT_BATT_CAP, &act_cap_mah);
+	if (rc < 0) {
+		pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
+		return rc;
+	}
 
-	*val = t_predicted;
+	rc = fg_get_sram_prop(chip, FG_SRAM_FULL_SOC, &full_soc);
+	if (rc < 0) {
+		pr_err("failed to get full soc rc=%d\n", rc);
+		return rc;
+	}
+	full_soc = DIV_ROUND_CLOSEST(((u16)full_soc >> 8) * FULL_CAPACITY,
+								FULL_SOC_RAW);
+	act_cap_mah = full_soc * act_cap_mah / 100;
+
+	divisor = CENTI_ICORRECT_C0 * 100 + CENTI_ICORRECT_C1 * msoc;
+	divisor = ibatt_avg * divisor / 100;
+	divisor = max(100, divisor);
+	*val = act_cap_mah * msoc * HOURS_TO_SECONDS / divisor;
 	return 0;
 }
 
@@ -3118,6 +3190,57 @@
 	fg_dbg(chip, FG_STATUS, "Prepared for Qnovo\n");
 	return 0;
 }
+
+static void ttf_work(struct work_struct *work)
+{
+	struct fg_chip *chip = container_of(work, struct fg_chip,
+					    ttf_work.work);
+	int rc, ibatt_now, vbatt_now, ttf;
+
+	mutex_lock(&chip->ttf.lock);
+	if (chip->charge_status != POWER_SUPPLY_STATUS_CHARGING &&
+			chip->charge_status != POWER_SUPPLY_STATUS_DISCHARGING)
+		goto end_work;
+
+	rc = fg_get_battery_current(chip, &ibatt_now);
+	if (rc < 0) {
+		pr_err("failed to get battery current, rc=%d\n", rc);
+		goto end_work;
+	}
+
+	rc = fg_get_battery_voltage(chip, &vbatt_now);
+	if (rc < 0) {
+		pr_err("failed to get battery voltage, rc=%d\n", rc);
+		goto end_work;
+	}
+
+	fg_circ_buf_add(&chip->ttf.ibatt, ibatt_now);
+	fg_circ_buf_add(&chip->ttf.vbatt, vbatt_now);
+
+	if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
+		rc = fg_get_time_to_full_locked(chip, &ttf);
+		if (rc < 0) {
+			pr_err("failed to get ttf, rc=%d\n", rc);
+			goto end_work;
+		}
+
+		/* keep the wake lock and prime the IBATT and VBATT buffers */
+		if (ttf < 0) {
+			/* delay for one FG cycle */
+			schedule_delayed_work(&chip->ttf_work,
+							msecs_to_jiffies(1500));
+			mutex_unlock(&chip->ttf.lock);
+			return;
+		}
+	}
+
+	/* recurse every 10 seconds */
+	schedule_delayed_work(&chip->ttf_work, msecs_to_jiffies(10000));
+end_work:
+	vote(chip->awake_votable, TTF_PRIMING, false, 0);
+	mutex_unlock(&chip->ttf.lock);
+}
+
 /* PSY CALLBACKS STAY HERE */
 
 static int fg_psy_get_property(struct power_supply *psy,
@@ -3195,17 +3318,18 @@
 		rc = fg_get_sram_prop(chip, FG_SRAM_VBATT_FULL, &pval->intval);
 		break;
 	case POWER_SUPPLY_PROP_CC_STEP:
-		if ((chip->cc_step.sel >= 0) &&
-					(chip->cc_step.sel < MAX_CC_STEPS)) {
-			pval->intval = chip->cc_step.arr[chip->cc_step.sel];
+		if ((chip->ttf.cc_step.sel >= 0) &&
+				(chip->ttf.cc_step.sel < MAX_CC_STEPS)) {
+			pval->intval =
+				chip->ttf.cc_step.arr[chip->ttf.cc_step.sel];
 		} else {
 			pr_err("cc_step_sel is out of bounds [0, %d]\n",
-				chip->cc_step.sel);
+				chip->ttf.cc_step.sel);
 			return -EINVAL;
 		}
 		break;
 	case POWER_SUPPLY_PROP_CC_STEP_SEL:
-		pval->intval = chip->cc_step.sel;
+		pval->intval = chip->ttf.cc_step.sel;
 		break;
 	default:
 		pr_err("unsupported property %d\n", psp);
@@ -3246,18 +3370,19 @@
 		rc = fg_prepare_for_qnovo(chip, pval->intval);
 		break;
 	case POWER_SUPPLY_PROP_CC_STEP:
-		if ((chip->cc_step.sel >= 0) &&
-					(chip->cc_step.sel < MAX_CC_STEPS)) {
-			chip->cc_step.arr[chip->cc_step.sel] = pval->intval;
+		if ((chip->ttf.cc_step.sel >= 0) &&
+				(chip->ttf.cc_step.sel < MAX_CC_STEPS)) {
+			chip->ttf.cc_step.arr[chip->ttf.cc_step.sel] =
+								pval->intval;
 		} else {
 			pr_err("cc_step_sel is out of bounds [0, %d]\n",
-				chip->cc_step.sel);
+				chip->ttf.cc_step.sel);
 			return -EINVAL;
 		}
 		break;
 	case POWER_SUPPLY_PROP_CC_STEP_SEL:
 		if ((pval->intval >= 0) && (pval->intval < MAX_CC_STEPS)) {
-			chip->cc_step.sel = pval->intval;
+			chip->ttf.cc_step.sel = pval->intval;
 		} else {
 			pr_err("cc_step_sel is out of bounds [0, %d]\n",
 				pval->intval);
@@ -4555,6 +4680,7 @@
 	chip->charge_status = -EINVAL;
 	chip->prev_charge_status = -EINVAL;
 	chip->ki_coeff_full_soc = -EINVAL;
+	chip->online_status = -EINVAL;
 	chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
 	if (!chip->regmap) {
 		dev_err(chip->dev, "Parent regmap is unavailable\n");
@@ -4623,7 +4749,7 @@
 	mutex_init(&chip->sram_rw_lock);
 	mutex_init(&chip->cyc_ctr.lock);
 	mutex_init(&chip->cl.lock);
-	mutex_init(&chip->batt_avg_lock);
+	mutex_init(&chip->ttf.lock);
 	mutex_init(&chip->charge_full_lock);
 	init_completion(&chip->soc_update);
 	init_completion(&chip->soc_ready);
@@ -4631,7 +4757,7 @@
 	INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work);
 	INIT_WORK(&chip->status_change_work, status_change_work);
 	INIT_WORK(&chip->cycle_count_work, cycle_count_work);
-	INIT_DELAYED_WORK(&chip->batt_avg_work, batt_avg_work);
+	INIT_DELAYED_WORK(&chip->ttf_work, ttf_work);
 	INIT_DELAYED_WORK(&chip->sram_dump_work, sram_dump_work);
 
 	rc = fg_memif_init(chip);
@@ -4728,7 +4854,7 @@
 	if (rc < 0)
 		pr_err("Error in configuring ESR timer, rc=%d\n", rc);
 
-	cancel_delayed_work_sync(&chip->batt_avg_work);
+	cancel_delayed_work_sync(&chip->ttf_work);
 	if (fg_sram_dump)
 		cancel_delayed_work_sync(&chip->sram_dump_work);
 	return 0;
@@ -4743,9 +4869,7 @@
 	if (rc < 0)
 		pr_err("Error in configuring ESR timer, rc=%d\n", rc);
 
-	fg_circ_buf_clr(&chip->ibatt_circ_buf);
-	fg_circ_buf_clr(&chip->vbatt_circ_buf);
-	schedule_delayed_work(&chip->batt_avg_work, 0);
+	schedule_delayed_work(&chip->ttf_work, 0);
 	if (fg_sram_dump)
 		schedule_delayed_work(&chip->sram_dump_work,
 				msecs_to_jiffies(fg_sram_dump_period_ms));