RE: [PATCH] mmc: sdhci-esdhc-imx: wait for data transfer completion before reset
From: Bough Chen <haibo.chen@nxp.com>
Date: 2025-12-03 10:35:16
Also in:
linux-mmc, lkml
-----Original Message----- From: Luke Wang <redacted> Sent: 2025年12月3日 17:59 To: adrian.hunter@intel.com; Bough Chen <haibo.chen@nxp.com>; ulf.hansson@linaro.org Cc: shawnguo@kernel.org; s.hauer@pengutronix.de; kernel@pengutronix.de; festevam@gmail.com; linux-mmc@vger.kernel.org; dl-S32 [off-list ref]; linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org Subject: [PATCH] mmc: sdhci-esdhc-imx: wait for data transfer completion before reset From: Luke Wang <redacted> On IMX7ULP platforms, certain SD cards (e.g. Kingston Canvas Go! Plus) cause system hangs and reboots during manual tuning. These cards exhibit large gaps (~16us) between tuning command response and data transmission. When CRC errors occur during tuning, the code assumes data errors even tuning
When cmd CRC errors occur during tuning,
data hasn't been fully received and then reset host data circuit. Per IMX7ULP reference manual, reset operations (RESET_DATA/ALL) need to make sure no active data transfers. Previously, resetting while data was in-flight caused unknown behavior. This patch adds polling for data transfer completion before executing resets.
You can show more details here for the unknown behavior, like clear the DMA address, causing bus error when use DMA transfer next data. Regards Haibo Chen
quoted hunk ↗ jump to hunk
Signed-off-by: Luke Wang <redacted> --- drivers/mmc/host/sdhci-esdhc-imx.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)diff --git a/drivers/mmc/host/sdhci-esdhc-imx.cb/drivers/mmc/host/sdhci-esdhc-imx.c index a7a5df673b0f..affde1936510 100644--- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c@@ -1453,6 +1453,21 @@ static void esdhc_set_uhs_signaling(structsdhci_host *host, unsigned timing) static void esdhc_reset(struct sdhci_host *host, u8 mask) { + u32 present_state; + int ret; + + /* + * For data or full reset, ensure any active data transfer completes + * before resetting to avoid system hang. + */ + if (mask & (SDHCI_RESET_DATA | SDHCI_RESET_ALL)) { + ret = readl_poll_timeout_atomic(host->ioaddr + ESDHC_PRSSTAT, present_state, + !(present_state & SDHCI_DATA_INHIBIT), 2, 100000); + if (ret == -ETIMEDOUT) + dev_warn(mmc_dev(host->mmc), + "timeout waiting for data transfer completion\n"); + } + sdhci_and_cqhci_reset(host, mask); sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); -- 2.34.1