From: Haibo Chen <haibo.chen@xxxxxxx> USDHC hardware auto tuning circuit support check 1/4/8 data lines and cmd line. Out of reset uSDHC, it default select check 4 data lines and do not check cmd line. This is incorrect if we use 8 data lines. So need to config the auto tuning mode according to current bus width. Signed-off-by: Haibo Chen <haibo.chen@xxxxxxx> --- drivers/mmc/host/sdhci-esdhc-imx.c | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index a49fac719fca..f18d169bc8ff 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -94,6 +94,11 @@ #define ESDHC_VEND_SPEC2 0xc8 #define ESDHC_VEND_SPEC2_EN_BUSY_IRQ (1 << 8) +#define ESDHC_VEND_SPEC2_AUTO_TUNE_8BIT_EN (1 << 4) +#define ESDHC_VEND_SPEC2_AUTO_TUNE_4BIT_EN (0 << 4) +#define ESDHC_VEND_SPEC2_AUTO_TUNE_1BIT_EN (2 << 4) +#define ESDHC_VEND_SPEC2_AUTO_TUNE_CMD_EN (1 << 6) +#define ESDHC_VEND_SPEC2_AUTO_TUNE_MODE_MASK (7 << 4) #define ESDHC_TUNING_CTRL 0xcc #define ESDHC_STD_TUNING_EN (1 << 24) @@ -114,6 +119,7 @@ #define ESDHC_CTRL_4BITBUS (0x1 << 1) #define ESDHC_CTRL_8BITBUS (0x2 << 1) #define ESDHC_CTRL_BUSWIDTH_MASK (0x3 << 1) +#define USDHC_GET_BUSWIDTH(c) (c & ESDHC_CTRL_BUSWIDTH_MASK) /* * There is an INT DMA ERR mismatch between eSDHC and STD SDHC SPEC: @@ -407,6 +413,30 @@ static inline void esdhc_wait_for_card_clock_gate_off(struct sdhci_host *host) dev_warn(mmc_dev(host->mmc), "%s: card clock still not gate off in 100us!.\n", __func__); } +/* Enable the auto tuning circuit to check the CMD line and BUS line */ +static inline void usdhc_auto_tuning_mode_sel(struct sdhci_host *host) +{ + u32 buswidth, auto_tune_buswidth; + + buswidth = USDHC_GET_BUSWIDTH(readl(host->ioaddr + SDHCI_HOST_CONTROL)); + + switch (buswidth) { + case ESDHC_CTRL_8BITBUS: + auto_tune_buswidth = ESDHC_VEND_SPEC2_AUTO_TUNE_8BIT_EN; + break; + case ESDHC_CTRL_4BITBUS: + auto_tune_buswidth = ESDHC_VEND_SPEC2_AUTO_TUNE_4BIT_EN; + break; + default: /* 1BITBUS */ + auto_tune_buswidth = ESDHC_VEND_SPEC2_AUTO_TUNE_1BIT_EN; + break; + } + + esdhc_clrset_le(host, ESDHC_VEND_SPEC2_AUTO_TUNE_MODE_MASK, + auto_tune_buswidth | ESDHC_VEND_SPEC2_AUTO_TUNE_CMD_EN, + ESDHC_VEND_SPEC2); +} + static u32 esdhc_readl_le(struct sdhci_host *host, int reg) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -643,6 +673,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) v |= ESDHC_MIX_CTRL_EXE_TUNE; m |= ESDHC_MIX_CTRL_FBCLK_SEL; m |= ESDHC_MIX_CTRL_AUTO_TUNE_EN; + usdhc_auto_tuning_mode_sel(host); } else { v &= ~ESDHC_MIX_CTRL_EXE_TUNE; } @@ -1012,6 +1043,8 @@ static void esdhc_post_tuning(struct sdhci_host *host) { u32 reg; + usdhc_auto_tuning_mode_sel(host); + reg = readl(host->ioaddr + ESDHC_MIX_CTRL); reg &= ~ESDHC_MIX_CTRL_EXE_TUNE; reg |= ESDHC_MIX_CTRL_AUTO_TUNE_EN; -- 2.17.1