[U-Boot] [PATCH 26/33] mmc: sdhci: add support for UHS timing

Ziyuan Xu xzy.xu at rock-chips.com
Mon May 15 06:07:20 UTC 2017


To support UHS speed mode, controller should enable 1.8V signaling and
select one of UHS modes.

Signed-off-by: Ziyuan Xu <xzy.xu at rock-chips.com>
---

 drivers/mmc/sdhci.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/mmc.h       |  1 +
 include/sdhci.h     | 17 +++++++++++++++++
 3 files changed, 58 insertions(+)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index ad86278..8f4a2a1 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -426,6 +426,39 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
 	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
 }
 
+static void sdhci_set_uhs_signaling(struct sdhci_host *host)
+{
+	u16 ctrl_2;
+	u32 timing = host->mmc->timing;
+
+	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	/* Select Bus Speed Mode for host */
+	ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+
+	if ((timing != MMC_TIMING_LEGACY) &&
+	    (timing != MMC_TIMING_MMC_HS) &&
+	    (timing != MMC_TIMING_SD_HS))
+		ctrl_2 |= SDHCI_CTRL_VDD_180;
+
+	if ((timing == MMC_TIMING_MMC_HS200) ||
+	    (timing == MMC_TIMING_UHS_SDR104))
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_DRV_TYPE_A;
+	else if (timing == MMC_TIMING_UHS_SDR12)
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
+	else if (timing == MMC_TIMING_UHS_SDR25)
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
+	else if (timing == MMC_TIMING_UHS_SDR50)
+		ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
+	else if ((timing == MMC_TIMING_UHS_DDR50) ||
+		 (timing == MMC_TIMING_MMC_DDR52))
+		ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
+	else if (timing == MMC_TIMING_MMC_HS400 ||
+		 timing == MMC_TIMING_MMC_HS400ES)
+		ctrl_2 |= SDHCI_CTRL_HS400 | SDHCI_CTRL_DRV_TYPE_A;
+
+	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+}
+
 #ifdef CONFIG_DM_MMC_OPS
 static bool sdhci_card_busy(struct udevice *dev)
 {
@@ -485,6 +518,13 @@ static int sdhci_set_ios(struct mmc *mmc)
 
 	sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 
+	if ((mmc->timing != MMC_TIMING_LEGACY) &&
+	    (mmc->timing != MMC_TIMING_MMC_HS) &&
+	    (mmc->timing != MMC_TIMING_SD_HS))
+		sdhci_set_power(host, MMC_VDD_165_195_SHIFT);
+
+	sdhci_set_uhs_signaling(host);
+
 	/* If available, call the driver specific "post" set_ios() function */
 	if (host->ops && host->ops->set_ios_post)
 		host->ops->set_ios_post(host);
diff --git a/include/mmc.h b/include/mmc.h
index 05bf39d..b5817f3 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -138,6 +138,7 @@
 
 #define MMC_STATE_PRG		(7 << 9)
 
+#define MMC_VDD_165_195_SHIFT	7
 #define MMC_VDD_165_195		0x00000080	/* VDD voltage 1.65 - 1.95 */
 #define MMC_VDD_20_21		0x00000100	/* VDD voltage 2.0 ~ 2.1 */
 #define MMC_VDD_21_22		0x00000200	/* VDD voltage 2.1 ~ 2.2 */
diff --git a/include/sdhci.h b/include/sdhci.h
index 75432db..449ada1 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -147,6 +147,23 @@
 #define SDHCI_ACMD12_ERR	0x3C
 
 /* 3E-3F reserved */
+#define SDHCI_HOST_CONTROL2		0x3E
+#define SDHCI_CTRL_UHS_MASK		0x0007
+#define SDHCI_CTRL_UHS_SDR12		0x0000
+#define SDHCI_CTRL_UHS_SDR25		0x0001
+#define SDHCI_CTRL_UHS_SDR50		0x0002
+#define SDHCI_CTRL_UHS_SDR104		0x0003
+#define SDHCI_CTRL_UHS_DDR50		0x0004
+#define SDHCI_CTRL_HS400		0x0005
+#define SDHCI_CTRL_VDD_180		0x0008
+#define SDHCI_CTRL_DRV_TYPE_MASK	0x0030
+#define SDHCI_CTRL_DRV_TYPE_B		0x0000
+#define SDHCI_CTRL_DRV_TYPE_A		0x0010
+#define SDHCI_CTRL_DRV_TYPE_C		0x0020
+#define SDHCI_CTRL_DRV_TYPE_D		0x0030
+#define SDHCI_CTRL_EXEC_TUNING		0x0040
+#define SDHCI_CTRL_TUNED_CLK		0x0080
+#define SDHCI_CTRL_PRESET_VAL_ENABLE	0x8000
 
 #define SDHCI_CAPABILITIES	0x40
 #define  SDHCI_TIMEOUT_CLK_MASK	0x0000003F
-- 
2.7.4




More information about the U-Boot mailing list