]> Git Repo - J-u-boot.git/blobdiff - drivers/mmc/fsl_esdhc.c
mmc: fsl_esdhc: convert to CONFIG_FSL_ESDHC_VS33_NOT_SUPPORT
[J-u-boot.git] / drivers / mmc / fsl_esdhc.c
index f6e0d43057e1c67cd9798938a970ff269a91959b..1d98fa65c481af5caf44fed63265518a4db77e4b 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2007, 2010-2011 Freescale Semiconductor, Inc
- * Copyright 2019-2020 NXP
+ * Copyright 2019-2021 NXP
  * Andy Fleming
  *
  * Based vaguely on the pxa mmc code:
 #include <fsl_esdhc.h>
 #include <fdt_support.h>
 #include <asm/cache.h>
+#include <asm/global_data.h>
 #include <asm/io.h>
 #include <dm.h>
 #include <dm/device_compat.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <sdhci.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -51,8 +54,9 @@ struct fsl_esdhc {
        char    reserved1[8];   /* reserved */
        uint    fevt;           /* Force event register */
        uint    admaes;         /* ADMA error status register */
-       uint    adsaddr;        /* ADMA system address register */
-       char    reserved2[160];
+       uint    adsaddrl;       /* ADMA system address low register */
+       uint    adsaddrh;       /* ADMA system address high register */
+       char    reserved2[156];
        uint    hostver;        /* Host controller version register */
        char    reserved3[4];   /* reserved */
        uint    dmaerraddr;     /* DMA error address register */
@@ -60,7 +64,17 @@ struct fsl_esdhc {
        uint    dmaerrattr;     /* DMA error attribute register */
        char    reserved5[4];   /* reserved */
        uint    hostcapblt2;    /* Host controller capabilities register 2 */
-       char    reserved6[756]; /* reserved */
+       char    reserved6[8];   /* reserved */
+       uint    tbctl;          /* Tuning block control register */
+       char    reserved7[32];  /* reserved */
+       uint    sdclkctl;       /* SD clock control register */
+       uint    sdtimingctl;    /* SD timing control register */
+       char    reserved8[20];  /* reserved */
+       uint    dllcfg0;        /* DLL config 0 register */
+       uint    dllcfg1;        /* DLL config 1 register */
+       char    reserved9[8];   /* reserved */
+       uint    dllstat0;       /* DLL status 0 register */
+       char    reserved10[664];/* reserved */
        uint    esdhcctl;       /* eSDHC control register */
 };
 
@@ -91,6 +105,8 @@ struct fsl_esdhc_priv {
        struct mmc *mmc;
 #endif
        struct udevice *dev;
+       struct sdhci_adma_desc *adma_desc_table;
+       dma_addr_t dma_addr;
 };
 
 /* Return the XFERTYP flags for a given command and data packet */
@@ -100,15 +116,15 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
 
        if (data) {
                xfertyp |= XFERTYP_DPSEL;
-#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-               xfertyp |= XFERTYP_DMAEN;
-#endif
+               if (!IS_ENABLED(CONFIG_SYS_FSL_ESDHC_USE_PIO) &&
+                   cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK &&
+                   cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK_HS200)
+                       xfertyp |= XFERTYP_DMAEN;
                if (data->blocks > 1) {
                        xfertyp |= XFERTYP_MSBSEL;
                        xfertyp |= XFERTYP_BCEN;
-#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
-                       xfertyp |= XFERTYP_AC12EN;
-#endif
+                       if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_ESDHC111))
+                               xfertyp |= XFERTYP_AC12EN;
                }
 
                if (data->flags & MMC_DATA_READ)
@@ -132,7 +148,6 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data)
        return XFERTYP_CMD(cmd->cmdidx) | xfertyp;
 }
 
-#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
 /*
  * PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
  */
@@ -195,66 +210,83 @@ static void esdhc_pio_read_write(struct fsl_esdhc_priv *priv,
                }
        }
 }
-#endif
 
-static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
-                           struct mmc_data *data)
+static void esdhc_setup_watermark_level(struct fsl_esdhc_priv *priv,
+                                       struct mmc_data *data)
 {
-       int timeout;
        struct fsl_esdhc *regs = priv->esdhc_regs;
-#if defined(CONFIG_FSL_LAYERSCAPE)
-       dma_addr_t addr;
-#endif
-       uint wml_value;
-
-       wml_value = data->blocksize/4;
+       uint wml_value = data->blocksize / 4;
 
        if (data->flags & MMC_DATA_READ) {
                if (wml_value > WML_RD_WML_MAX)
                        wml_value = WML_RD_WML_MAX_VAL;
 
                esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
-#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-#if defined(CONFIG_FSL_LAYERSCAPE)
-               addr = virt_to_phys((void *)(data->dest));
-               if (upper_32_bits(addr))
-                       printf("Error found for upper 32 bits\n");
-               else
-                       esdhc_write32(&regs->dsaddr, lower_32_bits(addr));
-#else
-               esdhc_write32(&regs->dsaddr, (u32)data->dest);
-#endif
-#endif
        } else {
-#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-               flush_dcache_range((ulong)data->src,
-                                  (ulong)data->src+data->blocks
-                                        *data->blocksize);
-#endif
                if (wml_value > WML_WR_WML_MAX)
                        wml_value = WML_WR_WML_MAX_VAL;
 
-               if (!(esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL)) {
-                       printf("Can not write to locked SD card.\n");
-                       return -EINVAL;
-               }
-
                esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
-                                       wml_value << 16);
-#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-#if defined(CONFIG_FSL_LAYERSCAPE)
-               addr = virt_to_phys((void *)(data->src));
-               if (upper_32_bits(addr))
-                       printf("Error found for upper 32 bits\n");
-               else
-                       esdhc_write32(&regs->dsaddr, lower_32_bits(addr));
-#else
-               esdhc_write32(&regs->dsaddr, (u32)data->src);
-#endif
-#endif
+                                  wml_value << 16);
+       }
+}
+
+static void esdhc_setup_dma(struct fsl_esdhc_priv *priv, struct mmc_data *data)
+{
+       uint trans_bytes = data->blocksize * data->blocks;
+       struct fsl_esdhc *regs = priv->esdhc_regs;
+       phys_addr_t adma_addr;
+       void *buf;
+
+       if (data->flags & MMC_DATA_WRITE)
+               buf = (void *)data->src;
+       else
+               buf = data->dest;
+
+       priv->dma_addr = dma_map_single(buf, trans_bytes,
+                                       mmc_get_dma_dir(data));
+
+       if (IS_ENABLED(CONFIG_FSL_ESDHC_SUPPORT_ADMA2) &&
+           priv->adma_desc_table) {
+               debug("Using ADMA2\n");
+               /* prefer ADMA2 if it is available */
+               sdhci_prepare_adma_table(priv->adma_desc_table, data,
+                                        priv->dma_addr);
+
+               adma_addr = virt_to_phys(priv->adma_desc_table);
+               esdhc_write32(&regs->adsaddrl, lower_32_bits(adma_addr));
+               if (IS_ENABLED(CONFIG_DMA_ADDR_T_64BIT))
+                       esdhc_write32(&regs->adsaddrh, upper_32_bits(adma_addr));
+               esdhc_clrsetbits32(&regs->proctl, PROCTL_DMAS_MASK,
+                                  PROCTL_DMAS_ADMA2);
+       } else {
+               debug("Using SDMA\n");
+               if (upper_32_bits(priv->dma_addr))
+                       printf("Cannot use 64 bit addresses with SDMA\n");
+               esdhc_write32(&regs->dsaddr, lower_32_bits(priv->dma_addr));
+               esdhc_clrsetbits32(&regs->proctl, PROCTL_DMAS_MASK,
+                                  PROCTL_DMAS_SDMA);
        }
 
        esdhc_write32(&regs->blkattr, data->blocks << 16 | data->blocksize);
+}
+
+static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
+                           struct mmc_data *data)
+{
+       int timeout;
+       bool is_write = data->flags & MMC_DATA_WRITE;
+       struct fsl_esdhc *regs = priv->esdhc_regs;
+
+       if (is_write && !(esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL)) {
+               printf("Can not write to locked SD card.\n");
+               return -EINVAL;
+       }
+
+       if (IS_ENABLED(CONFIG_SYS_FSL_ESDHC_USE_PIO))
+               esdhc_setup_watermark_level(priv, data);
+       else
+               esdhc_setup_dma(priv, data);
 
        /* Calculate the timeout period for data transactions */
        /*
@@ -287,41 +319,18 @@ static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
        if (timeout < 0)
                timeout = 0;
 
-#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
-       if ((timeout == 4) || (timeout == 8) || (timeout == 12))
+       if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_ESDHC_A001) &&
+           (timeout == 4 || timeout == 8 || timeout == 12))
                timeout++;
-#endif
 
-#ifdef ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
-       timeout = 0xE;
-#endif
+       if (IS_ENABLED(ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE))
+               timeout = 0xE;
+
        esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, timeout << 16);
 
        return 0;
 }
 
-static void check_and_invalidate_dcache_range
-       (struct mmc_cmd *cmd,
-        struct mmc_data *data) {
-       unsigned start = 0;
-       unsigned end = 0;
-       unsigned size = roundup(ARCH_DMA_MINALIGN,
-                               data->blocks*data->blocksize);
-#if defined(CONFIG_FSL_LAYERSCAPE)
-       dma_addr_t addr;
-
-       addr = virt_to_phys((void *)(data->dest));
-       if (upper_32_bits(addr))
-               printf("Error found for upper 32 bits\n");
-       else
-               start = lower_32_bits(addr);
-#else
-       start = (unsigned)data->dest;
-#endif
-       end = start + size;
-       invalidate_dcache_range(start, end);
-}
-
 /*
  * Sends a command out on the bus.  Takes the mmc pointer,
  * a command pointer, and an optional data pointer.
@@ -336,10 +345,9 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
        struct fsl_esdhc *regs = priv->esdhc_regs;
        unsigned long start;
 
-#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
-       if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+       if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_ESDHC111) &&
+           cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
                return 0;
-#endif
 
        esdhc_write32(&regs->irqstat, -1);
 
@@ -365,9 +373,6 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
                err = esdhc_setup_data(priv, mmc, data);
                if(err)
                        return err;
-
-               if (data->flags & MMC_DATA_READ)
-                       check_and_invalidate_dcache_range(cmd, data);
        }
 
        /* Figure out the transfer arguments */
@@ -380,6 +385,10 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
        esdhc_write32(&regs->cmdarg, cmd->cmdarg);
        esdhc_write32(&regs->xfertyp, xfertyp);
 
+       if (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK ||
+           cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200)
+               flags = IRQSTAT_BRR;
+
        /* Wait for the command to complete */
        start = get_timer(0);
        while (!(esdhc_read32(&regs->irqstat) & flags)) {
@@ -436,32 +445,37 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
 
        /* Wait until all of the blocks are transferred */
        if (data) {
-#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
-               esdhc_pio_read_write(priv, data);
-#else
-               do {
-                       irqstat = esdhc_read32(&regs->irqstat);
-
-                       if (irqstat & IRQSTAT_DTOE) {
-                               err = -ETIMEDOUT;
-                               goto out;
-                       }
+               if (IS_ENABLED(CONFIG_SYS_FSL_ESDHC_USE_PIO)) {
+                       esdhc_pio_read_write(priv, data);
+               } else {
+                       flags = DATA_COMPLETE;
+                       if (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK ||
+                           cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200)
+                               flags = IRQSTAT_BRR;
+
+                       do {
+                               irqstat = esdhc_read32(&regs->irqstat);
 
-                       if (irqstat & DATA_ERR) {
-                               err = -ECOMM;
-                               goto out;
-                       }
-               } while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
+                               if (irqstat & IRQSTAT_DTOE) {
+                                       err = -ETIMEDOUT;
+                                       goto out;
+                               }
 
-               /*
-                * Need invalidate the dcache here again to avoid any
-                * cache-fill during the DMA operations such as the
-                * speculative pre-fetching etc.
-                */
-               if (data->flags & MMC_DATA_READ) {
-                       check_and_invalidate_dcache_range(cmd, data);
+                               if (irqstat & DATA_ERR) {
+                                       err = -ECOMM;
+                                       goto out;
+                               }
+                       } while ((irqstat & flags) != flags);
+
+                       /*
+                        * Need invalidate the dcache here again to avoid any
+                        * cache-fill during the DMA operations such as the
+                        * speculative pre-fetching etc.
+                        */
+                       dma_unmap_single(priv->dma_addr,
+                                        data->blocks * data->blocksize,
+                                        mmc_get_dma_dir(data));
                }
-#endif
        }
 
 out:
@@ -505,6 +519,27 @@ 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;
+
        pre_div >>= 1;
        div -= 1;
 
@@ -555,9 +590,107 @@ static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable)
        }
 }
 
+static void esdhc_flush_async_fifo(struct fsl_esdhc_priv *priv)
+{
+       struct fsl_esdhc *regs = priv->esdhc_regs;
+       u32 time_out;
+
+       esdhc_setbits32(&regs->esdhcctl, ESDHCCTL_FAF);
+
+       time_out = 20;
+       while (esdhc_read32(&regs->esdhcctl) & ESDHCCTL_FAF) {
+               if (time_out == 0) {
+                       printf("fsl_esdhc: Flush asynchronous FIFO timeout.\n");
+                       break;
+               }
+               time_out--;
+               mdelay(1);
+       }
+}
+
+static void esdhc_tuning_block_enable(struct fsl_esdhc_priv *priv,
+                                     bool en)
+{
+       struct fsl_esdhc *regs = priv->esdhc_regs;
+
+       esdhc_clock_control(priv, false);
+       esdhc_flush_async_fifo(priv);
+       if (en)
+               esdhc_setbits32(&regs->tbctl, TBCTL_TB_EN);
+       else
+               esdhc_clrbits32(&regs->tbctl, TBCTL_TB_EN);
+       esdhc_clock_control(priv, true);
+}
+
+static void esdhc_exit_hs400(struct fsl_esdhc_priv *priv)
+{
+       struct fsl_esdhc *regs = priv->esdhc_regs;
+
+       esdhc_clrbits32(&regs->sdtimingctl, FLW_CTL_BG);
+       esdhc_clrbits32(&regs->sdclkctl, CMD_CLK_CTL);
+
+       esdhc_clock_control(priv, false);
+       esdhc_clrbits32(&regs->tbctl, HS400_MODE);
+       esdhc_clock_control(priv, true);
+
+       esdhc_clrbits32(&regs->dllcfg0, DLL_FREQ_SEL | DLL_ENABLE);
+       esdhc_clrbits32(&regs->tbctl, HS400_WNDW_ADJUST);
+
+       esdhc_tuning_block_enable(priv, false);
+}
+
+static int esdhc_set_timing(struct fsl_esdhc_priv *priv, enum bus_mode mode)
+{
+       struct fsl_esdhc *regs = priv->esdhc_regs;
+       ulong start;
+       u32 val;
+
+       /* Exit HS400 mode before setting any other mode */
+       if (esdhc_read32(&regs->tbctl) & HS400_MODE &&
+           mode != MMC_HS_400)
+               esdhc_exit_hs400(priv);
+
+       esdhc_clock_control(priv, false);
+
+       if (mode == MMC_HS_200)
+               esdhc_clrsetbits32(&regs->autoc12err, UHSM_MASK,
+                                  UHSM_SDR104_HS200);
+       if (mode == MMC_HS_400) {
+               esdhc_setbits32(&regs->tbctl, HS400_MODE);
+               esdhc_setbits32(&regs->sdclkctl, CMD_CLK_CTL);
+               esdhc_clock_control(priv, true);
+
+               if (priv->clock == 200000000)
+                       esdhc_setbits32(&regs->dllcfg0, DLL_FREQ_SEL);
+
+               esdhc_setbits32(&regs->dllcfg0, DLL_ENABLE);
+
+               esdhc_setbits32(&regs->dllcfg0, DLL_RESET);
+               udelay(1);
+               esdhc_clrbits32(&regs->dllcfg0, DLL_RESET);
+
+               start = get_timer(0);
+               val = DLL_STS_SLV_LOCK;
+               while (!(esdhc_read32(&regs->dllstat0) & val)) {
+                       if (get_timer(start) > 1000) {
+                               printf("fsl_esdhc: delay chain lock timeout\n");
+                               return -ETIMEDOUT;
+                       }
+               }
+
+               esdhc_setbits32(&regs->tbctl, HS400_WNDW_ADJUST);
+
+               esdhc_clock_control(priv, false);
+               esdhc_flush_async_fifo(priv);
+       }
+       esdhc_clock_control(priv, true);
+       return 0;
+}
+
 static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
 {
        struct fsl_esdhc *regs = priv->esdhc_regs;
+       int ret;
 
        if (priv->is_sdhc_per_clk) {
                /* Select to use peripheral clock */
@@ -566,10 +699,18 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
                esdhc_clock_control(priv, true);
        }
 
+       if (mmc->selected_mode == MMC_HS_400)
+               esdhc_tuning_block_enable(priv, true);
+
        /* Set the clock speed */
        if (priv->clock != mmc->clock)
                set_sysctl(priv, mmc, mmc->clock);
 
+       /* Set timing */
+       ret = esdhc_set_timing(priv, mmc->selected_mode);
+       if (ret)
+               return ret;
+
        /* Set the bus width */
        esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
 
@@ -608,12 +749,15 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
                        return -ETIMEDOUT;
        }
 
+       /* Clean TBCTL[TB_EN] which is not able to be reset by reset all */
+       esdhc_clrbits32(&regs->tbctl, TBCTL_TB_EN);
+
        esdhc_enable_cache_snooping(regs);
 
        esdhc_setbits32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
 
        /* Set the initial clock speed */
-       mmc_set_clock(mmc, 400000, MMC_CLK_ENABLE);
+       set_sysctl(priv, mmc, 400000);
 
        /* Disable the BRR and BWR bits in IRQSTAT */
        esdhc_clrbits32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
@@ -624,6 +768,9 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
        /* Set timout to the maximum value */
        esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
 
+       if (IS_ENABLED(CONFIG_SYS_FSL_ESDHC_UNRELIABLE_PULSE_DETECTION_WORKAROUND))
+               esdhc_clrbits32(&regs->dllcfg1, DLL_PD_PULSE_STRETCH_SEL);
+
        return 0;
 }
 
@@ -648,12 +795,21 @@ static void fsl_esdhc_get_cfg_common(struct fsl_esdhc_priv *priv,
        u32 caps;
 
        caps = esdhc_read32(&regs->hostcapblt);
-#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC135
-       caps &= ~(HOSTCAPBLT_SRS | HOSTCAPBLT_VS18 | HOSTCAPBLT_VS30);
-#endif
-#ifdef CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33
+
+       /*
+        * For eSDHC, power supply is through peripheral circuit. Some eSDHC
+        * versions have value 0 of the bit but that does not reflect the
+        * truth. 3.3V is common for SD/MMC, and is supported for all boards
+        * with eSDHC in current u-boot. So, make 3.3V is supported in
+        * default in code. CONFIG_FSL_ESDHC_VS33_NOT_SUPPORT can be enabled
+        * if future board does not support 3.3V.
+        */
        caps |= HOSTCAPBLT_VS33;
-#endif
+       if (IS_ENABLED(CONFIG_FSL_ESDHC_VS33_NOT_SUPPORT))
+               caps &= ~HOSTCAPBLT_VS33;
+
+       if (IS_ENABLED(CONFIG_SYS_FSL_ERRATUM_ESDHC135))
+               caps &= ~(HOSTCAPBLT_SRS | HOSTCAPBLT_VS18 | HOSTCAPBLT_VS30);
        if (caps & HOSTCAPBLT_VS18)
                cfg->voltages |= MMC_VDD_165_195;
        if (caps & HOSTCAPBLT_VS30)
@@ -671,61 +827,21 @@ static void fsl_esdhc_get_cfg_common(struct fsl_esdhc_priv *priv,
        cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 }
 
-#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
-void mmc_adapter_card_type_ident(void)
-{
-       u8 card_id;
-       u8 value;
-
-       card_id = QIXIS_READ(present) & QIXIS_SDID_MASK;
-       gd->arch.sdhc_adapter = card_id;
-
-       switch (card_id) {
-       case QIXIS_ESDHC_ADAPTER_TYPE_EMMC45:
-               value = QIXIS_READ(brdcfg[5]);
-               value |= (QIXIS_DAT4 | QIXIS_DAT5_6_7);
-               QIXIS_WRITE(brdcfg[5], value);
-               break;
-       case QIXIS_ESDHC_ADAPTER_TYPE_SDMMC_LEGACY:
-               value = QIXIS_READ(pwr_ctl[1]);
-               value |= QIXIS_EVDD_BY_SDHC_VS;
-               QIXIS_WRITE(pwr_ctl[1], value);
-               break;
-       case QIXIS_ESDHC_ADAPTER_TYPE_EMMC44:
-               value = QIXIS_READ(brdcfg[5]);
-               value |= (QIXIS_SDCLKIN | QIXIS_SDCLKOUT);
-               QIXIS_WRITE(brdcfg[5], value);
-               break;
-       case QIXIS_ESDHC_ADAPTER_TYPE_RSV:
-               break;
-       case QIXIS_ESDHC_ADAPTER_TYPE_MMC:
-               break;
-       case QIXIS_ESDHC_ADAPTER_TYPE_SD:
-               break;
-       case QIXIS_ESDHC_NO_ADAPTER:
-               break;
-       default:
-               break;
-       }
-}
-#endif
-
 #ifdef CONFIG_OF_LIBFDT
 __weak int esdhc_status_fixup(void *blob, const char *compat)
 {
-#ifdef CONFIG_FSL_ESDHC_PIN_MUX
-       if (!hwconfig("esdhc")) {
+       if (IS_ENABLED(CONFIG_FSL_ESDHC_PIN_MUX) && !hwconfig("esdhc")) {
                do_fixup_by_compat(blob, compat, "status", "disabled",
                                sizeof("disabled"), 1);
                return 1;
        }
-#endif
+
        return 0;
 }
 
-#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
-static int fsl_esdhc_get_cd(struct udevice *dev);
 
+#if CONFIG_IS_ENABLED(DM_MMC)
+static int fsl_esdhc_get_cd(struct udevice *dev);
 static void esdhc_disable_for_no_card(void *blob)
 {
        struct udevice *dev;
@@ -744,6 +860,10 @@ static void esdhc_disable_for_no_card(void *blob)
                                 sizeof("disabled"), 1);
        }
 }
+#else
+static void esdhc_disable_for_no_card(void *blob)
+{
+}
 #endif
 
 void fdt_fixup_esdhc(void *blob, struct bd_info *bd)
@@ -752,9 +872,10 @@ void fdt_fixup_esdhc(void *blob, struct bd_info *bd)
 
        if (esdhc_status_fixup(blob, compat))
                return;
-#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
-       esdhc_disable_for_no_card(blob);
-#endif
+
+       if (IS_ENABLED(CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND))
+               esdhc_disable_for_no_card(blob);
+
        do_fixup_by_compat_u32(blob, compat, "clock-frequency",
                               gd->arch.sdhc_clk, 1);
 }
@@ -836,10 +957,9 @@ int fsl_esdhc_initialize(struct bd_info *bis, struct fsl_esdhc_cfg *cfg)
                printf("No max bus width provided. Assume 8-bit supported.\n");
        }
 
-#ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK
-       if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK)
+       if (IS_ENABLED(CONFIG_ESDHC_DETECT_8_BIT_QUIRK))
                mmc_cfg->host_caps &= ~MMC_MODE_8BIT;
-#endif
+
        mmc_cfg->ops = &esdhc_ops;
 
        fsl_esdhc_get_cfg_common(priv, mmc_cfg);
@@ -869,8 +989,9 @@ int fsl_esdhc_mmc_init(struct bd_info *bis)
 static int fsl_esdhc_probe(struct udevice *dev)
 {
        struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
-       struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
+       struct fsl_esdhc_plat *plat = dev_get_plat(dev);
        struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+       u32 caps, hostver;
        fdt_addr_t addr;
        struct mmc *mmc;
        int ret;
@@ -885,6 +1006,21 @@ static int fsl_esdhc_probe(struct udevice *dev)
 #endif
        priv->dev = dev;
 
+       if (IS_ENABLED(CONFIG_FSL_ESDHC_SUPPORT_ADMA2)) {
+               /*
+                * Only newer eSDHC controllers can do ADMA2 if the ADMA flag
+                * is set in the host capabilities register.
+                */
+               caps = esdhc_read32(&priv->esdhc_regs->hostcapblt);
+               hostver = esdhc_read32(&priv->esdhc_regs->hostver);
+               if (caps & HOSTCAPBLT_DMAS &&
+                   HOSTVER_VENDOR(hostver) > VENDOR_V_22) {
+                       priv->adma_desc_table = sdhci_adma_init();
+                       if (!priv->adma_desc_table)
+                               debug("Could not allocate ADMA tables, falling back to SDMA\n");
+               }
+       }
+
        if (gd->arch.sdhc_per_clk) {
                priv->sdhc_clk = gd->arch.sdhc_per_clk;
                priv->is_sdhc_per_clk = true;
@@ -911,16 +1047,16 @@ static int fsl_esdhc_probe(struct udevice *dev)
        if (ret)
                return ret;
 
-#ifdef CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND
-       if (!fsl_esdhc_get_cd(dev))
+       if (IS_ENABLED(CONFIG_FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND) &&
+           !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)
 {
-       struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
+       struct fsl_esdhc_plat *plat = dev_get_plat(dev);
        struct fsl_esdhc_priv *priv = dev_get_priv(dev);
 
        if (plat->cfg.host_caps & MMC_CAP_NONREMOVABLE)
@@ -932,7 +1068,7 @@ static int fsl_esdhc_get_cd(struct udevice *dev)
 static int fsl_esdhc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
                              struct mmc_data *data)
 {
-       struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
+       struct fsl_esdhc_plat *plat = dev_get_plat(dev);
        struct fsl_esdhc_priv *priv = dev_get_priv(dev);
 
        return esdhc_send_cmd_common(priv, &plat->mmc, cmd, data);
@@ -940,12 +1076,75 @@ static int fsl_esdhc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
 
 static int fsl_esdhc_set_ios(struct udevice *dev)
 {
-       struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
+       struct fsl_esdhc_plat *plat = dev_get_plat(dev);
        struct fsl_esdhc_priv *priv = dev_get_priv(dev);
 
        return esdhc_set_ios_common(priv, &plat->mmc);
 }
 
+static int fsl_esdhc_reinit(struct udevice *dev)
+{
+       struct fsl_esdhc_plat *plat = dev_get_plat(dev);
+       struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+
+       return esdhc_init_common(priv, &plat->mmc);
+}
+
+#ifdef MMC_SUPPORTS_TUNING
+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(&regs->autoc12err, EXECUTE_TUNING);
+
+       irqstaten = esdhc_read32(&regs->irqstaten);
+       esdhc_write32(&regs->irqstaten, IRQSTATEN_BRR);
+
+       for (i = 0; i < MAX_TUNING_LOOP; i++) {
+               mmc_send_tuning(mmc, opcode, NULL);
+               mdelay(1);
+
+               val = esdhc_read32(&regs->autoc12err);
+               if (!(val & EXECUTE_TUNING)) {
+                       if (val & SMPCLKSEL)
+                               break;
+               }
+       }
+
+       esdhc_write32(&regs->irqstaten, irqstaten);
+
+       if (i != MAX_TUNING_LOOP) {
+               if (plat->mmc.hs400_tuning)
+                       esdhc_setbits32(&regs->sdtimingctl, FLW_CTL_BG);
+               return 0;
+       }
+
+       printf("fsl_esdhc: tuning failed!\n");
+       esdhc_clrbits32(&regs->autoc12err, SMPCLKSEL);
+       esdhc_clrbits32(&regs->autoc12err, EXECUTE_TUNING);
+       esdhc_tuning_block_enable(priv, false);
+       return -ETIMEDOUT;
+}
+#endif
+
+int fsl_esdhc_hs400_prepare_ddr(struct udevice *dev)
+{
+       struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+
+       esdhc_tuning_block_enable(priv, false);
+       return 0;
+}
+
 static const struct dm_mmc_ops fsl_esdhc_ops = {
        .get_cd         = fsl_esdhc_get_cd,
        .send_cmd       = fsl_esdhc_send_cmd,
@@ -953,6 +1152,8 @@ static const struct dm_mmc_ops fsl_esdhc_ops = {
 #ifdef MMC_SUPPORTS_TUNING
        .execute_tuning = fsl_esdhc_execute_tuning,
 #endif
+       .reinit = fsl_esdhc_reinit,
+       .hs400_prepare_ddr = fsl_esdhc_hs400_prepare_ddr,
 };
 
 static const struct udevice_id fsl_esdhc_ids[] = {
@@ -962,7 +1163,7 @@ static const struct udevice_id fsl_esdhc_ids[] = {
 
 static int fsl_esdhc_bind(struct udevice *dev)
 {
-       struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
+       struct fsl_esdhc_plat *plat = dev_get_plat(dev);
 
        return mmc_bind(dev, &plat->mmc, &plat->cfg);
 }
@@ -974,7 +1175,7 @@ U_BOOT_DRIVER(fsl_esdhc) = {
        .ops    = &fsl_esdhc_ops,
        .bind   = fsl_esdhc_bind,
        .probe  = fsl_esdhc_probe,
-       .platdata_auto_alloc_size = sizeof(struct fsl_esdhc_plat),
-       .priv_auto_alloc_size = sizeof(struct fsl_esdhc_priv),
+       .plat_auto      = sizeof(struct fsl_esdhc_plat),
+       .priv_auto      = sizeof(struct fsl_esdhc_priv),
 };
 #endif
This page took 0.05356 seconds and 4 git commands to generate.