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

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

power: qpnp-fg: fix profile loading for hotswap



During a hotswap, there will always be a first_soc interrupt when the
fuel gauge hardware detects a battery insertion. This completes the
first_soc_done completion that fg_do_restart() waits for, resulting in a
situation where the RESTART_GO bit is immediately cleared without
waiting for an actual fuel gauge restart.

Fix this by changing the semantics of the first_soc_done completion.
The function fg_do_restart() will now reinit the completion before it
restarts the fuel gauge, ensuring that the completion is not completed
when the driver is waiting for the hardware to restart. Also, complete
the first_soc_done completion at probe time if the first_soc_done
interrupt is high.

Change-Id: I970896869df2dfc2d4ad37a1c384915299a0cfb6
Signed-off-by: default avatarXiaozhe Shi <xiaozhes@codeaurora.org>
parent ea0c0d74
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -3717,6 +3717,23 @@ static bool is_battery_missing(struct fg_chip *chip)
	return (fg_batt_sts & BATT_MISSING_STS) ? true : false;
}

#define SOC_FIRST_EST_DONE	BIT(5)
static bool is_first_est_done(struct fg_chip *chip)
{
	int rc;
	u8 fg_soc_sts;

	rc = fg_read(chip, &fg_soc_sts,
				 INT_RT_STS(chip->soc_base), 1);
	if (rc) {
		pr_err("spmi read failed: addr=%03X, rc=%d\n",
				INT_RT_STS(chip->soc_base), rc);
		return false;
	}

	return (fg_soc_sts & SOC_FIRST_EST_DONE) ? true : false;
}

static irqreturn_t fg_vbatt_low_handler(int irq, void *_chip)
{
	struct fg_chip *chip = _chip;
@@ -4340,6 +4357,25 @@ static int fg_do_restart(struct fg_chip *chip, bool write_profile)

	/* decrement the user count so that memory access can be released */
	fg_release_access_if_necessary(chip);

	/*
	 * make sure that the first estimate has completed
	 * in case of a hotswap
	 */
	rc = wait_for_completion_interruptible_timeout(&chip->first_soc_done,
			msecs_to_jiffies(PROFILE_LOAD_TIMEOUT_MS));
	if (rc <= 0) {
		pr_err("transaction timed out rc=%d\n", rc);
		rc = -ETIMEDOUT;
		goto fail;
	}

	/*
	 * reinitialize the completion so that the driver knows when the restart
	 * finishes
	 */
	reinit_completion(&chip->first_soc_done);

	/*
	 * set the restart bits so that the next fg cycle will not reload
	 * the profile
@@ -6231,6 +6267,10 @@ static int fg_probe(struct spmi_device *spmi)
		}
	}

	/* check if the first estimate is already finished at this time */
	if (is_first_est_done(chip))
		complete_all(&chip->first_soc_done);

	reg = 0xFF;
	rc = fg_write(chip, &reg, INT_EN_CLR(chip->mem_base), 1);
	if (rc) {