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.z...@rock-chips.com>


Reviewed-by: Jaehoon Chung <jh80.ch...@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,
> +     },
>       { }
>  };
>  
> 

Reply via email to