mmc: fsl_esdhc: workaround for hardware 3.3v IO reliability issue
authorYangbo Lu <yangbo.lu@nxp.com>
Tue, 19 May 2020 03:06:44 +0000 (11:06 +0800)
committerPeng Fan <peng.fan@nxp.com>
Mon, 15 Jun 2020 01:45:22 +0000 (09:45 +0800)
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>
drivers/mmc/Kconfig
drivers/mmc/fsl_esdhc.c
include/fsl_esdhc.h

index 3c4f057373fce6d4f89c9809c5012f55bd7d7fb9..8f56572c39a00c46be9861bfbfab23124f2157f0 100644 (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
index 704407981beb016598ee36b98e9fde8052310216..a4b923ab99f2d1719596aa9d5badb01d3457eb8f 100644 (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)
index 8e8cd2cc1a555ef124c21b6778020e1c32ebd19b..e148eaa880477f0fc73794ad5ee26cdb477f6d4c 100644 (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