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

Commit c0a7d5bf authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "power: qpnp-fg-gen4: Add TTF support for step charging"

parents 4e5b8c60 158cb6d7
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;
+71 −1
Original line number Diff line number Diff line
@@ -629,6 +629,8 @@ static int fg_gen4_get_ttf_param(void *data, enum ttf_param param, int *val)
	case TTF_MODE:
		if (is_qnovo_en(fg))
			*val = TTF_MODE_QNOVO;
		else if (chip->ttf->step_chg_cfg_valid)
			*val = TTF_MODE_V_STEP_CHG;
		else
			*val = TTF_MODE_NORMAL;
		break;
@@ -924,7 +926,7 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg)
	struct device_node *node = fg->dev->of_node;
	struct device_node *batt_node, *profile_node;
	const char *data;
	int rc, len;
	int rc, len, i, tuple_len;

	batt_node = of_find_node_by_name(node, "qcom,battery-data");
	if (!batt_node) {
@@ -999,6 +1001,64 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg)
		}
	}

	/*
	 * Currently step charging thresholds should be read only for Vbatt
	 * based and not for SOC based.
	 */
	if (!of_property_read_bool(profile_node, "qcom,soc-based-step-chg") &&
		of_find_property(profile_node, "qcom,step-chg-ranges", &len) &&
		fg->bp.float_volt_uv > 0 && fg->bp.fastchg_curr_ma > 0) {
		len /= sizeof(u32);
		tuple_len = len / (sizeof(struct range_data) / sizeof(u32));
		if (tuple_len <= 0 || tuple_len > MAX_STEP_CHG_ENTRIES)
			return -EINVAL;

		mutex_lock(&chip->ttf->lock);
		chip->ttf->step_chg_cfg =
			kcalloc(len, sizeof(*chip->ttf->step_chg_cfg),
				GFP_KERNEL);
		if (!chip->ttf->step_chg_cfg) {
			mutex_unlock(&chip->ttf->lock);
			return -ENOMEM;
		}

		chip->ttf->step_chg_data =
			kcalloc(tuple_len, sizeof(*chip->ttf->step_chg_data),
				GFP_KERNEL);
		if (!chip->ttf->step_chg_data) {
			kfree(chip->ttf->step_chg_cfg);
			mutex_unlock(&chip->ttf->lock);
			return -ENOMEM;
		}

		rc = read_range_data_from_node(profile_node,
				"qcom,step-chg-ranges",
				chip->ttf->step_chg_cfg,
				fg->bp.float_volt_uv,
				fg->bp.fastchg_curr_ma * 1000);
		if (rc < 0) {
			pr_err("Error in reading qcom,step-chg-ranges from battery profile, rc=%d\n",
				rc);
			kfree(chip->ttf->step_chg_data);
			kfree(chip->ttf->step_chg_cfg);
			chip->ttf->step_chg_cfg = NULL;
			mutex_unlock(&chip->ttf->lock);
			return rc;
		}

		chip->ttf->step_chg_num_params = tuple_len;
		chip->ttf->step_chg_cfg_valid = true;
		mutex_unlock(&chip->ttf->lock);

		if (chip->ttf->step_chg_cfg_valid) {
			for (i = 0; i < tuple_len; i++)
				pr_debug("Vbatt_low: %d Vbatt_high: %d FCC: %d\n",
				chip->ttf->step_chg_cfg[i].low_threshold,
				chip->ttf->step_chg_cfg[i].high_threshold,
				chip->ttf->step_chg_cfg[i].value);
		}
	}

	if (of_find_property(profile_node, "qcom,therm-pull-up", NULL)) {
		rc = of_property_read_u32(profile_node, "qcom,therm-pull-up",
				&fg->bp.therm_pull_up_kohms);
@@ -1765,6 +1825,7 @@ static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data)
{
	struct fg_dev *fg = data;
	struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg);
	u8 status;
	int rc;

@@ -1783,6 +1844,15 @@ static irqreturn_t fg_batt_missing_irq_handler(int irq, void *data)
		fg->profile_load_status = PROFILE_NOT_LOADED;
		fg->soc_reporting_ready = false;
		fg->batt_id_ohms = -EINVAL;

		mutex_lock(&chip->ttf->lock);
		chip->ttf->step_chg_cfg_valid = false;
		chip->ttf->step_chg_num_params = 0;
		kfree(chip->ttf->step_chg_cfg);
		chip->ttf->step_chg_cfg = NULL;
		kfree(chip->ttf->step_chg_data);
		chip->ttf->step_chg_data = NULL;
		mutex_unlock(&chip->ttf->lock);
		return IRQ_HANDLED;
	}