summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/Kconfig11
-rw-r--r--drivers/mmc/fsl_esdhc.c41
-rw-r--r--drivers/mmc/fsl_esdhc_imx.c40
-rw-r--r--drivers/mmc/mmc.c17
4 files changed, 39 insertions, 70 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 2bc19dd56b..2f0eedc22f 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -79,7 +79,7 @@ config MMC_QUIRKS
help
Some cards and hosts may sometimes behave unexpectedly (quirks).
This option enable workarounds to handle those quirks. Some of them
- are enabled by default, other may require additionnal flags or are
+ are enabled by default, other may require additional flags or are
enabled by the host driver.
config MMC_HW_PARTITIONING
@@ -711,19 +711,10 @@ endif
config FSL_ESDHC
bool "Freescale/NXP eSDHC controller support"
- select FSL_ESDHC_USE_PERIPHERAL_CLK if MMC_HS200_SUPPORT || MMC_UHS_SUPPORT
help
This selects support for the eSDHC (Enhanced Secure Digital Host
Controller) found on numerous Freescale/NXP SoCs.
-config FSL_ESDHC_USE_PERIPHERAL_CLK
- bool "enable ESDHC peripheral clock support"
- depends on FSL_ESDHC
- help
- eSDHC supports two reference clocks (platform clock and peripheral clock).
- Peripheral clock which could provide higher clock frequency is required to
- be used for tuning of SD UHS mode and eMMC HS200/HS400 modes.
-
config FSL_ESDHC_IMX
bool "Freescale/NXP i.MX eSDHC controller support"
help
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 1e7d606cd8..112f115015 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -81,6 +81,7 @@ struct fsl_esdhc_plat {
struct fsl_esdhc_priv {
struct fsl_esdhc *esdhc_regs;
unsigned int sdhc_clk;
+ bool is_sdhc_per_clk;
unsigned int clock;
#if !CONFIG_IS_ENABLED(DM_MMC)
struct mmc *mmc;
@@ -523,7 +524,6 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
}
-#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable)
{
struct fsl_esdhc *regs = priv->esdhc_regs;
@@ -550,18 +550,18 @@ static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable)
mdelay(1);
}
}
-#endif
static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
{
struct fsl_esdhc *regs = priv->esdhc_regs;
-#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
- /* Select to use peripheral clock */
- esdhc_clock_control(priv, false);
- esdhc_setbits32(&regs->esdhcctl, ESDHCCTL_PCS);
- esdhc_clock_control(priv, true);
-#endif
+ if (priv->is_sdhc_per_clk) {
+ /* Select to use peripheral clock */
+ esdhc_clock_control(priv, false);
+ esdhc_setbits32(&regs->esdhcctl, ESDHCCTL_PCS);
+ esdhc_clock_control(priv, true);
+ }
+
/* Set the clock speed */
if (priv->clock != mmc->clock)
set_sysctl(priv, mmc, mmc->clock);
@@ -716,17 +716,8 @@ void fdt_fixup_esdhc(void *blob, bd_t *bd)
if (esdhc_status_fixup(blob, compat))
return;
-#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
- do_fixup_by_compat_u32(blob, compat, "peripheral-frequency",
- gd->arch.sdhc_clk, 1);
-#else
do_fixup_by_compat_u32(blob, compat, "clock-frequency",
gd->arch.sdhc_clk, 1);
-#endif
-#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
- do_fixup_by_compat_u32(blob, compat, "adapter-type",
- (u32)(gd->arch.sdhc_adapter), 1);
-#endif
}
#endif
@@ -788,6 +779,8 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
priv->esdhc_regs = (struct fsl_esdhc *)(unsigned long)(cfg->esdhc_base);
priv->sdhc_clk = cfg->sdhc_clk;
+ if (gd->arch.sdhc_per_clk)
+ priv->is_sdhc_per_clk = true;
mmc_cfg = &plat->cfg;
@@ -826,7 +819,11 @@ int fsl_esdhc_mmc_init(bd_t *bis)
cfg = calloc(sizeof(struct fsl_esdhc_cfg), 1);
cfg->esdhc_base = CONFIG_SYS_FSL_ESDHC_ADDR;
- cfg->sdhc_clk = gd->arch.sdhc_clk;
+ /* Prefer peripheral clock which provides higher frequency. */
+ if (gd->arch.sdhc_per_clk)
+ cfg->sdhc_clk = gd->arch.sdhc_per_clk;
+ else
+ cfg->sdhc_clk = gd->arch.sdhc_clk;
return fsl_esdhc_initialize(bis, cfg);
}
#else /* DM_MMC */
@@ -848,7 +845,13 @@ static int fsl_esdhc_probe(struct udevice *dev)
#endif
priv->dev = dev;
- priv->sdhc_clk = gd->arch.sdhc_clk;
+ if (gd->arch.sdhc_per_clk) {
+ priv->sdhc_clk = gd->arch.sdhc_per_clk;
+ priv->is_sdhc_per_clk = true;
+ } else {
+ priv->sdhc_clk = gd->arch.sdhc_clk;
+ }
+
if (priv->sdhc_clk <= 0) {
dev_err(dev, "Unable to get clk for %s\n", dev->name);
return -EINVAL;
diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c
index 96fe01e26d..462ad2878a 100644
--- a/drivers/mmc/fsl_esdhc_imx.c
+++ b/drivers/mmc/fsl_esdhc_imx.c
@@ -661,35 +661,6 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
priv->clock = clock;
}
-#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
-static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable)
-{
- struct fsl_esdhc *regs = priv->esdhc_regs;
- u32 value;
- u32 time_out;
-
- value = esdhc_read32(&regs->sysctl);
-
- if (enable)
- value |= SYSCTL_CKEN;
- else
- value &= ~SYSCTL_CKEN;
-
- esdhc_write32(&regs->sysctl, value);
-
- time_out = 20;
- value = PRSSTAT_SDSTB;
- while (!(esdhc_read32(&regs->prsstat) & value)) {
- if (time_out == 0) {
- printf("fsl_esdhc: Internal clock never stabilised.\n");
- break;
- }
- time_out--;
- mdelay(1);
- }
-}
-#endif
-
#ifdef MMC_SUPPORTS_TUNING
static int esdhc_change_pinstate(struct udevice *dev)
{
@@ -961,12 +932,6 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
int ret __maybe_unused;
u32 clock;
-#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
- /* Select to use peripheral clock */
- esdhc_clock_control(priv, false);
- esdhc_setbits32(&regs->scr, ESDHCCTL_PCS);
- esdhc_clock_control(priv, true);
-#endif
/* Set the clock speed */
clock = mmc->clock;
if (clock < mmc->cfg->f_min)
@@ -1394,13 +1359,8 @@ void fdt_fixup_esdhc(void *blob, bd_t *bd)
if (esdhc_status_fixup(blob, compat))
return;
-#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
- do_fixup_by_compat_u32(blob, compat, "peripheral-frequency",
- gd->arch.sdhc_clk, 1);
-#else
do_fixup_by_compat_u32(blob, compat, "clock-frequency",
gd->arch.sdhc_clk, 1);
-#endif
}
#endif
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index f683b52ead..d43983d4a6 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1444,6 +1444,20 @@ static int sd_read_ssr(struct mmc *mmc)
cmd.cmdarg = mmc->rca << 16;
err = mmc_send_cmd(mmc, &cmd, NULL);
+#ifdef CONFIG_MMC_QUIRKS
+ if (err && (mmc->quirks & MMC_QUIRK_RETRY_APP_CMD)) {
+ int retries = 4;
+ /*
+ * It has been seen that APP_CMD may fail on the first
+ * attempt, let's try a few more times
+ */
+ do {
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (!err)
+ break;
+ } while (retries--);
+ }
+#endif
if (err)
return err;
@@ -2755,7 +2769,8 @@ int mmc_get_op_cond(struct mmc *mmc)
#ifdef CONFIG_MMC_QUIRKS
mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN |
- MMC_QUIRK_RETRY_SEND_CID;
+ MMC_QUIRK_RETRY_SEND_CID |
+ MMC_QUIRK_RETRY_APP_CMD;
#endif
err = mmc_power_cycle(mmc);