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

Commit 336bb183 authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy
Browse files

power: qpnp-fg: fix retry transaction in IMA read



When the start and end beat counts do not match during IMA read,
clear IMA_REQ_ACCESS before retrying the transaction again.

Also, as per the hardware documentation, RIF_MEM_ACCESS_REQ
status has to be checked before doing an IMA read/write. Without
doing that, there is a chance of interrupting an ongoing SRAM
access ending up in IMA exception. Fix it.

CRs-Fixed: 950434
Change-Id: Ia899c7c300b01ce56149cfc1d97ed464fedc2724
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 1acad2bb
Loading
Loading
Loading
Loading
+55 −12
Original line number Diff line number Diff line
@@ -671,33 +671,43 @@ static int fg_masked_write(struct fg_chip *chip, u16 addr,
}

#define RIF_MEM_ACCESS_REQ	BIT(7)
static inline bool fg_check_sram_access(struct fg_chip *chip)
static int fg_check_rif_mem_access(struct fg_chip *chip, bool *status)
{
	int rc;
	u8 mem_if_sts;

	rc = fg_read(chip, &mem_if_sts, INT_RT_STS(chip->mem_base), 1);
	rc = fg_read(chip, &mem_if_sts, MEM_INTF_CFG(chip), 1);
	if (rc) {
		pr_err("failed to read mem status rc=%d\n", rc);
		pr_err("failed to read rif_mem status rc=%d\n", rc);
		return rc;
	}

	*status = mem_if_sts & RIF_MEM_ACCESS_REQ;
	return 0;
}

	if ((mem_if_sts & BIT(FG_MEM_AVAIL)) == 0)
		return false;
static bool fg_check_sram_access(struct fg_chip *chip)
{
	int rc;
	u8 mem_if_sts;
	bool rif_mem_sts = false;

	rc = fg_read(chip, &mem_if_sts, MEM_INTF_CFG(chip), 1);
	rc = fg_read(chip, &mem_if_sts, INT_RT_STS(chip->mem_base), 1);
	if (rc) {
		pr_err("failed to read mem status rc=%d\n", rc);
		return 0;
		return false;
	}

	if ((mem_if_sts & RIF_MEM_ACCESS_REQ) == 0)
	if ((mem_if_sts & BIT(FG_MEM_AVAIL)) == 0)
		return false;

	return true;
	rc = fg_check_rif_mem_access(chip, &rif_mem_sts);
	if (rc)
		return false;

	return rif_mem_sts;
}

#define RIF_MEM_ACCESS_REQ	BIT(7)
static inline int fg_assert_sram_access(struct fg_chip *chip)
{
	int rc;
@@ -1263,6 +1273,34 @@ static int fg_interleaved_mem_config(struct fg_chip *chip, u8 *val,
		u16 address, int len, int offset, int op)
{
	int rc = 0;
	bool rif_mem_sts = true;
	int time_count = 0;

	while (1) {
		rc = fg_check_rif_mem_access(chip, &rif_mem_sts);
		if (rc)
			return rc;

		if (!rif_mem_sts)
			break;

		if (fg_debug_mask & (FG_MEM_DEBUG_READS | FG_MEM_DEBUG_WRITES))
			pr_info("RIF_MEM_ACCESS_REQ is not clear yet for IMA_%s\n",
				op ? "write" : "read");

		/*
		 * Try this no more than 4 times. If RIF_MEM_ACCESS_REQ is not
		 * clear, then return an error instead of waiting for it again.
		 */
		if  (time_count > 4) {
			pr_err("Waited for 1.5 seconds polling RIF_MEM_ACCESS_REQ\n");
			return -ETIMEDOUT;
		}

		/* Wait for 4ms before reading RIF_MEM_ACCESS_REQ again */
		usleep_range(4000, 4100);
		time_count++;
	}

	/* configure for IMA access */
	rc = fg_masked_write(chip, MEM_INTF_CFG(chip),
@@ -1307,6 +1345,7 @@ static int fg_interleaved_mem_read(struct fg_chip *chip, u8 *val, u16 address,
{
	int rc = 0, orig_address = address;
	u8 start_beat_count, end_beat_count, count = 0;
	bool retry = false;

	if (offset > 3) {
		pr_err("offset too large %d\n", offset);
@@ -1375,7 +1414,7 @@ retry:
	if (start_beat_count != end_beat_count) {
		if (fg_debug_mask & FG_MEM_DEBUG_READS)
			pr_info("Beat count do not match - retry transaction\n");
		goto retry;
		retry = true;
	}
out:
	/* Release IMA access */
@@ -1383,6 +1422,10 @@ out:
	if (rc)
		pr_err("failed to reset IMA access bit rc = %d\n", rc);

	if (retry) {
		retry = false;
		goto retry;
	}
	mutex_unlock(&chip->rw_lock);

exit: