diff mbox series

[v3,13/14] mmc: sdhci-esdhc-imx: clear DMA_SEL when disable DMA mode

Message ID 1581324597-31031-8-git-send-email-haibo.chen@nxp.com (mailing list archive)
State New, archived
Headers show
Series few fix for sdhci-esdhc-imx | expand

Commit Message

Bough Chen Feb. 10, 2020, 8:49 a.m. UTC
From: Haibo Chen <haibo.chen@nxp.com>

Currently, when use standard tuning, driver default disable DMA just before
send tuning command. But on i.MX8 usdhc, this is not enough. Need also clear
DMA_SEL. If not, once the DMA_SEL select AMDA2 before, even dma already disabled,
when send tuning command, usdhc will still prefetch the ADMA script from wrong
DMA address, then we will see IOMMU report some error which show lack of TLB
mapping.

Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
 drivers/mmc/host/sdhci-esdhc-imx.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

Comments

Adrian Hunter Feb. 18, 2020, 8 a.m. UTC | #1
On 10/02/20 10:49 am, haibo.chen@nxp.com wrote:
> From: Haibo Chen <haibo.chen@nxp.com>
> 
> Currently, when use standard tuning, driver default disable DMA just before
> send tuning command. But on i.MX8 usdhc, this is not enough. Need also clear
> DMA_SEL. If not, once the DMA_SEL select AMDA2 before, even dma already disabled,
> when send tuning command, usdhc will still prefetch the ADMA script from wrong
> DMA address, then we will see IOMMU report some error which show lack of TLB
> mapping.
> 
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index dedc067cd0dd..44837e3014e8 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -639,10 +639,24 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
>  			 * For DMA access restore the levels to default value.
>  			 */
>  			m = readl(host->ioaddr + ESDHC_WTMK_LVL);
> -			if (val & SDHCI_TRNS_DMA)
> +			if (val & SDHCI_TRNS_DMA) {
>  				wml = ESDHC_WTMK_LVL_WML_VAL_DEF;
> -			else
> +			} else {
> +				u8 ctrl;
>  				wml = ESDHC_WTMK_LVL_WML_VAL_MAX;
> +
> +				/*
> +				 * Since already disable DMA mode, so also need
> +				 * to clear the DMASEL. Otherwise, for standard
> +				 * tuning, when send tuning command, usdhc will
> +				 * still prefetch the ADMA script from wrong
> +				 * DMA address, then we will see IOMMU report
> +				 * some error which show lack of TLB mapping.
> +				 */
> +				ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
> +				ctrl &= ~SDHCI_CTRL_DMA_MASK;
> +				sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
> +			}
>  			m &= ~(ESDHC_WTMK_LVL_RD_WML_MASK |
>  			       ESDHC_WTMK_LVL_WR_WML_MASK);
>  			m |= (wml << ESDHC_WTMK_LVL_RD_WML_SHIFT) |
>
diff mbox series

Patch

diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index dedc067cd0dd..44837e3014e8 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -639,10 +639,24 @@  static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 			 * For DMA access restore the levels to default value.
 			 */
 			m = readl(host->ioaddr + ESDHC_WTMK_LVL);
-			if (val & SDHCI_TRNS_DMA)
+			if (val & SDHCI_TRNS_DMA) {
 				wml = ESDHC_WTMK_LVL_WML_VAL_DEF;
-			else
+			} else {
+				u8 ctrl;
 				wml = ESDHC_WTMK_LVL_WML_VAL_MAX;
+
+				/*
+				 * Since already disable DMA mode, so also need
+				 * to clear the DMASEL. Otherwise, for standard
+				 * tuning, when send tuning command, usdhc will
+				 * still prefetch the ADMA script from wrong
+				 * DMA address, then we will see IOMMU report
+				 * some error which show lack of TLB mapping.
+				 */
+				ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+				ctrl &= ~SDHCI_CTRL_DMA_MASK;
+				sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+			}
 			m &= ~(ESDHC_WTMK_LVL_RD_WML_MASK |
 			       ESDHC_WTMK_LVL_WR_WML_MASK);
 			m |= (wml << ESDHC_WTMK_LVL_RD_WML_SHIFT) |