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

Commit e50d0dc3 authored by Xiaozhe Shi's avatar Xiaozhe Shi
Browse files

power: qpnp-bms: estimate OCVs based on temperature



The BMS driver will throw out the hardware taken open circuit voltage
(OCV) if there has been a warm reset and the PMIC did not go through
the power on sequence. This is to throw out the stale OCVs from the
last boot.

However, if there is no shutdown SOC stored, the BMS driver must
estimate an OCV. When estimating an OCV, there is no information about
the battery state of charge yet, so the default battery resistance is
used to do the estimation. However, this only works in cases where the
battery temperature is not cold.

When the battery temperature is cold, the real rbatt will be much larger
than the default rbatt. If the default rbatt is used, the estimated OCV
will most likely be much too low, and a faulty SOC will be used. This
issue is exacerbated by the fact that the shutdown SOC is thrown out
when the battery is cold, so this situation can arise much more
frequently.

Fix this by estimating the battery OCV based on temperature and just
using a default rbatt SOC of 50%.

Change-Id: Ibc89fcd74a295bb2196be2d8c977e8b1b8598d7a
Signed-off-by: default avatarXiaozhe Shi <xiaozhes@codeaurora.org>
parent 235cd46b
Loading
Loading
Loading
Loading
+28 −29
Original line number Diff line number Diff line
@@ -907,13 +907,32 @@ static int get_simultaneous_batt_v_and_i(struct qpnp_bms_chip *chip,
	return 0;
}

static int estimate_ocv(struct qpnp_bms_chip *chip)
static int get_rbatt(struct qpnp_bms_chip *chip,
					int soc_rbatt_mohm, int batt_temp)
{
	int ibat_ua, vbat_uv, ocv_est_uv;
	int rc;
	int rbatt_mohm = chip->default_rbatt_mohm + chip->r_conn_mohm
					+ chip->rbatt_capacitive_mohm;
	int rbatt_mohm, scalefactor;

	rbatt_mohm = chip->default_rbatt_mohm;
	if (chip->rbatt_sf_lut == NULL)  {
		pr_debug("RBATT = %d\n", rbatt_mohm);
		return rbatt_mohm;
	}
	/* Convert the batt_temp to DegC from deciDegC */
	scalefactor = interpolate_scalingfactor(chip->rbatt_sf_lut,
						batt_temp, soc_rbatt_mohm);
	rbatt_mohm = (rbatt_mohm * scalefactor) / 100;

	rbatt_mohm += chip->r_conn_mohm;
	rbatt_mohm += chip->rbatt_capacitive_mohm;
	return rbatt_mohm;
}

#define DEFAULT_RBATT_SOC	50
static int estimate_ocv(struct qpnp_bms_chip *chip, int batt_temp)
{
	int ibat_ua, vbat_uv, ocv_est_uv, rbatt_mohm, rc;

	rbatt_mohm = get_rbatt(chip, DEFAULT_RBATT_SOC, batt_temp);
	rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
	if (rc) {
		pr_err("simultaneous failed rc = %d\n", rc);
@@ -921,7 +940,8 @@ static int estimate_ocv(struct qpnp_bms_chip *chip)
	}

	ocv_est_uv = vbat_uv + (ibat_ua * rbatt_mohm) / 1000;
	pr_debug("estimated pon ocv = %d\n", ocv_est_uv);
	pr_debug("estimated pon ocv = %d, vbat_uv = %d ibat_ua = %d rbatt_mohm = %d\n",
			ocv_est_uv, vbat_uv, ibat_ua, rbatt_mohm);
	return ocv_est_uv;
}

@@ -1046,10 +1066,9 @@ static int read_soc_params_raw(struct qpnp_bms_chip *chip,
		pr_debug("PON_OCV_UV = %d, cc = %llx\n",
				chip->last_ocv_uv, raw->cc);
		warm_reset = qpnp_pon_is_warm_reset();
		if (raw->last_good_ocv_uv < MIN_OCV_UV
				|| warm_reset > 0) {
		if (raw->last_good_ocv_uv < MIN_OCV_UV || warm_reset > 0) {
			pr_debug("OCV is stale or bad, estimating new OCV.\n");
			chip->last_ocv_uv = estimate_ocv(chip);
			chip->last_ocv_uv = estimate_ocv(chip, batt_temp);
			raw->last_good_ocv_uv = chip->last_ocv_uv;
			reset_cc(chip, CLEAR_CC | CLEAR_SHDW_CC);
			pr_debug("New PON_OCV_UV = %d, cc = %llx\n",
@@ -1218,26 +1237,6 @@ static int calculate_cc(struct qpnp_bms_chip *chip, int64_t cc,
	}
}

static int get_rbatt(struct qpnp_bms_chip *chip,
					int soc_rbatt_mohm, int batt_temp)
{
	int rbatt_mohm, scalefactor;

	rbatt_mohm = chip->default_rbatt_mohm;
	if (chip->rbatt_sf_lut == NULL)  {
		pr_debug("RBATT = %d\n", rbatt_mohm);
		return rbatt_mohm;
	}
	/* Convert the batt_temp to DegC from deciDegC */
	scalefactor = interpolate_scalingfactor(chip->rbatt_sf_lut,
						batt_temp, soc_rbatt_mohm);
	rbatt_mohm = (rbatt_mohm * scalefactor) / 100;

	rbatt_mohm += chip->r_conn_mohm;
	rbatt_mohm += chip->rbatt_capacitive_mohm;
	return rbatt_mohm;
}

#define IAVG_MINIMAL_TIME	2
static void calculate_iavg(struct qpnp_bms_chip *chip, int cc_uah,
				int *iavg_ua, int delta_time_s)