[v3,03/24] mmc: omap_hsmmc: add support to set default io voltage

Message ID 1517324513-13875-4-git-send-email-jjhiblot@ti.com
State New
Headers show
Series
  • Untitled series #8505
Related show

Commit Message

Jean-Jacques Hiblot Jan. 30, 2018, 3:01 p.m.
From: Kishon Vijay Abraham I <kishon@ti.com>

"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>
---

Changes in v3: None

 arch/arm/include/asm/omap_mmc.h | 12 ++++++--
 drivers/mmc/omap_hsmmc.c        | 67 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 77 insertions(+), 2 deletions(-)

Patch

diff --git a/arch/arm/include/asm/omap_mmc.h b/arch/arm/include/asm/omap_mmc.h
index 102aec2..c4d326d 100644
--- a/arch/arm/include/asm/omap_mmc.h
+++ b/arch/arm/include/asm/omap_mmc.h
@@ -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
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 713faab..5141bf6 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -74,6 +74,9 @@  struct omap_hsmmc_data {
 	int wp_gpio;
 #endif
 #endif
+#if CONFIG_IS_ENABLED(DM_MMC)
+	uint iov;
+#endif
 	u8 controller_flags;
 #ifndef CONFIG_OMAP34XX
 	struct omap_hsmmc_adma_desc *adma_desc_table;
@@ -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");