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

Commit bdf36373 authored by Anirudh Ghayal's avatar Anirudh Ghayal
Browse files

power: qpnp-qg: Update the recharge/hold-SOC logic



In the current code the hold-soc logic scales the SOC
when there is a discharge or a re-charge event. However,
the expectation is to hold the SOC to 100% until we
recharge back to 100%. Only start scaling the SOC
if we are indeed discharging (msoc < recharge_soc)
or USB is removed. Also, scale the SOC slower if
we are in the maintenance mode.

Also, the expectation of recharge SOC is to start
start recharge at that SOC value and not a point lower,
fix it accordingly.

Change-Id: Ifb21caf0531fdf042d46a8fd906cb4e067e9910f
Signed-off-by: default avatarAnirudh Ghayal <aghayal@codeaurora.org>
parent 4db6264c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -134,6 +134,7 @@ struct qpnp_qg {
	u32			esr_last;
	ktime_t			last_user_update_time;
	ktime_t			last_fifo_update_time;
	unsigned long		last_maint_soc_update_time;

	/* soc params */
	int			catch_up_soc;
@@ -145,6 +146,7 @@ struct qpnp_qg {
	int			full_soc;
	int			sys_soc;
	int			last_adj_ssoc;
	int			recharge_soc;
	struct alarm		alarm_timer;
	u32			sdam_data[SDAM_MAX];

+40 −7
Original line number Diff line number Diff line
@@ -41,6 +41,11 @@ module_param_named(
	soc_cold_interval_ms, qg_delta_soc_cold_interval_ms, int, 0600
);

static int qg_maint_soc_update_ms = 120000;
module_param_named(
	maint_soc_update_ms, qg_maint_soc_update_ms, int, 0600
);

int qg_adjust_sys_soc(struct qpnp_qg *chip)
{
	int soc, vbat_uv, rc;
@@ -93,10 +98,11 @@ static void get_next_update_time(struct qpnp_qg *chip)

	/* Lower the delta soc interval by half at cold */
	rc = qg_get_battery_temp(chip, &batt_temp);
	if (rc < 0)
		pr_err("Failed to read battery temperature rc=%d\n", rc);
	else if (batt_temp < chip->dt.cold_temp_threshold)
	if (!rc && batt_temp < chip->dt.cold_temp_threshold)
		min_delta_soc_interval_ms = qg_delta_soc_cold_interval_ms;
	else if (chip->maint_soc > 0 && chip->maint_soc >= chip->recharge_soc)
		/* if in maintenance mode scale slower */
		min_delta_soc_interval_ms = qg_maint_soc_update_ms;

	if (!min_delta_soc_interval_ms)
		min_delta_soc_interval_ms = 1000;	/* 1 second */
@@ -135,9 +141,34 @@ static bool is_scaling_required(struct qpnp_qg *chip)
	return true;
}

static bool maint_soc_timeout(struct qpnp_qg *chip)
{
	unsigned long now;
	int rc;

	if (chip->maint_soc < 0)
		return false;

	rc = get_rtc_time(&now);
	if (rc < 0)
		return true;

	/* Do not scale if we have dropped below recharge-soc */
	if (chip->maint_soc < chip->recharge_soc)
		return true;

	if ((now - chip->last_maint_soc_update_time) >=
			(qg_maint_soc_update_ms / 1000)) {
		chip->last_maint_soc_update_time = now;
		return true;
	}

	return false;
}

static void update_msoc(struct qpnp_qg *chip)
{
	int rc = 0, batt_temp = 0,  batt_soc_32bit = 0;
	int rc = 0, sdam_soc, batt_temp = 0,  batt_soc_32bit = 0;
	bool usb_present = is_usb_present(chip);

	if (chip->catch_up_soc > chip->msoc) {
@@ -150,7 +181,8 @@ static void update_msoc(struct qpnp_qg *chip)
	}
	chip->msoc = CAP(0, 100, chip->msoc);

	if (chip->maint_soc > 0 && chip->msoc < chip->maint_soc) {
	if (chip->maint_soc > 0 && chip->msoc < chip->maint_soc
				&& maint_soc_timeout(chip)) {
		chip->maint_soc -= chip->dt.delta_soc;
		chip->maint_soc = CAP(0, 100, chip->maint_soc);
	}
@@ -165,8 +197,9 @@ static void update_msoc(struct qpnp_qg *chip)
		pr_err("Failed to update MSOC register rc=%d\n", rc);

	/* update SDAM with the new MSOC */
	chip->sdam_data[SDAM_SOC] = chip->msoc;
	rc = qg_sdam_write(SDAM_SOC, chip->msoc);
	sdam_soc = (chip->maint_soc > 0) ? chip->maint_soc : chip->msoc;
	chip->sdam_data[SDAM_SOC] = sdam_soc;
	rc = qg_sdam_write(SDAM_SOC, sdam_soc);
	if (rc < 0)
		pr_err("Failed to update SDAM with MSOC rc=%d\n", rc);

+36 −16
Original line number Diff line number Diff line
@@ -1858,9 +1858,11 @@ static int qg_charge_full_update(struct qpnp_qg *chip)
		recharge_soc = DEFAULT_RECHARGE_SOC;
	}
	recharge_soc = prop.intval;
	chip->recharge_soc = recharge_soc;

	qg_dbg(chip, QG_DEBUG_STATUS, "msoc=%d health=%d charge_full=%d\n",
				chip->msoc, health, chip->charge_full);
	qg_dbg(chip, QG_DEBUG_STATUS, "msoc=%d health=%d charge_full=%d charge_done=%d\n",
				chip->msoc, health, chip->charge_full,
				chip->charge_done);
	if (chip->charge_done && !chip->charge_full) {
		if (chip->msoc >= 99 && health == POWER_SUPPLY_HEALTH_GOOD) {
			chip->charge_full = true;
@@ -1871,10 +1873,18 @@ static int qg_charge_full_update(struct qpnp_qg *chip)
			qg_dbg(chip, QG_DEBUG_STATUS, "Terminated charging @ msoc=%d\n",
					chip->msoc);
		}
	} else if ((!chip->charge_done || chip->msoc < recharge_soc)
	} else if ((!chip->charge_done || chip->msoc <= recharge_soc)
				&& chip->charge_full) {

		if (chip->wa_flags & QG_RECHARGE_SOC_WA) {
		bool usb_present = is_usb_present(chip);

		/*
		 * force a recharge only if SOC <= recharge SOC and
		 * we have not started charging.
		 */
		if ((chip->wa_flags & QG_RECHARGE_SOC_WA) &&
			usb_present && chip->msoc <= recharge_soc &&
			chip->charge_status != POWER_SUPPLY_STATUS_CHARGING) {
			/* Force recharge */
			prop.intval = 0;
			rc = power_supply_set_property(chip->batt_psy,
@@ -1882,23 +1892,33 @@ static int qg_charge_full_update(struct qpnp_qg *chip)
			if (rc < 0)
				pr_err("Failed to force recharge rc=%d\n", rc);
			else
				qg_dbg(chip, QG_DEBUG_STATUS,
					"Forced recharge\n");
				qg_dbg(chip, QG_DEBUG_STATUS, "Forced recharge\n");
		}


		if (chip->charge_done)
			return 0;	/* wait for recharge */

		/*
		 * If recharge or discharge has started and
		 * if linearize soc dtsi property defined
		 * scale msoc from 100% for better UX.
		 * If SOC has indeed dropped below recharge-SOC or
		 * the USB is removed, if linearize-soc is set scale
		 * msoc from 100% for better UX.
		 */
		if (chip->dt.linearize_soc && chip->msoc < 99) {
		if (chip->msoc < recharge_soc || !usb_present) {
			if (chip->dt.linearize_soc) {
				get_rtc_time(&chip->last_maint_soc_update_time);
				chip->maint_soc = FULL_SOC;
				qg_scale_soc(chip, false);
			}

			chip->charge_full = false;
			qg_dbg(chip, QG_DEBUG_STATUS, "msoc=%d recharge_soc=%d charge_full (1->0)\n",
					chip->msoc, recharge_soc);
		chip->charge_full = false;
		} else {
			/* continue with charge_full state */
			qg_dbg(chip, QG_DEBUG_STATUS, "msoc=%d recharge_soc=%d charge_full=%d usb_present=%d\n",
					chip->msoc, recharge_soc,
					chip->charge_full, usb_present);
		}
	}
out:
	return 0;