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

Commit ce98c02e authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mmc: sdhci-msm: Fix HW issue with power IRQ handling during reset"

parents 2344e053 0f5fd60a
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -2068,6 +2068,18 @@ static int sdhci_msm_set_vdd_io_vol(struct sdhci_msm_pltfm_data *pdata,
	return ret;
}

void sdhci_msm_dump_pwr_ctrl_regs(struct sdhci_host *host)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_msm_host *msm_host = pltfm_host->priv;

	pr_err("%s: PWRCTL_STATUS: 0x%08x | PWRCTL_MASK: 0x%08x | PWRCTL_CTL: 0x%08x\n",
		mmc_hostname(host->mmc),
		readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS),
		readl_relaxed(msm_host->core_mem + CORE_PWRCTL_MASK),
		readl_relaxed(msm_host->core_mem + CORE_PWRCTL_CTL));
}

static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
{
	struct sdhci_host *host = (struct sdhci_host *)data;
@@ -2078,6 +2090,7 @@ static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
	int ret = 0;
	int pwr_state = 0, io_level = 0;
	unsigned long flags;
	int retry = 10;

	irq_status = readb_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
	pr_debug("%s: Received IRQ(%d), status=0x%x\n",
@@ -2092,6 +2105,29 @@ static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
	 * completed before its next update to registers within hc_mem.
	 */
	mb();
	/*
	 * There is a rare HW scenario where the first clear pulse could be
	 * lost when actual reset and clear/read of status register is
	 * happening at a time. Hence, retry for at least 10 times to make
	 * sure status register is cleared. Otherwise, this will result in
	 * a spurious power IRQ resulting in system instability.
	 */
	while (irq_status &
		readb_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS)) {
		if (retry == 0) {
			pr_err("%s: Timedout clearing (0x%x) pwrctl status register\n",
				mmc_hostname(host->mmc), irq_status);
			sdhci_msm_dump_pwr_ctrl_regs(host);
			BUG_ON(1);
		}
		writeb_relaxed(irq_status,
				(msm_host->core_mem + CORE_PWRCTL_CLEAR));
		retry--;
		udelay(10);
	}
	if (likely(retry < 10))
		pr_debug("%s: success clearing (0x%x) pwrctl status register, retries left %d\n",
				mmc_hostname(host->mmc), irq_status, retry);

	/* Handle BUS ON/OFF*/
	if (irq_status & CORE_PWRCTL_BUS_ON) {