diff options
author | Michael Walle | 2021-03-17 15:01:36 +0100 |
---|---|---|
committer | Peng Fan | 2021-04-06 18:35:55 +0800 |
commit | bd7b8505f2c0c87785488a040ff7d2711465b401 (patch) | |
tree | 18339f5edd994fa13dee06a4b2bc2aa50ad97209 /drivers | |
parent | e9978b17cd7bc19f0459b2829756f1d891382bf9 (diff) |
mmc: fsl_esdhc: add workaround for erratum A-011334
LS1028A SoCs are restricted in what divider values are allowed for HS400
mode. This is basically a port from the corresponding linux driver.
Signed-off-by: Michael Walle <michael@walle.cc>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/Kconfig | 3 | ||||
-rw-r--r-- | drivers/mmc/fsl_esdhc.c | 25 |
2 files changed, 27 insertions, 1 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c34fce370e5..b0ff92b5fa1 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -813,3 +813,6 @@ config SYS_FSL_ERRATUM_ESDHC135 config SYS_FSL_ERRATUM_ESDHC_A001 bool + +config SYS_FSL_ERRATUM_A011334 + bool diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 6014e1c5cac..09ea1a9de91 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -518,6 +518,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; @@ -1063,9 +1081,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(®s->autoc12err, EXECUTE_TUNING); @@ -1073,7 +1096,7 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) esdhc_write32(®s->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(®s->autoc12err); |