These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / mmc / host / sdhci-esdhc-imx.c
index 82f512d..1f1582f 100644 (file)
@@ -4,7 +4,7 @@
  * derived from the OF-version.
  *
  * Copyright (c) 2010 Pengutronix e.K.
- *   Author: Wolfram Sang <w.sang@pengutronix.de>
+ *   Author: Wolfram Sang <kernel@pengutronix.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@
 #include "sdhci-esdhc.h"
 
 #define        ESDHC_CTRL_D3CD                 0x08
+#define ESDHC_BURST_LEN_EN_INCR                (1 << 27)
 /* VENDOR SPEC register */
 #define ESDHC_VENDOR_SPEC              0xc0
 #define  ESDHC_VENDOR_SPEC_SDIO_QUIRK  (1 << 1)
@@ -44,6 +45,7 @@
 #define  ESDHC_MIX_CTRL_EXE_TUNE       (1 << 22)
 #define  ESDHC_MIX_CTRL_SMPCLK_SEL     (1 << 23)
 #define  ESDHC_MIX_CTRL_FBCLK_SEL      (1 << 25)
+#define  ESDHC_MIX_CTRL_HS400_EN       (1 << 26)
 /* Bits 3 and 6 are not SDHCI standard definitions */
 #define  ESDHC_MIX_CTRL_SDHCI_MASK     0xb7
 /* Tuning bits */
 #define  ESDHC_TUNE_CTRL_MIN           0
 #define  ESDHC_TUNE_CTRL_MAX           ((1 << 7) - 1)
 
+/* strobe dll register */
+#define ESDHC_STROBE_DLL_CTRL          0x70
+#define ESDHC_STROBE_DLL_CTRL_ENABLE   (1 << 0)
+#define ESDHC_STROBE_DLL_CTRL_RESET    (1 << 1)
+#define ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT     3
+
+#define ESDHC_STROBE_DLL_STATUS                0x74
+#define ESDHC_STROBE_DLL_STS_REF_LOCK  (1 << 1)
+#define ESDHC_STROBE_DLL_STS_SLV_LOCK  0x1
+
 #define ESDHC_TUNING_CTRL              0xcc
 #define ESDHC_STD_TUNING_EN            (1 << 24)
 /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
 #define ESDHC_TUNING_START_TAP         0x1
+#define ESDHC_TUNING_STEP_SHIFT                16
 
 /* pinctrl state */
 #define ESDHC_PINCTRL_STATE_100MHZ     "state_100mhz"
 #define ESDHC_FLAG_STD_TUNING          BIT(5)
 /* The IP has SDHCI_CAPABILITIES_1 register */
 #define ESDHC_FLAG_HAVE_CAP1           BIT(6)
+/*
+ * The IP has errata ERR004536
+ * uSDHC: ADMA Length Mismatch Error occurs if the AHB read access is slow,
+ * when reading data from the card
+ */
+#define ESDHC_FLAG_ERR004536           BIT(7)
+/* The IP supports HS200 mode */
+#define ESDHC_FLAG_HS200               BIT(8)
+/* The IP supports HS400 mode */
+#define ESDHC_FLAG_HS400               BIT(9)
+
+/* A higher clock ferquency than this rate requires strobell dll control */
+#define ESDHC_STROBE_DLL_CLK_FREQ      100000000
 
 struct esdhc_soc_data {
        u32 flags;
@@ -139,7 +165,19 @@ static struct esdhc_soc_data usdhc_imx6q_data = {
 
 static struct esdhc_soc_data usdhc_imx6sl_data = {
        .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
-                       | ESDHC_FLAG_HAVE_CAP1,
+                       | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_ERR004536
+                       | ESDHC_FLAG_HS200,
+};
+
+static struct esdhc_soc_data usdhc_imx6sx_data = {
+       .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+                       | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200,
+};
+
+static struct esdhc_soc_data usdhc_imx7d_data = {
+       .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+                       | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
+                       | ESDHC_FLAG_HS400,
 };
 
 struct pltfm_imx_data {
@@ -161,7 +199,7 @@ struct pltfm_imx_data {
        u32 is_ddr;
 };
 
-static struct platform_device_id imx_esdhc_devtype[] = {
+static const struct platform_device_id imx_esdhc_devtype[] = {
        {
                .name = "sdhci-esdhc-imx25",
                .driver_data = (kernel_ulong_t) &esdhc_imx25_data,
@@ -182,8 +220,10 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
        { .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, },
        { .compatible = "fsl,imx51-esdhc", .data = &esdhc_imx51_data, },
        { .compatible = "fsl,imx53-esdhc", .data = &esdhc_imx53_data, },
+       { .compatible = "fsl,imx6sx-usdhc", .data = &usdhc_imx6sx_data, },
        { .compatible = "fsl,imx6sl-usdhc", .data = &usdhc_imx6sl_data, },
        { .compatible = "fsl,imx6q-usdhc", .data = &usdhc_imx6q_data, },
+       { .compatible = "fsl,imx7d-usdhc", .data = &usdhc_imx7d_data, },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, imx_esdhc_dt_ids);
@@ -259,6 +299,9 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
                                val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104
                                        | SDHCI_SUPPORT_SDR50
                                        | SDHCI_USE_SDR50_TUNING;
+
+                       if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
+                               val |= SDHCI_SUPPORT_HS400;
                }
        }
 
@@ -298,7 +341,7 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
        u32 data;
 
        if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) {
-               if (val & SDHCI_INT_CARD_INT) {
+               if ((val & SDHCI_INT_CARD_INT) && !esdhc_is_usdhc(imx_data)) {
                        /*
                         * Clear and then set D3CD bit to avoid missing the
                         * card interrupt.  This is a eSDHC controller problem
@@ -313,6 +356,11 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
                        data |= ESDHC_CTRL_D3CD;
                        writel(data, host->ioaddr + SDHCI_HOST_CONTROL);
                }
+
+               if (val & SDHCI_INT_ADMA_ERROR) {
+                       val &= ~SDHCI_INT_ADMA_ERROR;
+                       val |= ESDHC_INT_VENDOR_SPEC_DMA_ERR;
+               }
        }
 
        if (unlikely((imx_data->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
@@ -333,13 +381,6 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
                        }
        }
 
-       if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) {
-               if (val & SDHCI_INT_ADMA_ERROR) {
-                       val &= ~SDHCI_INT_ADMA_ERROR;
-                       val |= ESDHC_INT_VENDOR_SPEC_DMA_ERR;
-               }
-       }
-
        writel(val, host->ioaddr + reg);
 }
 
@@ -435,6 +476,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
                } else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
                        u32 v = readl(host->ioaddr + SDHCI_ACMD12_ERR);
                        u32 m = readl(host->ioaddr + ESDHC_MIX_CTRL);
+                       u32 tuning_ctrl;
                        if (val & SDHCI_CTRL_TUNED_CLK) {
                                v |= ESDHC_MIX_CTRL_SMPCLK_SEL;
                        } else {
@@ -445,6 +487,11 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
                        if (val & SDHCI_CTRL_EXEC_TUNING) {
                                v |= ESDHC_MIX_CTRL_EXE_TUNE;
                                m |= ESDHC_MIX_CTRL_FBCLK_SEL;
+                               tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
+                               tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP;
+                               if (imx_data->boarddata.tuning_step)
+                                       tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
+                                       writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
                        } else {
                                v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
                        }
@@ -568,13 +615,8 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
 static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
 {
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-       struct pltfm_imx_data *imx_data = pltfm_host->priv;
-       struct esdhc_platform_data *boarddata = &imx_data->boarddata;
 
-       if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock))
-               return boarddata->f_max;
-       else
-               return pltfm_host->clock;
+       return pltfm_host->clock;
 }
 
 static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
@@ -717,7 +759,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
        min = ESDHC_TUNE_CTRL_MIN;
        while (min < ESDHC_TUNE_CTRL_MAX) {
                esdhc_prepare_tuning(host, min);
-               if (!mmc_send_tuning(host->mmc))
+               if (!mmc_send_tuning(host->mmc, opcode, NULL))
                        break;
                min += ESDHC_TUNE_CTRL_STEP;
        }
@@ -726,7 +768,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
        max = min + ESDHC_TUNE_CTRL_STEP;
        while (max < ESDHC_TUNE_CTRL_MAX) {
                esdhc_prepare_tuning(host, max);
-               if (mmc_send_tuning(host->mmc)) {
+               if (mmc_send_tuning(host->mmc, opcode, NULL)) {
                        max -= ESDHC_TUNE_CTRL_STEP;
                        break;
                }
@@ -736,7 +778,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)
        /* use average delay to get the best timing */
        avg = (min + max) / 2;
        esdhc_prepare_tuning(host, avg);
-       ret = mmc_send_tuning(host->mmc);
+       ret = mmc_send_tuning(host->mmc, opcode, NULL);
        esdhc_post_tuning(host);
 
        dev_dbg(mmc_dev(host->mmc), "tunning %s at 0x%x ret %d\n",
@@ -766,6 +808,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
                break;
        case MMC_TIMING_UHS_SDR104:
        case MMC_TIMING_MMC_HS200:
+       case MMC_TIMING_MMC_HS400:
                pinctrl = imx_data->pins_200mhz;
                break;
        default:
@@ -776,24 +819,68 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
        return pinctrl_select_state(imx_data->pinctrl, pinctrl);
 }
 
+/*
+ * For HS400 eMMC, there is a data_strobe line, this signal is generated
+ * by the device and used for data output and CRC status response output
+ * in HS400 mode. The frequency of this signal follows the frequency of
+ * CLK generated by host. Host receive the data which is aligned to the
+ * edge of data_strobe line. Due to the time delay between CLK line and
+ * data_strobe line, if the delay time is larger than one clock cycle,
+ * then CLK and data_strobe line will misaligned, read error shows up.
+ * So when the CLK is higher than 100MHz, each clock cycle is short enough,
+ * host should config the delay target.
+ */
+static void esdhc_set_strobe_dll(struct sdhci_host *host)
+{
+       u32 v;
+
+       if (host->mmc->actual_clock > ESDHC_STROBE_DLL_CLK_FREQ) {
+               /* force a reset on strobe dll */
+               writel(ESDHC_STROBE_DLL_CTRL_RESET,
+                       host->ioaddr + ESDHC_STROBE_DLL_CTRL);
+               /*
+                * enable strobe dll ctrl and adjust the delay target
+                * for the uSDHC loopback read clock
+                */
+               v = ESDHC_STROBE_DLL_CTRL_ENABLE |
+                       (7 << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT);
+               writel(v, host->ioaddr + ESDHC_STROBE_DLL_CTRL);
+               /* wait 1us to make sure strobe dll status register stable */
+               udelay(1);
+               v = readl(host->ioaddr + ESDHC_STROBE_DLL_STATUS);
+               if (!(v & ESDHC_STROBE_DLL_STS_REF_LOCK))
+                       dev_warn(mmc_dev(host->mmc),
+                               "warning! HS400 strobe DLL status REF not lock!\n");
+               if (!(v & ESDHC_STROBE_DLL_STS_SLV_LOCK))
+                       dev_warn(mmc_dev(host->mmc),
+                               "warning! HS400 strobe DLL status SLV not lock!\n");
+       }
+}
+
 static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
 {
+       u32 m;
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct pltfm_imx_data *imx_data = pltfm_host->priv;
        struct esdhc_platform_data *boarddata = &imx_data->boarddata;
 
+       /* disable ddr mode and disable HS400 mode */
+       m = readl(host->ioaddr + ESDHC_MIX_CTRL);
+       m &= ~(ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN);
+       imx_data->is_ddr = 0;
+
        switch (timing) {
        case MMC_TIMING_UHS_SDR12:
        case MMC_TIMING_UHS_SDR25:
        case MMC_TIMING_UHS_SDR50:
        case MMC_TIMING_UHS_SDR104:
        case MMC_TIMING_MMC_HS200:
+               writel(m, host->ioaddr + ESDHC_MIX_CTRL);
                break;
        case MMC_TIMING_UHS_DDR50:
        case MMC_TIMING_MMC_DDR52:
-               writel(readl(host->ioaddr + ESDHC_MIX_CTRL) |
-                               ESDHC_MIX_CTRL_DDREN,
-                               host->ioaddr + ESDHC_MIX_CTRL);
+               m |= ESDHC_MIX_CTRL_DDREN;
+               writel(m, host->ioaddr + ESDHC_MIX_CTRL);
                imx_data->is_ddr = 1;
                if (boarddata->delay_line) {
                        u32 v;
@@ -805,6 +892,12 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
                        writel(v, host->ioaddr + ESDHC_DLL_CTRL);
                }
                break;
+       case MMC_TIMING_MMC_HS400:
+               m |= ESDHC_MIX_CTRL_DDREN | ESDHC_MIX_CTRL_HS400_EN;
+               writel(m, host->ioaddr + ESDHC_MIX_CTRL);
+               imx_data->is_ddr = 1;
+               esdhc_set_strobe_dll(host);
+               break;
        }
 
        esdhc_change_pinstate(host, timing);
@@ -865,33 +958,20 @@ static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
 static int
 sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
                         struct sdhci_host *host,
-                        struct esdhc_platform_data *boarddata)
+                        struct pltfm_imx_data *imx_data)
 {
        struct device_node *np = pdev->dev.of_node;
-
-       if (!np)
-               return -ENODEV;
-
-       if (of_get_property(np, "non-removable", NULL))
-               boarddata->cd_type = ESDHC_CD_PERMANENT;
-
-       if (of_get_property(np, "fsl,cd-controller", NULL))
-               boarddata->cd_type = ESDHC_CD_CONTROLLER;
+       struct esdhc_platform_data *boarddata = &imx_data->boarddata;
+       int ret;
 
        if (of_get_property(np, "fsl,wp-controller", NULL))
                boarddata->wp_type = ESDHC_WP_CONTROLLER;
 
-       boarddata->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
-       if (gpio_is_valid(boarddata->cd_gpio))
-               boarddata->cd_type = ESDHC_CD_GPIO;
-
        boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
        if (gpio_is_valid(boarddata->wp_gpio))
                boarddata->wp_type = ESDHC_WP_GPIO;
 
-       of_property_read_u32(np, "bus-width", &boarddata->max_bus_width);
-
-       of_property_read_u32(np, "max-frequency", &boarddata->f_max);
+       of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step);
 
        if (of_find_property(np, "no-1-8-v", NULL))
                boarddata->support_vsel = false;
@@ -903,25 +983,117 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
 
        mmc_of_parse_voltage(np, &host->ocr_mask);
 
+       /* sdr50 and sdr104 needs work on 1.8v signal voltage */
+       if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) &&
+           !IS_ERR(imx_data->pins_default)) {
+               imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl,
+                                               ESDHC_PINCTRL_STATE_100MHZ);
+               imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl,
+                                               ESDHC_PINCTRL_STATE_200MHZ);
+               if (IS_ERR(imx_data->pins_100mhz) ||
+                               IS_ERR(imx_data->pins_200mhz)) {
+                       dev_warn(mmc_dev(host->mmc),
+                               "could not get ultra high speed state, work on normal mode\n");
+                       /*
+                        * fall back to not support uhs by specify no 1.8v quirk
+                        */
+                       host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+               }
+       } else {
+               host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+       }
+
+       /* call to generic mmc_of_parse to support additional capabilities */
+       ret = mmc_of_parse(host->mmc);
+       if (ret)
+               return ret;
+
+       if (!IS_ERR_VALUE(mmc_gpio_get_cd(host->mmc)))
+               host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+
        return 0;
 }
 #else
 static inline int
 sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
                         struct sdhci_host *host,
-                        struct esdhc_platform_data *boarddata)
+                        struct pltfm_imx_data *imx_data)
 {
        return -ENODEV;
 }
 #endif
 
+static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev,
+                        struct sdhci_host *host,
+                        struct pltfm_imx_data *imx_data)
+{
+       struct esdhc_platform_data *boarddata = &imx_data->boarddata;
+       int err;
+
+       if (!host->mmc->parent->platform_data) {
+               dev_err(mmc_dev(host->mmc), "no board data!\n");
+               return -EINVAL;
+       }
+
+       imx_data->boarddata = *((struct esdhc_platform_data *)
+                               host->mmc->parent->platform_data);
+       /* write_protect */
+       if (boarddata->wp_type == ESDHC_WP_GPIO) {
+               err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio);
+               if (err) {
+                       dev_err(mmc_dev(host->mmc),
+                               "failed to request write-protect gpio!\n");
+                       return err;
+               }
+               host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
+       }
+
+       /* card_detect */
+       switch (boarddata->cd_type) {
+       case ESDHC_CD_GPIO:
+               err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0);
+               if (err) {
+                       dev_err(mmc_dev(host->mmc),
+                               "failed to request card-detect gpio!\n");
+                       return err;
+               }
+               /* fall through */
+
+       case ESDHC_CD_CONTROLLER:
+               /* we have a working card_detect back */
+               host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+               break;
+
+       case ESDHC_CD_PERMANENT:
+               host->mmc->caps |= MMC_CAP_NONREMOVABLE;
+               break;
+
+       case ESDHC_CD_NONE:
+               break;
+       }
+
+       switch (boarddata->max_bus_width) {
+       case 8:
+               host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA;
+               break;
+       case 4:
+               host->mmc->caps |= MMC_CAP_4_BIT_DATA;
+               break;
+       case 1:
+       default:
+               host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
+               break;
+       }
+
+       return 0;
+}
+
 static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 {
        const struct of_device_id *of_id =
                        of_match_device(imx_esdhc_dt_ids, &pdev->dev);
        struct sdhci_pltfm_host *pltfm_host;
        struct sdhci_host *host;
-       struct esdhc_platform_data *boarddata;
        int err;
        struct pltfm_imx_data *imx_data;
 
@@ -988,9 +1160,35 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
         * to something insane.  Change it back here.
         */
        if (esdhc_is_usdhc(imx_data)) {
-               writel(0x08100810, host->ioaddr + ESDHC_WTMK_LVL);
+               writel(0x10401040, host->ioaddr + ESDHC_WTMK_LVL);
+
                host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
                host->mmc->caps |= MMC_CAP_1_8V_DDR;
+
+               /*
+                * ROM code will change the bit burst_length_enable setting
+                * to zero if this usdhc is choosed to boot system. Change
+                * it back here, otherwise it will impact the performance a
+                * lot. This bit is used to enable/disable the burst length
+                * for the external AHB2AXI bridge, it's usefully especially
+                * for INCR transfer because without burst length indicator,
+                * the AHB2AXI bridge does not know the burst length in
+                * advance. And without burst length indicator, AHB INCR
+                * transfer can only be converted to singles on the AXI side.
+                */
+               writel(readl(host->ioaddr + SDHCI_HOST_CONTROL)
+                       | ESDHC_BURST_LEN_EN_INCR,
+                       host->ioaddr + SDHCI_HOST_CONTROL);
+
+               if (!(imx_data->socdata->flags & ESDHC_FLAG_HS200))
+                       host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
+
+               /*
+               * errata ESDHC_FLAG_ERR004536 fix for MX6Q TO1.2 and MX6DL
+               * TO1.1, it's harmless for MX6SL
+               */
+               writel(readl(host->ioaddr + 0x6c) | BIT(7),
+                       host->ioaddr + 0x6c);
        }
 
        if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
@@ -1002,54 +1200,16 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
                        ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP,
                        host->ioaddr + ESDHC_TUNING_CTRL);
 
-       boarddata = &imx_data->boarddata;
-       if (sdhci_esdhc_imx_probe_dt(pdev, host, boarddata) < 0) {
-               if (!host->mmc->parent->platform_data) {
-                       dev_err(mmc_dev(host->mmc), "no board data!\n");
-                       err = -EINVAL;
-                       goto disable_clk;
-               }
-               imx_data->boarddata = *((struct esdhc_platform_data *)
-                                       host->mmc->parent->platform_data);
-       }
-
-       /* card_detect */
-       if (boarddata->cd_type == ESDHC_CD_CONTROLLER)
-               host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
-
-       switch (boarddata->max_bus_width) {
-       case 8:
-               host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA;
-               break;
-       case 4:
-               host->mmc->caps |= MMC_CAP_4_BIT_DATA;
-               break;
-       case 1:
-       default:
-               host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
-               break;
-       }
+       if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
+               host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
 
-       /* sdr50 and sdr104 needs work on 1.8v signal voltage */
-       if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) &&
-           !IS_ERR(imx_data->pins_default)) {
-               imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl,
-                                               ESDHC_PINCTRL_STATE_100MHZ);
-               imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl,
-                                               ESDHC_PINCTRL_STATE_200MHZ);
-               if (IS_ERR(imx_data->pins_100mhz) ||
-                               IS_ERR(imx_data->pins_200mhz)) {
-                       dev_warn(mmc_dev(host->mmc),
-                               "could not get ultra high speed state, work on normal mode\n");
-                       /* fall back to not support uhs by specify no 1.8v quirk */
-                       host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
-               }
-       } else {
-               host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
-       }
+       if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
+               host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400;
 
-       /* call to generic mmc_of_parse to support additional capabilities */
-       err = mmc_of_parse(host->mmc);
+       if (of_id)
+               err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
+       else
+               err = sdhci_esdhc_imx_probe_nondt(pdev, host, imx_data);
        if (err)
                goto disable_clk;
 
@@ -1151,5 +1311,5 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
 module_platform_driver(sdhci_esdhc_imx_driver);
 
 MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");
-MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
 MODULE_LICENSE("GPL v2");