power: qpnp-fg-gen3: make TTF monotonic by limiting slope
Currently if there is a spike in system load or a thermal event which causes the battery current to change dramatically then the TTF can jump. While a battery is charging the TTF should be monotonically decreasing. Track the TTF starting with the first estimate and set hard bounds of -2 and -0.1 on the slope. The negative slope ensures the TTF is monotonically decreasing and the hard bounds on the slope smooth out significant changes in the TTF. Change-Id: I68a934599ff25bc5a9eb67b372b28a723532a540 Signed-off-by: Nicholas Troast <ntroast@codeaurora.org> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
This commit is contained in:
parent
811a8bd2ef
commit
96168e19d4
2 changed files with 41 additions and 2 deletions
|
@ -338,6 +338,8 @@ struct ttf {
|
||||||
struct fg_cc_step_data cc_step;
|
struct fg_cc_step_data cc_step;
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
int mode;
|
int mode;
|
||||||
|
int last_ttf;
|
||||||
|
s64 last_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct fg_pt fg_ln_table[] = {
|
static const struct fg_pt fg_ln_table[] = {
|
||||||
|
|
|
@ -2225,6 +2225,8 @@ static void fg_ttf_update(struct fg_chip *chip)
|
||||||
mutex_lock(&chip->ttf.lock);
|
mutex_lock(&chip->ttf.lock);
|
||||||
fg_circ_buf_clr(&chip->ttf.ibatt);
|
fg_circ_buf_clr(&chip->ttf.ibatt);
|
||||||
fg_circ_buf_clr(&chip->ttf.vbatt);
|
fg_circ_buf_clr(&chip->ttf.vbatt);
|
||||||
|
chip->ttf.last_ttf = 0;
|
||||||
|
chip->ttf.last_ms = 0;
|
||||||
mutex_unlock(&chip->ttf.lock);
|
mutex_unlock(&chip->ttf.lock);
|
||||||
schedule_delayed_work(&chip->ttf_work, msecs_to_jiffies(delay_ms));
|
schedule_delayed_work(&chip->ttf_work, msecs_to_jiffies(delay_ms));
|
||||||
}
|
}
|
||||||
|
@ -2824,8 +2826,9 @@ static int fg_get_time_to_full_locked(struct fg_chip *chip, int *val)
|
||||||
int rc, ibatt_avg, vbatt_avg, rbatt, msoc, full_soc, act_cap_mah,
|
int rc, ibatt_avg, vbatt_avg, rbatt, msoc, full_soc, act_cap_mah,
|
||||||
i_cc2cv, soc_cc2cv, tau, divisor, iterm, ttf_mode,
|
i_cc2cv, soc_cc2cv, tau, divisor, iterm, ttf_mode,
|
||||||
i, soc_per_step, msoc_this_step, msoc_next_step,
|
i, soc_per_step, msoc_this_step, msoc_next_step,
|
||||||
ibatt_this_step, t_predicted_this_step,
|
ibatt_this_step, t_predicted_this_step, ttf_slope,
|
||||||
t_predicted_cv, t_predicted = 0;
|
t_predicted_cv, t_predicted = 0;
|
||||||
|
s64 delta_ms;
|
||||||
|
|
||||||
if (chip->bp.float_volt_uv <= 0) {
|
if (chip->bp.float_volt_uv <= 0) {
|
||||||
pr_err("battery profile is not loaded\n");
|
pr_err("battery profile is not loaded\n");
|
||||||
|
@ -2859,6 +2862,8 @@ static int fg_get_time_to_full_locked(struct fg_chip *chip, int *val)
|
||||||
if (chip->ttf.mode != ttf_mode) {
|
if (chip->ttf.mode != ttf_mode) {
|
||||||
fg_circ_buf_clr(&chip->ttf.ibatt);
|
fg_circ_buf_clr(&chip->ttf.ibatt);
|
||||||
fg_circ_buf_clr(&chip->ttf.vbatt);
|
fg_circ_buf_clr(&chip->ttf.vbatt);
|
||||||
|
chip->ttf.last_ttf = 0;
|
||||||
|
chip->ttf.last_ms = 0;
|
||||||
chip->ttf.mode = ttf_mode;
|
chip->ttf.mode = ttf_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3006,11 +3011,33 @@ cv_estimate:
|
||||||
fg_dbg(chip, FG_TTF, "t_predicted_cv=%d\n", t_predicted_cv);
|
fg_dbg(chip, FG_TTF, "t_predicted_cv=%d\n", t_predicted_cv);
|
||||||
t_predicted += t_predicted_cv;
|
t_predicted += t_predicted_cv;
|
||||||
|
|
||||||
|
fg_dbg(chip, FG_TTF, "t_predicted_prefilter=%d\n", t_predicted);
|
||||||
|
if (chip->ttf.last_ms != 0) {
|
||||||
|
delta_ms = ktime_ms_delta(ktime_get_boottime(),
|
||||||
|
ms_to_ktime(chip->ttf.last_ms));
|
||||||
|
if (delta_ms > 10000) {
|
||||||
|
ttf_slope = div64_s64(
|
||||||
|
(s64)(t_predicted - chip->ttf.last_ttf) *
|
||||||
|
MICRO_UNIT, delta_ms);
|
||||||
|
if (ttf_slope > -100)
|
||||||
|
ttf_slope = -100;
|
||||||
|
else if (ttf_slope < -2000)
|
||||||
|
ttf_slope = -2000;
|
||||||
|
|
||||||
|
t_predicted = div_s64(
|
||||||
|
(s64)ttf_slope * delta_ms, MICRO_UNIT) +
|
||||||
|
chip->ttf.last_ttf;
|
||||||
|
fg_dbg(chip, FG_TTF, "ttf_slope=%d\n", ttf_slope);
|
||||||
|
} else {
|
||||||
|
t_predicted = chip->ttf.last_ttf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* clamp the ttf to 0 */
|
/* clamp the ttf to 0 */
|
||||||
if (t_predicted < 0)
|
if (t_predicted < 0)
|
||||||
t_predicted = 0;
|
t_predicted = 0;
|
||||||
|
|
||||||
fg_dbg(chip, FG_TTF, "t_predicted=%d\n", t_predicted);
|
fg_dbg(chip, FG_TTF, "t_predicted_postfilter=%d\n", t_predicted);
|
||||||
*val = t_predicted;
|
*val = t_predicted;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3238,6 +3265,7 @@ static void ttf_work(struct work_struct *work)
|
||||||
struct fg_chip *chip = container_of(work, struct fg_chip,
|
struct fg_chip *chip = container_of(work, struct fg_chip,
|
||||||
ttf_work.work);
|
ttf_work.work);
|
||||||
int rc, ibatt_now, vbatt_now, ttf;
|
int rc, ibatt_now, vbatt_now, ttf;
|
||||||
|
ktime_t ktime_now;
|
||||||
|
|
||||||
mutex_lock(&chip->ttf.lock);
|
mutex_lock(&chip->ttf.lock);
|
||||||
if (chip->charge_status != POWER_SUPPLY_STATUS_CHARGING &&
|
if (chip->charge_status != POWER_SUPPLY_STATUS_CHARGING &&
|
||||||
|
@ -3274,6 +3302,15 @@ static void ttf_work(struct work_struct *work)
|
||||||
mutex_unlock(&chip->ttf.lock);
|
mutex_unlock(&chip->ttf.lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update the TTF reference point every minute */
|
||||||
|
ktime_now = ktime_get_boottime();
|
||||||
|
if (ktime_ms_delta(ktime_now,
|
||||||
|
ms_to_ktime(chip->ttf.last_ms)) > 60000 ||
|
||||||
|
chip->ttf.last_ms == 0) {
|
||||||
|
chip->ttf.last_ttf = ttf;
|
||||||
|
chip->ttf.last_ms = ktime_to_ms(ktime_now);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* recurse every 10 seconds */
|
/* recurse every 10 seconds */
|
||||||
|
|
Loading…
Add table
Reference in a new issue