mmc: sdhci: add support for UHS timing

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>
This commit is contained in:
Ziyuan Xu 2017-05-15 14:07:20 +08:00 committed by Kever Yang
parent 31044c33de
commit 76194d8c2f
3 changed files with 58 additions and 0 deletions

View File

@ -425,6 +425,39 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); 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 #ifdef CONFIG_DM_MMC
static bool sdhci_card_busy(struct udevice *dev) static bool sdhci_card_busy(struct udevice *dev)
{ {
@ -484,6 +517,13 @@ static int sdhci_set_ios(struct mmc *mmc)
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 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 available, call the driver specific "post" set_ios() function */
if (host->ops && host->ops->set_ios_post) if (host->ops && host->ops->set_ios_post)
host->ops->set_ios_post(host); host->ops->set_ios_post(host);

View File

@ -138,6 +138,7 @@
#define MMC_STATE_PRG (7 << 9) #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_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ #define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */ #define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */

View File

@ -147,6 +147,23 @@
#define SDHCI_ACMD12_ERR 0x3C #define SDHCI_ACMD12_ERR 0x3C
/* 3E-3F reserved */ /* 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_CAPABILITIES 0x40
#define SDHCI_TIMEOUT_CLK_MASK 0x0000003F #define SDHCI_TIMEOUT_CLK_MASK 0x0000003F