]> git.sur5r.net Git - u-boot/commitdiff
mmc: omap_hsmmc: add support to set default io voltage
authorKishon Vijay Abraham I <kishon@ti.com>
Tue, 30 Jan 2018 15:01:32 +0000 (16:01 +0100)
committerJaehoon Chung <jh80.chung@samsung.com>
Mon, 19 Feb 2018 07:58:54 +0000 (16:58 +0900)
"ti,dual-volt" is used in linux kernel to set the voltage capabilities.
For host controller dt nodes that doesn't have "ti,dual-volt",
it's assumed 1.8v is the io voltage. This is not always true (like in
the case of beagle-x15 where the io lines are connected to 3.3v).
Hence if "no-1-8-v" property is set, io voltage will be set to 3v.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
arch/arm/include/asm/omap_mmc.h
drivers/mmc/omap_hsmmc.c

index 102aec28f9790cf685b362b39a66a121cbc5460f..c4d326dfc158bc04fa89f9cb770ef31ae801b32a 100644 (file)
@@ -65,6 +65,7 @@ struct omap_hsmmc_plat {
        struct hsmmc *base_addr;
        struct mmc mmc;
        bool cd_inverted;
+       u32 controller_flags;
 };
 
 /*
@@ -124,8 +125,10 @@ struct omap_hsmmc_plat {
 #define DTW_8_BITMODE                   (0x1 << 5) /* CON[DW8]*/
 #define SDBP_PWROFF                    (0x0 << 8)
 #define SDBP_PWRON                     (0x1 << 8)
+#define SDVS_MASK                      (0x7 << 9)
 #define SDVS_1V8                       (0x5 << 9)
 #define SDVS_3V0                       (0x6 << 9)
+#define SDVS_3V3                       (0x7 << 9)
 #define DMA_SELECT                     (0x2 << 3)
 #define ICE_MASK                       (0x1 << 0)
 #define ICE_STOP                       (0x0 << 0)
@@ -159,8 +162,13 @@ struct omap_hsmmc_plat {
 #define IE_CERR                                (0x01 << 28)
 #define IE_BADA                                (0x01 << 29)
 
-#define VS30_3V0SUP                    (1 << 25)
-#define VS18_1V8SUP                    (1 << 26)
+#define VS33_3V3SUP                    BIT(24)
+#define VS30_3V0SUP                    BIT(25)
+#define VS18_1V8SUP                    BIT(26)
+
+#define IOV_3V3                                3300000
+#define IOV_3V0                                3000000
+#define IOV_1V8                                1800000
 
 /* Driver definitions */
 #define MMCSD_SECTOR_SIZE              512
index 713faab11095cea84cb803b6270357d63b382965..5141bf66e1236d35ca51a1bcc92d69405de0fb03 100644 (file)
@@ -73,6 +73,9 @@ struct omap_hsmmc_data {
        int cd_gpio;
        int wp_gpio;
 #endif
+#endif
+#if CONFIG_IS_ENABLED(DM_MMC)
+       uint iov;
 #endif
        u8 controller_flags;
 #ifndef CONFIG_OMAP34XX
@@ -111,6 +114,8 @@ struct omap_hsmmc_adma_desc {
  * that the bandwidth is always above 3MB/s).
  */
 #define DMA_TIMEOUT_PER_MB     333
+#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT          BIT(0)
+#define OMAP_HSMMC_NO_1_8_V                    BIT(1)
 #define OMAP_HSMMC_USE_ADMA                    BIT(2)
 
 static int mmc_read_data(struct hsmmc *mmc_base, char *buf, unsigned int size);
@@ -252,6 +257,58 @@ void mmc_init_stream(struct hsmmc *mmc_base)
        writel(readl(&mmc_base->con) & ~INIT_INITSTREAM, &mmc_base->con);
 }
 
+#if CONFIG_IS_ENABLED(DM_MMC)
+static void omap_hsmmc_conf_bus_power(struct mmc *mmc)
+{
+       struct hsmmc *mmc_base;
+       struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
+       u32 val;
+
+       mmc_base = priv->base_addr;
+
+       val = readl(&mmc_base->hctl) & ~SDVS_MASK;
+
+       switch (priv->iov) {
+       case IOV_3V3:
+               val |= SDVS_3V3;
+               break;
+       case IOV_3V0:
+               val |= SDVS_3V0;
+               break;
+       case IOV_1V8:
+               val |= SDVS_1V8;
+               break;
+       }
+
+       writel(val, &mmc_base->hctl);
+}
+
+static void omap_hsmmc_set_capabilities(struct mmc *mmc)
+{
+       struct hsmmc *mmc_base;
+       struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
+       u32 val;
+
+       mmc_base = priv->base_addr;
+       val = readl(&mmc_base->capa);
+
+       if (priv->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
+               val |= (VS30_3V0SUP | VS18_1V8SUP);
+               priv->iov = IOV_3V0;
+       } else if (priv->controller_flags & OMAP_HSMMC_NO_1_8_V) {
+               val |= VS30_3V0SUP;
+               val &= ~VS18_1V8SUP;
+               priv->iov = IOV_3V0;
+       } else {
+               val |= VS18_1V8SUP;
+               val &= ~VS30_3V0SUP;
+               priv->iov = IOV_1V8;
+       }
+
+       writel(val, &mmc_base->capa);
+}
+#endif
+
 static int omap_hsmmc_init_setup(struct mmc *mmc)
 {
        struct omap_hsmmc_data *priv = omap_hsmmc_get_data(mmc);
@@ -286,9 +343,15 @@ static int omap_hsmmc_init_setup(struct mmc *mmc)
        if (reg_val & MADMA_EN)
                priv->controller_flags |= OMAP_HSMMC_USE_ADMA;
 #endif
+
+#if CONFIG_IS_ENABLED(DM_MMC)
+       omap_hsmmc_set_capabilities(mmc);
+       omap_hsmmc_conf_bus_power(mmc);
+#else
        writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl);
        writel(readl(&mmc_base->capa) | VS30_3V0SUP | VS18_1V8SUP,
                &mmc_base->capa);
+#endif
 
        reg_val = readl(&mmc_base->con) & RESERVED_MASK;
 
@@ -1071,6 +1134,10 @@ static int omap_hsmmc_ofdata_to_platdata(struct udevice *dev)
        cfg->f_max = fdtdec_get_int(fdt, node, "max-frequency", 52000000);
        cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
        cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+       if (fdtdec_get_bool(fdt, node, "ti,dual-volt"))
+               plat->controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT;
+       if (fdtdec_get_bool(fdt, node, "no-1-8-v"))
+               plat->controller_flags |= OMAP_HSMMC_NO_1_8_V;
 
 #ifdef OMAP_HSMMC_USE_GPIO
        plat->cd_inverted = fdtdec_get_bool(fdt, node, "cd-inverted");