diff options
author | Michael Walle <michael@walle.cc> | 2021-03-17 17:01:36 +0300 |
---|---|---|
committer | Peng Fan <peng.fan@nxp.com> | 2021-04-06 13:35:55 +0300 |
commit | bd7b8505f2c0c87785488a040ff7d2711465b401 (patch) | |
tree | 18339f5edd994fa13dee06a4b2bc2aa50ad97209 /drivers/mmc/fsl_esdhc.c | |
parent | e9978b17cd7bc19f0459b2829756f1d891382bf9 (diff) | |
download | u-boot-bd7b8505f2c0c87785488a040ff7d2711465b401.tar.xz |
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/mmc/fsl_esdhc.c')
-rw-r--r-- | drivers/mmc/fsl_esdhc.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 6014e1c5ca..09ea1a9de9 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); |