Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 47c88a85 authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy
Browse files

fg-alg: Add TTF support for step charging



Step charging configuration comes from the battery profile which
defines the variable charging current configurations based on
Vbatt or State of charge (SOC). When voltage based step charging
is enabled, Time to full (TTF) calculations needs a change as the
charging rate changes. As per the hardware recommendation, add
the calculation needed to go through each of the charging window
and compute the time.

Change-Id: I9b264b8af25f93aba20a8609f4786427081764a0
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 0b908b0f
Loading
Loading
Loading
Loading
+95 −2
Original line number Diff line number Diff line
@@ -798,12 +798,16 @@ static int ttf_lerp(const struct ttf_pt *pts, size_t tablesize,

static int get_time_to_full_locked(struct ttf *ttf, int *val)
{
	struct step_chg_data *step_chg_data = ttf->step_chg_data;
	struct range_data *step_chg_cfg = ttf->step_chg_cfg;
	int rc, ibatt_avg, vbatt_avg, rbatt = 0, msoc = 0, act_cap_mah = 0,
		i_cc2cv = 0, soc_cc2cv, tau, divisor, iterm = 0, ttf_mode = 0,
		i, soc_per_step, msoc_this_step, msoc_next_step,
		ibatt_this_step, t_predicted_this_step, ttf_slope,
		t_predicted_cv, t_predicted = 0, charge_type = 0,
		t_predicted_cv, t_predicted = 0, charge_type = 0, i_step,
		float_volt_uv = 0;
	int vbatt_now, multiplier, curr_window = 0, pbatt_avg;
	bool power_approx = false;
	s64 delta_ms;

	rc = ttf->get_ttf_param(ttf->data, TTF_MSOC, &msoc);
@@ -887,9 +891,13 @@ static int get_time_to_full_locked(struct ttf *ttf, int *val)
		pr_err("failed to get charge_type rc=%d\n", rc);
		return rc;
	}

	pr_debug("TTF: mode: %d\n", ttf->mode);

	/* estimated battery current at the CC to CV transition */
	switch (ttf->mode) {
	case TTF_MODE_NORMAL:
	case TTF_MODE_V_STEP_CHG:
		i_cc2cv = ibatt_avg * vbatt_avg /
			max(MILLI_UNIT, float_volt_uv / MILLI_UNIT);
		break;
@@ -945,6 +953,91 @@ static int get_time_to_full_locked(struct ttf *ttf, int *val)
				msoc_this_step, msoc_next_step,
				ibatt_this_step, t_predicted_this_step);
		}
		break;
	case TTF_MODE_V_STEP_CHG:
		if (!step_chg_data || !step_chg_cfg)
			break;

		pbatt_avg = vbatt_avg * ibatt_avg;

		rc =  ttf->get_ttf_param(ttf->data, TTF_VBAT, &vbatt_now);
		if (rc < 0) {
			pr_err("failed to get battery voltage, rc=%d\n", rc);
			return rc;
		}

		curr_window = ttf->step_chg_num_params - 1;
		for (i = 0; i < ttf->step_chg_num_params; i++) {
			if (is_between(step_chg_cfg[i].low_threshold,
					step_chg_cfg[i].high_threshold,
					vbatt_now))
				curr_window = i;
		}

		pr_debug("TTF: curr_window: %d pbatt_avg: %d\n", curr_window,
			pbatt_avg);

		t_predicted_this_step = 0;
		for (i = 0; i < ttf->step_chg_num_params; i++) {
			/*
			 * If Ibatt_avg differs by step charging threshold by
			 * more than 100 mA, then use power approximation to
			 * get charging current step.
			 */

			if (step_chg_cfg[i].value - ibatt_avg > 100)
				power_approx = true;

			/* Calculate OCV for each window */
			if (power_approx) {
				i_step = pbatt_avg / max((u32)MILLI_UNIT,
					(step_chg_cfg[i].high_threshold /
						MILLI_UNIT));
			} else {
				if (i == curr_window)
					i_step = ((step_chg_cfg[i].value /
							MILLI_UNIT) +
							ibatt_avg) / 2;
				else
					i_step = (step_chg_cfg[i].value /
							MILLI_UNIT);
			}

			step_chg_data[i].ocv = step_chg_cfg[i].high_threshold -
						(rbatt * i_step);

			/* Calculate SOC for each window */
			step_chg_data[i].soc = (float_volt_uv -
					step_chg_data[i].ocv) / OCV_SLOPE_UV;
			step_chg_data[i].soc = 100 - step_chg_data[i].soc;

			/* Calculate CC time for each window */
			multiplier = act_cap_mah * HOURS_TO_SECONDS;
			if (curr_window > 0 && i < curr_window)
				t_predicted_this_step = 0;
			else if (i == curr_window)
				t_predicted_this_step =
					div_s64((s64)multiplier *
						(step_chg_data[i].soc - msoc),
						i_step);
			else if (i > 0)
				t_predicted_this_step =
					div_s64((s64)multiplier *
						(step_chg_data[i].soc -
						step_chg_data[i - 1].soc),
						i_step);

			if (t_predicted_this_step < 0)
				t_predicted_this_step = 0;

			t_predicted_this_step =
				DIV_ROUND_CLOSEST(t_predicted_this_step, 100);
			pr_debug("TTF: step: %d i_step: %d OCV: %d SOC: %d t_pred: %d\n",
				i, i_step, step_chg_data[i].ocv,
				step_chg_data[i].soc, t_predicted_this_step);
			t_predicted += t_predicted_this_step;
		}

		break;
	default:
		pr_err("TTF mode %d is not supported\n", ttf->mode);
+17 −0
Original line number Diff line number Diff line
@@ -13,11 +13,18 @@
#ifndef __FG_ALG_H__
#define __FG_ALG_H__

#include "step-chg-jeita.h"

#define BUCKET_COUNT		8
#define BUCKET_SOC_PCT		(256 / BUCKET_COUNT)
#define MAX_CC_STEPS		20
#define MAX_TTF_SAMPLES		10

#define is_between(left, right, value) \
		(((left) >= (right) && (left) >= (value) \
			&& (value) >= (right)) \
		|| ((left) <= (right) && (left) <= (value) \
			&& (value) <= (right)))
struct cycle_counter {
	void		*data;
	char		str_buf[BUCKET_COUNT * 8];
@@ -63,6 +70,7 @@ struct cap_learning {
enum ttf_mode {
	TTF_MODE_NORMAL = 0,
	TTF_MODE_QNOVO,
	TTF_MODE_V_STEP_CHG,
};

enum ttf_param {
@@ -94,12 +102,21 @@ struct ttf_pt {
	s32 y;
};

struct step_chg_data {
	int ocv;
	int soc;
};

struct ttf {
	void			*data;
	struct ttf_circ_buf	ibatt;
	struct ttf_circ_buf	vbatt;
	struct ttf_cc_step_data	cc_step;
	struct mutex		lock;
	struct step_chg_data	*step_chg_data;
	struct range_data	*step_chg_cfg;
	bool			step_chg_cfg_valid;
	int			step_chg_num_params;
	int			mode;
	int			last_ttf;
	int			input_present;