]> git.sur5r.net Git - u-boot/blobdiff - drivers/mmc/fsl_esdhc.c
mmc: fsl_esdhc: drop CONFIG_SYS_FSL_ESDHC_FORCE_VSELECT
[u-boot] / drivers / mmc / fsl_esdhc.c
index f3c63585a8e13a8b1e1aa3502658de31e3783c89..3abd2d30aff89cb821645e5d79884f2cb0f85202 100644 (file)
@@ -16,6 +16,7 @@
 #include <hwconfig.h>
 #include <mmc.h>
 #include <part.h>
+#include <power/regulator.h>
 #include <malloc.h>
 #include <fsl_esdhc.h>
 #include <fdt_support.h>
@@ -92,6 +93,7 @@ struct fsl_esdhc {
  * @dev: pointer for the device
  * @non_removable: 0: removable; 1: non-removable
  * @wp_enable: 1: enable checking wp; 0: no check
+ * @vs18_enable: 1: use 1.8V voltage; 0: use 3.3V
  * @cd_gpio: gpio for card detection
  * @wp_gpio: gpio for write protection
  */
@@ -104,6 +106,7 @@ struct fsl_esdhc_priv {
        struct udevice *dev;
        int non_removable;
        int wp_enable;
+       int vs18_enable;
 #ifdef CONFIG_DM_GPIO
        struct gpio_desc cd_gpio;
        struct gpio_desc wp_gpio;
@@ -521,7 +524,13 @@ out:
 
 static void set_sysctl(struct mmc *mmc, uint clock)
 {
-       int div, pre_div;
+       int div = 1;
+#ifdef ARCH_MXC
+       int pre_div = 1;
+#else
+       int pre_div = 2;
+#endif
+       int ddr_pre_div = mmc->ddr_mode ? 2 : 1;
        struct fsl_esdhc_priv *priv = mmc->priv;
        struct fsl_esdhc *regs = priv->esdhc_regs;
        int sdhc_clk = priv->sdhc_clk;
@@ -530,18 +539,13 @@ static void set_sysctl(struct mmc *mmc, uint clock)
        if (clock < mmc->cfg->f_min)
                clock = mmc->cfg->f_min;
 
-       if (sdhc_clk / 16 > clock) {
-               for (pre_div = 2; pre_div < 256; pre_div *= 2)
-                       if ((sdhc_clk / pre_div) <= (clock * 16))
-                               break;
-       } else
-               pre_div = 2;
+       while (sdhc_clk / (16 * pre_div * ddr_pre_div) > clock && pre_div < 256)
+               pre_div *= 2;
 
-       for (div = 1; div <= 16; div++)
-               if ((sdhc_clk / (div * pre_div)) <= clock)
-                       break;
+       while (sdhc_clk / (div * pre_div * ddr_pre_div) > clock && div < 16)
+               div++;
 
-       pre_div >>= mmc->ddr_mode ? 2 : 1;
+       pre_div >>= 1;
        div -= 1;
 
        clk = (pre_div << 8) | (div << 4);
@@ -669,9 +673,8 @@ static int esdhc_init(struct mmc *mmc)
        /* Set timout to the maximum value */
        esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
 
-#ifdef CONFIG_SYS_FSL_ESDHC_FORCE_VSELECT
-       esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
-#endif
+       if (priv->vs18_enable)
+               esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
 
        return 0;
 }
@@ -723,20 +726,6 @@ static const struct mmc_ops esdhc_ops = {
        .getcd          = esdhc_getcd,
 };
 
-static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg,
-                                struct fsl_esdhc_priv *priv)
-{
-       if (!cfg || !priv)
-               return -EINVAL;
-
-       priv->esdhc_regs = (struct fsl_esdhc *)(unsigned long)(cfg->esdhc_base);
-       priv->bus_width = cfg->max_bus_width;
-       priv->sdhc_clk = cfg->sdhc_clk;
-       priv->wp_enable  = cfg->wp_enable;
-
-       return 0;
-};
-
 static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
 {
        struct fsl_esdhc *regs;
@@ -759,6 +748,9 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
                        VENDORSPEC_HCKEN | VENDORSPEC_IPGEN | VENDORSPEC_CKEN);
 #endif
 
+       if (priv->vs18_enable)
+               esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
+
        writel(SDHCI_IRQ_EN_BITS, &regs->irqstaten);
        memset(&priv->cfg, 0, sizeof(priv->cfg));
 
@@ -833,6 +825,22 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv)
        return 0;
 }
 
+#ifndef CONFIG_DM_MMC
+static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg,
+                                struct fsl_esdhc_priv *priv)
+{
+       if (!cfg || !priv)
+               return -EINVAL;
+
+       priv->esdhc_regs = (struct fsl_esdhc *)(unsigned long)(cfg->esdhc_base);
+       priv->bus_width = cfg->max_bus_width;
+       priv->sdhc_clk = cfg->sdhc_clk;
+       priv->wp_enable  = cfg->wp_enable;
+       priv->vs18_enable  = cfg->vs18_enable;
+
+       return 0;
+};
+
 int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg)
 {
        struct fsl_esdhc_priv *priv;
@@ -871,6 +879,7 @@ int fsl_esdhc_mmc_init(bd_t *bis)
        cfg->sdhc_clk = gd->arch.sdhc_clk;
        return fsl_esdhc_initialize(bis, cfg);
 }
+#endif
 
 #ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT
 void mmc_adapter_card_type_ident(void)
@@ -959,11 +968,12 @@ static int fsl_esdhc_probe(struct udevice *dev)
        struct fsl_esdhc_priv *priv = dev_get_priv(dev);
        const void *fdt = gd->fdt_blob;
        int node = dev_of_offset(dev);
+       struct udevice *vqmmc_dev;
        fdt_addr_t addr;
        unsigned int val;
        int ret;
 
-       addr = dev_get_addr(dev);
+       addr = devfdt_get_addr(dev);
        if (addr == FDT_ADDR_T_NONE)
                return -EINVAL;
 
@@ -983,19 +993,42 @@ static int fsl_esdhc_probe(struct udevice *dev)
         } else {
                priv->non_removable = 0;
 #ifdef CONFIG_DM_GPIO
-               gpio_request_by_name_nodev(fdt, node, "cd-gpios", 0,
-                                          &priv->cd_gpio, GPIOD_IS_IN);
+               gpio_request_by_name_nodev(offset_to_ofnode(node), "cd-gpios",
+                                          0, &priv->cd_gpio, GPIOD_IS_IN);
 #endif
        }
 
        priv->wp_enable = 1;
 
 #ifdef CONFIG_DM_GPIO
-       ret = gpio_request_by_name_nodev(fdt, node, "wp-gpios", 0,
+       ret = gpio_request_by_name_nodev(offset_to_ofnode(node), "wp-gpios", 0,
                                         &priv->wp_gpio, GPIOD_IS_IN);
        if (ret)
                priv->wp_enable = 0;
 #endif
+
+       priv->vs18_enable = 0;
+
+#ifdef CONFIG_DM_REGULATOR
+       /*
+        * If emmc I/O has a fixed voltage at 1.8V, this must be provided,
+        * otherwise, emmc will work abnormally.
+        */
+       ret = device_get_supply_regulator(dev, "vqmmc-supply", &vqmmc_dev);
+       if (ret) {
+               dev_dbg(dev, "no vqmmc-supply\n");
+       } else {
+               ret = regulator_set_enable(vqmmc_dev, true);
+               if (ret) {
+                       dev_err(dev, "fail to enable vqmmc-supply\n");
+                       return ret;
+               }
+
+               if (regulator_get_value(vqmmc_dev) == 1800000)
+                       priv->vs18_enable = 1;
+       }
+#endif
+
        /*
         * TODO:
         * Because lack of clk driver, if SDHC clk is not enabled,