summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/Kconfig6
-rw-r--r--drivers/mmc/fsl_esdhc.c31
-rw-r--r--drivers/mmc/mmc-uclass.c12
-rw-r--r--drivers/mmc/mmc.c8
4 files changed, 45 insertions, 12 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c34fce370e..492567575e 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -813,3 +813,9 @@ config SYS_FSL_ERRATUM_ESDHC135
config SYS_FSL_ERRATUM_ESDHC_A001
bool
+
+config SYS_FSL_ERRATUM_A011334
+ bool
+
+config SYS_FSL_ESDHC_UNRELIABLE_PULSE_DETECTION_WORKAROUND
+ bool
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 6014e1c5ca..7501fdb71e 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -71,7 +71,8 @@ struct fsl_esdhc {
uint sdtimingctl; /* SD timing control register */
char reserved8[20]; /* reserved */
uint dllcfg0; /* DLL config 0 register */
- char reserved9[12]; /* reserved */
+ uint dllcfg1; /* DLL config 1 register */
+ char reserved9[8]; /* reserved */
uint dllstat0; /* DLL status 0 register */
char reserved10[664];/* reserved */
uint esdhcctl; /* eSDHC control register */
@@ -518,6 +519,24 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
while (sdhc_clk / (div * pre_div) > clock && div < 16)
div++;
+ if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_A011334) &&
+ clock == 200000000 && mmc->selected_mode == MMC_HS_400) {
+ u32 div_ratio = pre_div * div;
+
+ if (div_ratio <= 4) {
+ pre_div = 4;
+ div = 1;
+ } else if (div_ratio <= 8) {
+ pre_div = 4;
+ div = 2;
+ } else if (div_ratio <= 12) {
+ pre_div = 4;
+ div = 3;
+ } else {
+ printf("unsupported clock division.\n");
+ }
+ }
+
mmc->clock = sdhc_clk / pre_div / div;
priv->clock = mmc->clock;
@@ -749,6 +768,9 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
/* Set timout to the maximum value */
esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
+ if (IS_ENABLED(CONFIG_SYS_FSL_ESDHC_UNRELIABLE_PULSE_DETECTION_WORKAROUND))
+ esdhc_clrbits32(&regs->dllcfg1, DLL_PD_PULSE_STRETCH_SEL);
+
return 0;
}
@@ -1063,9 +1085,14 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
struct fsl_esdhc_plat *plat = dev_get_plat(dev);
struct fsl_esdhc_priv *priv = dev_get_priv(dev);
struct fsl_esdhc *regs = priv->esdhc_regs;
+ struct mmc *mmc = &plat->mmc;
u32 val, irqstaten;
int i;
+ if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_A011334) &&
+ plat->mmc.hs400_tuning)
+ set_sysctl(priv, mmc, mmc->clock);
+
esdhc_tuning_block_enable(priv, true);
esdhc_setbits32(&regs->autoc12err, EXECUTE_TUNING);
@@ -1073,7 +1100,7 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
esdhc_write32(&regs->irqstaten, IRQSTATEN_BRR);
for (i = 0; i < MAX_TUNING_LOOP; i++) {
- mmc_send_tuning(&plat->mmc, opcode, NULL);
+ mmc_send_tuning(mmc, opcode, NULL);
mdelay(1);
val = esdhc_read32(&regs->autoc12err);
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 53eabc9e61..d36aae367e 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -383,18 +383,16 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
{
struct blk_desc *bdesc;
struct udevice *bdev;
- int ret, devnum = -1;
+ int ret;
if (!mmc_get_ops(dev))
return -ENOSYS;
-#ifndef CONFIG_SPL_BUILD
- /* Use the fixed index with aliase node's index */
- ret = dev_read_alias_seq(dev, &devnum);
- debug("%s: alias ret=%d, devnum=%d\n", __func__, ret, devnum);
-#endif
+
+ /* Use the fixed index with aliases node's index */
+ debug("%s: alias devnum=%d\n", __func__, dev_seq(dev));
ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC,
- devnum, 512, 0, &bdev);
+ dev_seq(dev), 512, 0, &bdev);
if (ret) {
debug("Cannot create block device\n");
return ret;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index b4c8e7f293..1e83007286 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -3052,9 +3052,11 @@ int mmc_init_device(int num)
struct mmc *m;
int ret;
- ret = uclass_get_device(UCLASS_MMC, num, &dev);
- if (ret)
- return ret;
+ if (uclass_get_device_by_seq(UCLASS_MMC, num, &dev)) {
+ ret = uclass_get_device(UCLASS_MMC, num, &dev);
+ if (ret)
+ return ret;
+ }
m = mmc_get_mmc_dev(dev);
if (!m)