
On 6/29/21 5:24 PM, Yifeng Zhao wrote:
This patch adds support for the RK3568 platform to this driver.
Signed-off-by: Yifeng Zhao yifeng.zhao@rock-chips.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
Changes in v3:
- Config the interface clock by clk_set_rate directly
Changes in v2:
- Used sdhci_set_clock api to set clock.
- Used read_poll_timeout api to check dll status.
drivers/mmc/rockchip_sdhci.c | 109 +++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+)
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index eff134c8f5..1ac00587d4 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -42,6 +42,34 @@ ((((x) >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK) ==\ PHYCTRL_DLLRDY_DONE)
+/* Rockchip specific Registers */ +#define DWCMSHC_EMMC_DLL_CTRL 0x800 +#define DWCMSHC_EMMC_DLL_CTRL_RESET BIT(1) +#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_START_DEFAULT 5 +#define DWCMSHC_EMMC_DLL_INC_VALUE 2 +#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; @@ -167,6 +195,77 @@ 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) +{
- struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
- int val, ret;
- u32 extra;
- if (clock > host->max_clk)
clock = host->max_clk;
- if (clock)
clk_set_rate(&priv->emmc_clk, clock);
- sdhci_set_clock(host->mmc, clock);
- if (clock >= 100 * MHz) {
/* reset DLL */
sdhci_writel(host, DWCMSHC_EMMC_DLL_CTRL_RESET, DWCMSHC_EMMC_DLL_CTRL);
udelay(1);
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
/* Init DLL settings */
extra = DWCMSHC_EMMC_DLL_START_DEFAULT << DWCMSHC_EMMC_DLL_START_POINT |
DWCMSHC_EMMC_DLL_INC_VALUE << DWCMSHC_EMMC_DLL_INC |
DWCMSHC_EMMC_DLL_START;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL);
ret = read_poll_timeout(readl, host->ioaddr + DWCMSHC_EMMC_DLL_STATUS0,
val, DLL_LOCK_WO_TMOUT(val), 1, 500);
if (ret)
return ret;
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);
- } else {
/* reset the clock phase when the frequency is lower than 100MHz */
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);
- }
- return 0;
+}
+static int rk3568_emmc_get_phy(struct udevice *dev) +{
- return 0;
+}
static int rockchip_sdhci_set_ios_post(struct sdhci_host *host) { struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); @@ -339,11 +438,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,
- }, { }
};