diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-esdhc-imx.c')
| -rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 33 | 
1 files changed, 31 insertions, 2 deletions
| diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index f18d169bc8ff..afaf33707d46 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -196,6 +196,9 @@   */  #define ESDHC_FLAG_BROKEN_AUTO_CMD23	BIT(16) +/* ERR004536 is not applicable for the IP  */ +#define ESDHC_FLAG_SKIP_ERR004536	BIT(17) +  enum wp_types {  	ESDHC_WP_NONE,		/* no WP, neither controller nor gpio */  	ESDHC_WP_CONTROLLER,	/* mmc controller internal WP */ @@ -289,6 +292,13 @@ static const struct esdhc_soc_data usdhc_imx7d_data = {  			| ESDHC_FLAG_BROKEN_AUTO_CMD23,  }; +static struct esdhc_soc_data usdhc_s32g2_data = { +	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_MAN_TUNING +			| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 +			| ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES +			| ESDHC_FLAG_SKIP_ERR004536, +}; +  static struct esdhc_soc_data usdhc_imx7ulp_data = {  	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING  			| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200 @@ -347,6 +357,7 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {  	{ .compatible = "fsl,imx7ulp-usdhc", .data = &usdhc_imx7ulp_data, },  	{ .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, },  	{ .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx8mm_data, }, +	{ .compatible = "nxp,s32g2-usdhc", .data = &usdhc_s32g2_data, },  	{ /* sentinel */ }  };  MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids); @@ -1187,6 +1198,7 @@ static void esdhc_reset_tuning(struct sdhci_host *host)  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);  	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);  	u32 ctrl; +	int ret;  	/* Reset the tuning circuit */  	if (esdhc_is_usdhc(imx_data)) { @@ -1199,7 +1211,22 @@ static void esdhc_reset_tuning(struct sdhci_host *host)  		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {  			ctrl = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS);  			ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL; +			ctrl &= ~ESDHC_MIX_CTRL_EXE_TUNE;  			writel(ctrl, host->ioaddr + SDHCI_AUTO_CMD_STATUS); +			/* Make sure ESDHC_MIX_CTRL_EXE_TUNE cleared */ +			ret = readl_poll_timeout(host->ioaddr + SDHCI_AUTO_CMD_STATUS, +				ctrl, !(ctrl & ESDHC_MIX_CTRL_EXE_TUNE), 1, 50); +			if (ret == -ETIMEDOUT) +				dev_warn(mmc_dev(host->mmc), +				 "Warning! clear execute tuning bit failed\n"); +			/* +			 * SDHCI_INT_DATA_AVAIL is W1C bit, set this bit will clear the +			 * usdhc IP internal logic flag execute_tuning_with_clr_buf, which +			 * will finally make sure the normal data transfer logic correct. +			 */ +			ctrl = readl(host->ioaddr + SDHCI_INT_STATUS); +			ctrl |= SDHCI_INT_DATA_AVAIL; +			writel(ctrl, host->ioaddr + SDHCI_INT_STATUS);  		}  	}  } @@ -1359,8 +1386,10 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host)  		 * erratum ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL  		 * TO1.1, it's harmless for MX6SL  		 */ -		writel(readl(host->ioaddr + 0x6c) & ~BIT(7), -			host->ioaddr + 0x6c); +		if (!(imx_data->socdata->flags & ESDHC_FLAG_SKIP_ERR004536)) { +			writel(readl(host->ioaddr + 0x6c) & ~BIT(7), +				host->ioaddr + 0x6c); +		}  		/* disable DLL_CTRL delay line settings */  		writel(0x0, host->ioaddr + ESDHC_DLL_CTRL); |