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

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

Merge "power: qpnp-qg: Add support for weighted capacity learning"

parents e2c5a35c fa9fb598
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -245,6 +245,20 @@ First Level Node - FG Gen4 device
		    capacity learning cycle. If this is not specified, then
		    the default value is 0. Unit is in decipercentage.

- qcom,cl-min-delta-batt-soc
	Usage:      optional
	Value type: <u32>
	Definition: Minimum change in battery SOC to qualify for capacity
		    learning. If this is not specified, then the default
		    value is 10. Unit is in percentage.

- qcom,cl-wt-enable
	Usage:      optional
	Value type: <empty>
	Definition: A boolean property to enable weighted capacity learning
		    based on change in battery SOC during a charging cycle.
		    If this is specified "qcom,cl-start-capacity" is not used.

- qcom,hold-soc-while-full
	Usage:      optional
	Value type: <empty>
+15 −0
Original line number Diff line number Diff line
@@ -262,6 +262,21 @@ First Level Node - QGAUGE device
		    capacity learning cycle. If this is not specified, then
		    the default value is 0. Unit is in decipercentage.

- qcom,cl-min-delta-batt-soc
        Usage:      optional
        Value type: <u32>
        Definition: Minimum change in battery SOC to qualify for capacity
                    learning. If this is not specified, then the default
                    value is 10. Unit is in percentage.

- qcom,cl-wt-enable
	Usage:      optional
	Value type: <empty>
	Definition: A boolean property to enable weighted capacity learning
		    based on change in battery SOC during a charging cycle.
		    If this is specified, then "qcom,cl-min-start-soc" and
		    "qcom,cl-max-start-soc" is not used.

- qcom,esr-disable
	Usage:      optional
	Value type: <bool>
+107 −20
Original line number Diff line number Diff line
@@ -369,17 +369,63 @@ static void cap_learning_post_process(struct cap_learning *cl)
		cl->final_cap_uah, old_cap, cl->learned_cap_uah);
}

/**
 * cap_wt_learning_process_full_data -
 * @cl: Capacity learning object
 * @batt_soc_pct: Battery State of Charge in percent
 * @cc_soc_delta_pct: percentage change in cc_soc
 * @delta_batt_soc_pct: percentage change in battery State of Charge
 *
 * Calculates the final learnt capacity when
 * weighted capacity learning is enabled.
 *
 */
static int cap_wt_learning_process_full_data(struct cap_learning *cl,
					int batt_soc_pct, int cc_soc_delta_pct,
					int delta_batt_soc_pct)
{
	int64_t delta_cap_uah, del_cap_uah, total_cap_uah,
		res_cap_uah, wt_learnt_cap_uah;

	/* If the delta is < 10%, then skip processing full data */
	if (delta_batt_soc_pct < cl->dt.min_delta_batt_soc) {
		pr_debug("batt_soc_delta_pct: %d\n", delta_batt_soc_pct);
		return -ERANGE;
	}

	delta_cap_uah = div64_s64(cl->learned_cap_uah * cc_soc_delta_pct, 100);
	/* Learnt Capacity from end Battery SOC to 100 % */
	res_cap_uah = div64_s64(cl->learned_cap_uah *
				(100 - batt_soc_pct), 100);
	total_cap_uah = cl->init_cap_uah + delta_cap_uah + res_cap_uah;
	/*
	 * difference in capacity learnt in this
	 * charge cycle and previous learnt capacity
	 */
	del_cap_uah = total_cap_uah - cl->learned_cap_uah;
	/* Applying weight based on change in battery SOC */
	wt_learnt_cap_uah = div64_s64(del_cap_uah * delta_batt_soc_pct,
					100);
	cl->final_cap_uah = cl->learned_cap_uah + wt_learnt_cap_uah;

	pr_debug("cc_soc_delta_pct=%d total_cap_uah=%lld\n",
		cc_soc_delta_pct, cl->final_cap_uah);
	return 0;
}

/**
 * cap_learning_process_full_data -
 * @cl: Capacity learning object
 * @batt_soc_msb: Most significant byte of Battery State of Charge
 *
 * Processes the coulomb counter during charge termination and calculates the
 * delta w.r.to the coulomb counter obtained earlier when the learning begun.
 *
 */
static int cap_learning_process_full_data(struct cap_learning *cl)
static int cap_learning_process_full_data(struct cap_learning *cl,
					int batt_soc_msb)
{
	int rc, cc_soc_sw, cc_soc_delta_pct;
	int rc, cc_soc_sw, cc_soc_delta_pct, delta_batt_soc_pct, batt_soc_pct;
	int64_t delta_cap_uah;

	rc = cl->get_cc_soc(cl->data, &cc_soc_sw);
@@ -388,10 +434,19 @@ static int cap_learning_process_full_data(struct cap_learning *cl)
		return rc;
	}

	batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW);
	delta_batt_soc_pct = batt_soc_pct - cl->init_batt_soc;
	cc_soc_delta_pct =
		div64_s64((int64_t)(cc_soc_sw - cl->init_cc_soc_sw) * 100,
			cl->cc_soc_max);

	if (cl->dt.cl_wt_enable) {
		rc = cap_wt_learning_process_full_data(cl, batt_soc_pct,
							cc_soc_delta_pct,
							delta_batt_soc_pct);
		return rc;
	}

	/* If the delta is < 50%, then skip processing full data */
	if (cc_soc_delta_pct < 50) {
		pr_err("cc_soc_delta_pct: %d\n", cc_soc_delta_pct);
@@ -422,12 +477,14 @@ static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc)
	batt_soc_msb = batt_soc >> 24;
	batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW);

	if (!cl->dt.cl_wt_enable) {
		if (batt_soc_pct > cl->dt.max_start_soc ||
				batt_soc_pct < cl->dt.min_start_soc) {
			pr_debug("Battery SOC %d is high/low, not starting\n",
					batt_soc_pct);
			return -EINVAL;
		}
	}

	cl->init_cap_uah = div64_s64(cl->learned_cap_uah * batt_soc_msb,
					FULL_SOC_RAW);
@@ -451,6 +508,7 @@ static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc)
	}

	cl->init_cc_soc_sw = cc_soc_sw;
	cl->init_batt_soc = batt_soc_pct;
	pr_debug("Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n",
		batt_soc_msb, cl->init_cc_soc_sw);
out:
@@ -460,18 +518,19 @@ static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc)
/**
 * cap_learning_done -
 * @cl: Capacity learning object
 * @batt_soc_msb: Most significant byte of battery State of Charge
 *
 * Top level function for getting coulomb counter and post processing the
 * data once the capacity learning is complete after charge termination.
 *
 */
static int cap_learning_done(struct cap_learning *cl)
static int cap_learning_done(struct cap_learning *cl, int batt_soc_msb)
{
	int rc;

	rc = cap_learning_process_full_data(cl);
	rc = cap_learning_process_full_data(cl, batt_soc_msb);
	if (rc < 0) {
		pr_err("Error in processing cap learning full data, rc=%d\n",
		pr_debug("Error in processing cap learning full data, rc=%d\n",
			rc);
		goto out;
	}
@@ -490,6 +549,30 @@ static int cap_learning_done(struct cap_learning *cl)
	return rc;
}

/**
 * cap_wt_learning_update -
 * @cl: Capacity learning object
 * @batt_soc_msb: Most significant byte of battery State of Charge
 * @input_present: Indicator for input presence
 *
 * Called by cap_learning_update when weighted learning is enabled
 *
 */
static void cap_wt_learning_update(struct cap_learning *cl, int batt_soc_msb,
					bool input_present)
{
	int rc;

	if (!input_present) {
		rc = cap_learning_done(cl, batt_soc_msb);
		if (rc < 0)
			pr_debug("Error in completing capacity learning, rc=%d\n",
				rc);
		cl->active = false;
		cl->init_cap_uah = 0;
	}
}

/**
 * cap_learning_update -
 * @cl: Capacity learning object
@@ -526,6 +609,10 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp,
	pr_debug("Charge_status: %d active: %d batt_soc: %d\n",
		charge_status, cl->active, batt_soc_msb);

	if (cl->active && cl->dt.cl_wt_enable)
		cap_wt_learning_update(cl, batt_soc_msb,
					input_present);

	/* Initialize the starting point of learning capacity */
	if (!cl->active) {
		if (charge_status == POWER_SUPPLY_STATUS_CHARGING) {
@@ -538,7 +625,7 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp,
		}
	} else {
		if (charge_done) {
			rc = cap_learning_done(cl);
			rc = cap_learning_done(cl, batt_soc_msb);
			if (rc < 0)
				pr_err("Error in completing capacity learning, rc=%d\n",
					rc);
@@ -547,17 +634,17 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp,
			cl->init_cap_uah = 0;
		}

		if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING) {
			if (!input_present) {
		if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING &&
				!input_present) {
			pr_debug("Capacity learning aborted @ battery SOC %d\n",
				 batt_soc_msb);
			cl->active = false;
			cl->init_cap_uah = 0;
			prime_cc = true;
		}
		}

		if (charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
		if (charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING &&
				!cl->dt.cl_wt_enable) {
			if (qnovo_en && input_present) {
				/*
				 * Don't abort the capacity learning when qnovo
+3 −0
Original line number Diff line number Diff line
@@ -48,12 +48,15 @@ struct cl_params {
	int	max_cap_limit;
	int	min_cap_limit;
	int	skew_decipct;
	int	min_delta_batt_soc;
	bool	cl_wt_enable;
};

struct cap_learning {
	void			*data;
	int			init_cc_soc_sw;
	int			cc_soc_max;
	int			init_batt_soc;
	int64_t			nom_cap_uah;
	int64_t			init_cap_uah;
	int64_t			final_cap_uah;
+9 −0
Original line number Diff line number Diff line
@@ -4363,6 +4363,7 @@ static int fg_parse_esr_cal_params(struct fg_dev *fg)
#define DEFAULT_CL_MAX_DEC_DECIPERC	100
#define DEFAULT_CL_MIN_LIM_DECIPERC	0
#define DEFAULT_CL_MAX_LIM_DECIPERC	0
#define DEFAULT_CL_DELTA_BATT_SOC	10
#define BTEMP_DELTA_LOW			0
#define BTEMP_DELTA_HIGH		3
#define DEFAULT_ESR_PULSE_THRESH_MA	47
@@ -4529,6 +4530,14 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip)
	else
		chip->cl->dt.max_start_soc = temp;

	chip->cl->dt.min_delta_batt_soc = DEFAULT_CL_DELTA_BATT_SOC;
	/* read from DT property and update, if value exists */
	of_property_read_u32(node, "qcom,cl-min-delta-batt-soc",
					&chip->cl->dt.min_delta_batt_soc);

	chip->cl->dt.cl_wt_enable = of_property_read_bool(node,
						"qcom,cl-wt-enable");

	rc = of_property_read_u32(node, "qcom,cl-min-temp", &temp);
	if (rc < 0)
		chip->cl->dt.min_temp = DEFAULT_CL_MIN_TEMP_DECIDEGC;
Loading