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

Commit c88d00c6 authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy
Browse files

power: fg-memif: Add workaround for DMA during SRAM access in PM8150B v1



Sometimes in PM8150B v1, FG SRAM can be accessed by HW over DMA
even after the access is granted to the SW by arbiter. When this
happens, FG SRAM data can get corrupted as HW might be modifying
it along with SW. As per the hardware recommendation, configure
PEEK_MUX4 to poll the status of ALG active. If it is asserted
low, wait for 1 ms before DMA is requested during FG SRAM access.

Change-Id: I0d1be7d86f40a515513e6a931264740344eb3263
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 5034c535
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -793,6 +793,37 @@ int fg_interleaved_mem_write(struct fg_dev *fg, u16 address, u8 offset,
	return rc;
}

static int fg_poll_alg_active(struct fg_dev *fg)
{
	u32 retries = 35, poll_time_us = 10000;
	int rc;
	u8 val;

	/*
	 * ALG active should be asserted low within ~164 ms mostly however
	 * during ESR pulsing, a worst case delay of ~320 ms is needed.
	 */
	while (retries--) {
		rc = fg_read(fg, BATT_INFO_PEEK_RD(fg), &val, 1);
		if (rc < 0) {
			pr_err("failed to read PEEK_MUX rc=%d\n", rc);
			return rc;
		}

		if (!(val & ALG_ACTIVE_BIT))
			break;

		usleep_range(poll_time_us, poll_time_us + 1);
	}

	if (val & ALG_ACTIVE_BIT)
		return -ETIMEDOUT;

	/* Wait for 1 ms after ALG active is asserted low */
	usleep_range(1000, 1001);
	return rc;
}

static int fg_direct_mem_release(struct fg_dev *fg)
{
	int rc;
@@ -823,6 +854,14 @@ static int fg_direct_mem_request(struct fg_dev *fg)
	int rc, ret, i = 0;
	u8 val, mask, poll_bit;

	if (fg->wa_flags & PM8150B_V1_DMA_WA) {
		rc = fg_poll_alg_active(fg);
		if (rc < 0) {
			pr_err("Failed to assert ALG active rc=%d\n", rc);
			return rc;
		}
	}

	val = mask = MEM_ARB_REQ_BIT;
	rc = fg_masked_write(fg, MEM_IF_MEM_ARB_CFG(fg), mask, val);
	if (rc < 0) {
@@ -1169,6 +1208,7 @@ static struct fg_dma_address fg_gen4_addr_map[6] = {
static int fg_dma_init(struct fg_dev *fg)
{
	int rc;
	u8 val;

	if (fg->version == GEN3_FG) {
		fg->sram.addr_map = fg_gen3_addr_map;
@@ -1217,6 +1257,17 @@ static int fg_dma_init(struct fg_dev *fg)
		return rc;
	}

	/* Configure PEEK_MUX only for PM8150B v1.0 */
	if (fg->wa_flags & PM8150B_V1_DMA_WA) {
		val = ALG_ACTIVE_PEEK_CFG;
		rc = fg_write(fg, BATT_INFO_PEEK_MUX4(fg), &val, 1);
		if (rc < 0) {
			pr_err("failed to configure batt_info_peek_mux4 rc:%d\n",
				rc);
			return rc;
		}
	}

	return 0;
}

+6 −0
Original line number Diff line number Diff line
@@ -275,6 +275,12 @@
#define ESR_REQ_CTL_BIT				BIT(1)
#define ESR_REQ_CTL_EN_BIT			BIT(0)

#define BATT_INFO_PEEK_MUX4(chip)		(chip->batt_info_base + 0xEE)
#define ALG_ACTIVE_PEEK_CFG			0xAC

#define BATT_INFO_PEEK_RD(chip)			(chip->batt_info_base + 0xEF)
#define ALG_ACTIVE_BIT				BIT(3)

/* FG_MEM_IF register and bit definitions */
#define MEM_IF_INT_RT_STS(chip)			((chip->mem_if_base) + 0x10)
#define MEM_XCP_BIT				BIT(1)