
This patch adds support for the RK3568 platform to this driver.
Signed-off-by: Yifeng Zhao yifeng.zhao@rock-chips.com ---
drivers/mmc/rockchip_sdhci.c | 103 +++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+)
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index 05ed998eca..befe48e061 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -36,6 +36,31 @@ #define PHYCTRL_FREQSEL_100M 0x2 #define PHYCTRL_FREQSEL_150M 0x3
+/* Rockchip specific Registers */ +#define DWCMSHC_EMMC_DLL_CTRL 0x800 +#define DWCMSHC_EMMC_DLL_RXCLK 0x804 +#define DWCMSHC_EMMC_DLL_TXCLK 0x808 +#define DWCMSHC_EMMC_DLL_STRBIN 0x80c +#define DWCMSHC_EMMC_DLL_STATUS0 0x840 +#define DWCMSHC_EMMC_DLL_STATUS1 0x844 +#define DWCMSHC_EMMC_DLL_START BIT(0) +#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29 +#define DWCMSHC_EMMC_DLL_START_POINT 16 +#define DWCMSHC_EMMC_DLL_INC 8 +#define DWCMSHC_EMMC_DLL_DLYENA BIT(27) +#define DLL_TXCLK_TAPNUM_DEFAULT 0x10 +#define DLL_STRBIN_TAPNUM_DEFAULT 0x3 +#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24) +#define DWCMSHC_EMMC_DLL_LOCKED BIT(8) +#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9) +#define DLL_RXCLK_NO_INVERTER 1 +#define DLL_RXCLK_INVERTER 0 +#define DWCMSHC_ENHANCED_STROBE BIT(8) +#define DLL_LOCK_WO_TMOUT(x) \ + ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ + (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0)) +#define ROCKCHIP_MAX_CLKS 3 + struct rockchip_sdhc_plat { struct mmc_config cfg; struct mmc mmc; @@ -267,6 +292,74 @@ static int rk3399_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo return 0; }
+static int rk3568_emmc_phy_init(struct udevice *dev) +{ + struct rockchip_sdhc *prv = dev_get_priv(dev); + struct sdhci_host *host = &prv->host; + u32 extra; + + extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); + return 0; +} + +static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clock) +{ + u32 extra; + int timeout = 500, ret; + + ret = rockchip_emmc_set_clock(host, clock); + + if (clock >= 50 * 1000000) { + sdhci_writel(host, BIT(1), DWCMSHC_EMMC_DLL_CTRL); + udelay(1); + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); + /* Init DLL settings */ + extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT | + 0x2 << DWCMSHC_EMMC_DLL_INC | + DWCMSHC_EMMC_DLL_START; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL); + + while (1) { + if (timeout < 0) + return -ETIMEDOUT; + if (DLL_LOCK_WO_TMOUT((sdhci_readl(host, DWCMSHC_EMMC_DLL_STATUS0)))) + break; + udelay(1); + timeout--; + } + + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); + + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_TXCLK_TAPNUM_DEFAULT | + DLL_TXCLK_TAPNUM_FROM_SW; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK); + + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_STRBIN_TAPNUM_DEFAULT; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN); + udelay(1); + } else { + /* reset the clock phase when the frequency is lower than 52MHz */ + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); + extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK); + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN); + udelay(1); + } + + return ret; +} + +static int rk3568_emmc_get_phy(struct udevice *dev) +{ + return 0; +} + static int sdhci_set_ios_post(struct sdhci_host *host) { struct mmc *mmc = host->mmc; @@ -370,11 +463,21 @@ static const struct sdhci_data rk3399_data = { .emmc_phy_init = rk3399_emmc_phy_init, };
+static const struct sdhci_data rk3568_data = { + .emmc_set_clock = rk3568_sdhci_emmc_set_clock, + .get_phy = rk3568_emmc_get_phy, + .emmc_phy_init = rk3568_emmc_phy_init, +}; + static const struct udevice_id sdhci_ids[] = { { .compatible = "arasan,sdhci-5.1", .data = (ulong)&rk3399_data, }, + { + .compatible = "rockchip,rk3568-dwcmshc", + .data = (ulong)&rk3568_data, + }, { } };