mmc: fsl_esdhc: workaround for hardware 3.3v IO reliability issue

When eSDHC operates at 3.3v, damage can accumulate in an internal
level shifter at a higher than expected rate. The faster the interface
runs, the more damage accumulates. This issue now is found on LX2160A
eSDHC1 for only SD card.

The hardware workaround is recommended to use an on-board level shifter
that is 1.8v on SoC side and 3.3v on SD card side.

For boards without hardware workaround, this option could be enabled,
ensuring 1.8v IO voltage and disabling eSDHC if no card.
This option assumes no hotplug, and u-boot has to make all the way to
to linux to use 1.8v UHS-I speed mode if has card.
If you do not want the workaround for better user experience, of course
you can choose to not select it running eSDHC in unsafe mode.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Acked-by: Peng Fan <peng.fan@nxp.com>
This commit is contained in:
Yangbo Lu 2020-05-19 11:06:44 +08:00 committed by Peng Fan
parent 9abf648436
commit c927d65873
3 changed files with 53 additions and 2 deletions

View File

@ -727,6 +727,21 @@ config FSL_ESDHC
This selects support for the eSDHC (Enhanced Secure Digital Host
Controller) found on numerous Freescale/NXP SoCs.
config FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
bool "enable eSDHC workaround for 3.3v IO reliability issue"
depends on FSL_ESDHC && DM_MMC
default n
help
When eSDHC operates at 3.3v, damage can accumulate in an internal
level shifter at a higher than expected rate. The faster the interface
runs, the more damage accumulates. This issue now is found on LX2160A
eSDHC1 for only SD card. The hardware workaround is recommended to use
an on-board level shifter that is 1.8v on SoC side and 3.3v on SD card
side. For boards without hardware workaround, this option could be
enabled, ensuring 1.8v IO voltage and disabling eSDHC if no card.
This option assumes no hotplug, and u-boot has to make all the way to
to linux to use 1.8v UHS-I speed mode if has card.
config FSL_ESDHC_IMX
bool "Freescale/NXP i.MX eSDHC controller support"
help

View File

@ -723,13 +723,38 @@ __weak int esdhc_status_fixup(void *blob, const char *compat)
return 0;
}
#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
static int fsl_esdhc_get_cd(struct udevice *dev);
static void esdhc_disable_for_no_card(void *blob)
{
struct udevice *dev;
for (uclass_first_device(UCLASS_MMC, &dev);
dev;
uclass_next_device(&dev)) {
char esdhc_path[50];
if (fsl_esdhc_get_cd(dev))
continue;
snprintf(esdhc_path, sizeof(esdhc_path), "/soc/esdhc@%lx",
(unsigned long)dev_read_addr(dev));
do_fixup_by_path(blob, esdhc_path, "status", "disabled",
sizeof("disabled"), 1);
}
}
#endif
void fdt_fixup_esdhc(void *blob, bd_t *bd)
{
const char *compat = "fsl,esdhc";
if (esdhc_status_fixup(blob, compat))
return;
#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
esdhc_disable_for_no_card(blob);
#endif
do_fixup_by_compat_u32(blob, compat, "clock-frequency",
gd->arch.sdhc_clk, 1);
}
@ -848,6 +873,7 @@ static int fsl_esdhc_probe(struct udevice *dev)
struct fsl_esdhc_priv *priv = dev_get_priv(dev);
fdt_addr_t addr;
struct mmc *mmc;
int ret;
addr = dev_read_addr(dev);
if (addr == FDT_ADDR_T_NONE)
@ -881,7 +907,15 @@ static int fsl_esdhc_probe(struct udevice *dev)
upriv->mmc = mmc;
return esdhc_init_common(priv, mmc);
ret = esdhc_init_common(priv, mmc);
if (ret)
return ret;
#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
if (!fsl_esdhc_get_cd(dev))
esdhc_setbits32(&priv->esdhc_regs->proctl, PROCTL_VOLT_SEL);
#endif
return 0;
}
static int fsl_esdhc_get_cd(struct udevice *dev)

View File

@ -4,6 +4,7 @@
*-------------------------------------------------------------------
*
* Copyright 2007-2008,2010-2011 Freescale Semiconductor, Inc
* Copyright 2020 NXP
*/
#ifndef __FSL_ESDHC_H__
@ -98,6 +99,7 @@
#define PROCTL_DTW_4 0x00000002
#define PROCTL_DTW_8 0x00000004
#define PROCTL_D3CD 0x00000008
#define PROCTL_VOLT_SEL 0x00000400
#define CMDARG 0x0002e008