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

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

Merge "power: qpnp-fg-gen4: Support OCV based step charging in TTF algorithm"

parents 0f13fdff 7d016c8f
Loading
Loading
Loading
Loading
+96 −35
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2018 The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
 */

#define pr_fmt(fmt)	"ALG: %s: " fmt, __func__
@@ -886,6 +886,62 @@ static int ttf_lerp(const struct ttf_pt *pts, size_t tablesize,
	return -EINVAL;
}

static int get_step_chg_current_window(struct ttf *ttf)
{
	struct range_data *step_chg_cfg = ttf->step_chg_cfg;
	int i, rc, curr_window, vbatt;

	if (ttf->mode == TTF_MODE_V_STEP_CHG) {
		rc =  ttf->get_ttf_param(ttf->data, TTF_VBAT, &vbatt);
		if (rc < 0) {
			pr_err("failed to get battery voltage, rc=%d\n", rc);
			return rc;
		}
	} else {
		rc = ttf->get_ttf_param(ttf->data, TTF_OCV, &vbatt);
		if (rc < 0) {
			pr_err("failed to get battery OCV, 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))
			curr_window = i;
	}

	return curr_window;
}

static int get_cc2cv_current(struct ttf *ttf, int ibatt_avg, int vbatt_avg,
				int float_volt_uv)
{
	int i_cc2cv = 0;

	switch (ttf->mode) {
	case TTF_MODE_NORMAL:
	case TTF_MODE_V_STEP_CHG:
	case TTF_MODE_OCV_STEP_CHG:
		i_cc2cv = ibatt_avg * vbatt_avg /
			max(MILLI_UNIT, float_volt_uv / MILLI_UNIT);
		break;
	case TTF_MODE_QNOVO:
		i_cc2cv = min(
			ttf->cc_step.arr[MAX_CC_STEPS - 1] / MILLI_UNIT,
			ibatt_avg * vbatt_avg /
			max(MILLI_UNIT, float_volt_uv / MILLI_UNIT));
		break;
	default:
		pr_err("TTF mode %d is not supported\n", ttf->mode);
		break;
	}

	return i_cc2cv;
}

static int get_time_to_full_locked(struct ttf *ttf, int *val)
{
	struct step_chg_data *step_chg_data = ttf->step_chg_data;
@@ -896,7 +952,7 @@ static int get_time_to_full_locked(struct ttf *ttf, int *val)
		ibatt_this_step, t_predicted_this_step, ttf_slope,
		t_predicted_cv, t_predicted = 0, charge_type = 0, i_step,
		float_volt_uv = 0;
	int vbatt_now, multiplier, curr_window = 0, pbatt_avg;
	int multiplier, curr_window = 0, pbatt_avg;
	bool power_approx = false;
	s64 delta_ms;

@@ -985,22 +1041,7 @@ static int get_time_to_full_locked(struct ttf *ttf, int *val)
	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;
	case TTF_MODE_QNOVO:
		i_cc2cv = min(
			ttf->cc_step.arr[MAX_CC_STEPS - 1] / MILLI_UNIT,
			ibatt_avg * vbatt_avg /
			max(MILLI_UNIT, float_volt_uv / MILLI_UNIT));
		break;
	default:
		pr_err("TTF mode %d is not supported\n", ttf->mode);
		break;
	}
	i_cc2cv = get_cc2cv_current(ttf, ibatt_avg, vbatt_avg, float_volt_uv);
	pr_debug("TTF: i_cc2cv=%d\n", i_cc2cv);

	/* if we are already in CV state then we can skip estimating CC */
@@ -1045,23 +1086,15 @@ static int get_time_to_full_locked(struct ttf *ttf, int *val)
		}
		break;
	case TTF_MODE_V_STEP_CHG:
	case TTF_MODE_OCV_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;
		curr_window = get_step_chg_current_window(ttf);
		if (curr_window < 0) {
			pr_err("Failed to get step charging window\n");
			return curr_window;
		}

		pr_debug("TTF: curr_window: %d pbatt_avg: %d\n", curr_window,
@@ -1093,8 +1126,13 @@ static int get_time_to_full_locked(struct ttf *ttf, int *val)
							MILLI_UNIT);
			}

			step_chg_data[i].ocv = step_chg_cfg[i].high_threshold -
			if (ttf->mode == TTF_MODE_V_STEP_CHG)
				step_chg_data[i].ocv =
					step_chg_cfg[i].high_threshold -
					(rbatt * i_step);
			else
				step_chg_data[i].ocv =
					step_chg_cfg[i].high_threshold;

			/* Calculate SOC for each window */
			step_chg_data[i].soc = (float_volt_uv -
@@ -1137,7 +1175,11 @@ static int get_time_to_full_locked(struct ttf *ttf, int *val)
cv_estimate:
	pr_debug("TTF: t_predicted_cc=%d\n", t_predicted);

	if (charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER)
		iterm = max(100, abs(iterm));
	else
		iterm = max(100, abs(iterm) + ttf->iterm_delta);

	pr_debug("TTF: iterm=%d\n", iterm);

	if (charge_type == POWER_SUPPLY_CHARGE_TYPE_TAPER)
@@ -1211,11 +1253,12 @@ int ttf_get_time_to_full(struct ttf *ttf, int *val)
	return rc;
}

#define DELTA_TTF_IBATT_UA      500000
static void ttf_work(struct work_struct *work)
{
	struct ttf *ttf = container_of(work,
				struct ttf, ttf_work.work);
	int rc, ibatt_now, vbatt_now, ttf_now, charge_status;
	int rc, ibatt_now, vbatt_now, ttf_now, charge_status, ibatt_avg;
	ktime_t ktime_now;

	mutex_lock(&ttf->lock);
@@ -1244,6 +1287,24 @@ static void ttf_work(struct work_struct *work)
	ttf_circ_buf_add(&ttf->vbatt, vbatt_now);

	if (charge_status == POWER_SUPPLY_STATUS_CHARGING) {
		rc = ttf_circ_buf_median(&ttf->ibatt, &ibatt_avg);
		if (rc < 0) {
			pr_err("failed to get IBATT AVG rc=%d\n", rc);
			goto end_work;
		}

		/*
		 * While Charging, if Ibatt_now differ from Ibatt_avg by 500mA,
		 * clear Ibatt buffer and refill with settled Ibatt values, to
		 * calculate accurate TTF
		 */
		if (ibatt_now < 0 && (abs(ibatt_now -
					ibatt_avg) >= DELTA_TTF_IBATT_UA)) {
			pr_debug("Clear Ibatt buffer, Ibatt_avg=%d Ibatt_now=%d\n",
					ibatt_avg, ibatt_now);
			ttf_circ_buf_clr(&ttf->ibatt);
		}

		rc = get_time_to_full_locked(ttf, &ttf_now);
		if (rc < 0) {
			pr_err("failed to get ttf, rc=%d\n", rc);
+4 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
 */

#ifndef __FG_ALG_H__
@@ -69,11 +69,13 @@ enum ttf_mode {
	TTF_MODE_NORMAL = 0,
	TTF_MODE_QNOVO,
	TTF_MODE_V_STEP_CHG,
	TTF_MODE_OCV_STEP_CHG,
};

enum ttf_param {
	TTF_MSOC = 0,
	TTF_VBAT,
	TTF_OCV,
	TTF_IBAT,
	TTF_FCC,
	TTF_MODE,
@@ -114,6 +116,7 @@ struct ttf {
	struct step_chg_data	*step_chg_data;
	struct range_data	*step_chg_cfg;
	bool			step_chg_cfg_valid;
	bool			ocv_step_chg_cfg_valid;
	int			step_chg_num_params;
	int			mode;
	int			last_ttf;
+26 −2
Original line number Diff line number Diff line
@@ -851,10 +851,21 @@ static int fg_gen4_get_cell_impedance(struct fg_gen4_chip *chip, int *val)
{
	struct fg_dev *fg = &chip->fg;
	int rc, esr_uohms, temp, vbat_term_mv, v_delta, rprot_uohms = 0;
	int rslow_uohms;

	rc = fg_get_battery_resistance(fg, &esr_uohms);
	if (rc < 0)
	rc = fg_get_sram_prop(fg, FG_SRAM_ESR_ACT, &esr_uohms);
	if (rc < 0) {
		pr_err("failed to get ESR_ACT, rc=%d\n", rc);
		return rc;
	}

	rc = fg_get_sram_prop(fg, FG_SRAM_RSLOW, &rslow_uohms);
	if (rc < 0) {
		pr_err("failed to get Rslow, rc=%d\n", rc);
		return rc;
	}

	esr_uohms += rslow_uohms;

	if (!chip->dt.five_pin_battery)
		goto out;
@@ -1084,6 +1095,11 @@ static int fg_gen4_get_ttf_param(void *data, enum ttf_param param, int *val)
	case TTF_VBAT:
		rc = fg_get_battery_voltage(fg, val);
		break;
	case TTF_OCV:
		rc = fg_get_sram_prop(fg, FG_SRAM_OCV, val);
		if (rc < 0)
			pr_err("Failed to get battery OCV, rc=%d\n", rc);
		break;
	case TTF_IBAT:
		rc = fg_get_battery_current(fg, val);
		break;
@@ -1117,6 +1133,8 @@ static int fg_gen4_get_ttf_param(void *data, enum ttf_param param, int *val)
			*val = TTF_MODE_QNOVO;
		else if (chip->ttf->step_chg_cfg_valid)
			*val = TTF_MODE_V_STEP_CHG;
		else if (chip->ttf->ocv_step_chg_cfg_valid)
			*val = TTF_MODE_OCV_STEP_CHG;
		else
			*val = TTF_MODE_NORMAL;
		break;
@@ -1622,6 +1640,12 @@ static int qpnp_fg_gen4_get_step_charging_params(struct fg_gen4_chip *chip,

		chip->ttf->step_chg_num_params = tuple_len;
		chip->ttf->step_chg_cfg_valid = true;
		if (of_property_read_bool(profile_node,
					   "qcom,ocv-based-step-chg")) {
			chip->ttf->step_chg_cfg_valid = false;
			chip->ttf->ocv_step_chg_cfg_valid = true;
		}

		mutex_unlock(&chip->ttf->lock);

		if (chip->ttf->step_chg_cfg_valid) {