[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