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

Commit 4328c9d5 authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy
Browse files

power: qpnp-fg: improve IMA error checking mechanism



Currently, we check for IMA errors only after the transaction is
initiated. Check for it even before the transactions begin from
hardware status. This way it will be guaranteed that the hardware
is in a right state.

Also, while checking for errors, it would be more appropriate to
check for the error bits in exception status than just the error
status as the former has more information including the latter.

Change-Id: I8826546640313dc73e55aff22f236c4fe18599ad
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 5323264c
Loading
Loading
Loading
Loading
+60 −24
Original line number Diff line number Diff line
@@ -1232,9 +1232,6 @@ out:
#define MEM_INTF_IMA_EXP_STS		0x55
#define MEM_INTF_IMA_HW_STS		0x56
#define MEM_INTF_IMA_BYTE_EN		0x60
#define IMA_ADDR_STBL_ERR		BIT(7)
#define IMA_WR_ACS_ERR			BIT(6)
#define IMA_RD_ACS_ERR			BIT(5)
#define IMA_IACS_CLR			BIT(2)
#define IMA_IACS_RDY			BIT(1)
static int fg_run_iacs_clear_sequence(struct fg_chip *chip)
@@ -1285,10 +1282,18 @@ static int fg_run_iacs_clear_sequence(struct fg_chip *chip)
	return rc;
}

static int fg_check_ima_exception(struct fg_chip *chip)
#define IACS_ERR_BIT		BIT(0)
#define XCT_ERR_BIT		BIT(1)
#define DATA_RD_ERR_BIT		BIT(3)
#define DATA_WR_ERR_BIT		BIT(4)
#define ADDR_BURST_WRAP_BIT	BIT(5)
#define ADDR_RNG_ERR_BIT	BIT(6)
#define ADDR_SRC_ERR_BIT	BIT(7)
static int fg_check_ima_exception(struct fg_chip *chip, bool check_hw_sts)
{
	int rc = 0, ret = 0;
	u8 err_sts = 0, exp_sts = 0, hw_sts = 0;
	bool run_err_clr_seq = false;

	rc = fg_read(chip, &err_sts,
			chip->mem_base + MEM_INTF_IMA_ERR_STS, 1);
@@ -1297,7 +1302,6 @@ static int fg_check_ima_exception(struct fg_chip *chip)
		return rc;
	}

	if (err_sts & (IMA_ADDR_STBL_ERR | IMA_WR_ACS_ERR | IMA_RD_ACS_ERR)) {
	rc = fg_read(chip, &exp_sts,
			chip->mem_base + MEM_INTF_IMA_EXP_STS, 1);
	if (rc) {
@@ -1312,10 +1316,35 @@ static int fg_check_ima_exception(struct fg_chip *chip)
		return rc;
	}

		pr_err("IMA access failed ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n",
	pr_info_once("Initial ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n",
		err_sts, exp_sts, hw_sts);
		rc = err_sts;

	if (fg_debug_mask & (FG_MEM_DEBUG_READS | FG_MEM_DEBUG_WRITES))
		pr_info("ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n",
			err_sts, exp_sts, hw_sts);

	if (check_hw_sts) {
		/*
		 * Lower nibble should be equal to upper nibble before SRAM
		 * transactions begins from SW side. If they are unequal, then
		 * the error clear sequence should be run irrespective of IMA
		 * exception errors.
		 */
		if ((hw_sts & 0x0F) != hw_sts >> 4) {
			pr_err("IMA HW not in correct state, hw_sts=%x\n",
				hw_sts);
			run_err_clr_seq = true;
		}
	}

	if (exp_sts & (IACS_ERR_BIT | XCT_ERR_BIT | DATA_RD_ERR_BIT |
		DATA_WR_ERR_BIT | ADDR_BURST_WRAP_BIT | ADDR_RNG_ERR_BIT |
		ADDR_SRC_ERR_BIT)) {
		pr_err("IMA exception bit set, exp_sts=%x\n", exp_sts);
		run_err_clr_seq = true;
	}

	if (run_err_clr_seq) {
		ret = fg_run_iacs_clear_sequence(chip);
		if (!ret)
			return -EAGAIN;
@@ -1485,7 +1514,7 @@ static int fg_check_iacs_ready(struct fg_chip *chip)
			pr_err("Couldn't check FG ALG status, rc=%d\n",
				rc);
		/* perform IACS_CLR sequence */
		fg_check_ima_exception(chip);
		fg_check_ima_exception(chip, false);
		return -EBUSY;
	}

@@ -1550,7 +1579,7 @@ static int __fg_interleaved_mem_write(struct fg_chip *chip, u8 *val,
		}

		/* check for error condition */
		rc = fg_check_ima_exception(chip);
		rc = fg_check_ima_exception(chip, false);
		if (rc) {
			pr_err("IMA transaction failed rc=%d", rc);
			return rc;
@@ -1597,7 +1626,7 @@ static int __fg_interleaved_mem_read(struct fg_chip *chip, u8 *val, u16 address,
		}

		/* check for error condition */
		rc = fg_check_ima_exception(chip);
		rc = fg_check_ima_exception(chip, false);
		if (rc) {
			pr_err("IMA transaction failed rc=%d", rc);
			return rc;
@@ -8456,7 +8485,7 @@ out:
#define ANA_MINOR		0x2
#define ANA_MAJOR		0x3
#define IACS_INTR_SRC_SLCT	BIT(3)
static int fg_setup_memif_offset(struct fg_chip *chip)
static int fg_memif_init(struct fg_chip *chip)
{
	int rc;
	u8 dig_major;
@@ -8494,6 +8523,13 @@ static int fg_setup_memif_offset(struct fg_chip *chip)
			pr_err("failed to configure interrupt source %d\n", rc);
			return rc;
		}

		/* check for error condition */
		rc = fg_check_ima_exception(chip, true);
		if (rc) {
			pr_err("Error in clearing IMA exception rc=%d", rc);
			return rc;
		}
	}

	return 0;
@@ -8763,7 +8799,7 @@ static int fg_probe(struct spmi_device *spmi)
		return rc;
	}

	rc = fg_setup_memif_offset(chip);
	rc = fg_memif_init(chip);
	if (rc) {
		pr_err("Unable to setup mem_if offsets rc=%d\n", rc);
		goto of_init_fail;