
To support UHS speed mode, controller should enable 1.8V signaling and select one of UHS modes.
Signed-off-by: Ziyuan Xu xzy.xu@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