From: Michael Walle Date: Wed, 17 Mar 2021 14:01:36 +0000 (+0100) Subject: mmc: fsl_esdhc: add workaround for erratum A-011334 X-Git-Url: http://git.dujemihanovic.xyz/img/sics.gif?a=commitdiff_plain;h=bd7b8505f2c0c87785488a040ff7d2711465b401;p=u-boot.git 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 --- diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig index ae0b7b21e8..c0190a233e 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig @@ -47,6 +47,7 @@ config ARCH_LS1028A select SYS_FSL_ERRATUM_A009663 if !TFABOOT select SYS_FSL_ERRATUM_A009942 if !TFABOOT select SYS_FSL_ERRATUM_A050382 + select SYS_FSL_ERRATUM_A011334 select RESV_RAM if GIC_V3_ITS imply PANIC_HANG diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c34fce370e..b0ff92b5fa 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 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);