[PATCH v2 2/3] mmc: rockchip_sdhci: Add support for RK3568

Jaehoon Chung jh80.chung at samsung.com
Tue Jun 29 02:45:00 CEST 2021


On 6/28/21 6:19 PM, Yifeng Zhao wrote:
> This patch adds support for the RK3568 platform to this driver.
> 
> Signed-off-by: Yifeng Zhao <yifeng.zhao at rock-chips.com>
> ---
> 
> 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 | 117 +++++++++++++++++++++++++++++++++++
>  1 file changed, 117 insertions(+)
> 
> diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
> index 2973911446..5ac524c9c9 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;
> @@ -178,6 +206,85 @@ 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 max_clk = host->max_clk;
> +	unsigned long mmc_clock;
> +	int val, ret;
> +	u32 extra;
> +
> +	if (clock) {
> +		mmc_clock = clk_set_rate(&priv->emmc_clk, clock);

Not need to use mmc_clock. It's possible to assign to host->max_clk directly.

host->max_clk = clk_set_rate();
if (IS_ERR_VALUE(host->max_clk))
	host->max_clk = max_clk;

> +		if (IS_ERR_VALUE(mmc_clock))
> +			host->max_clk = max_clk;
> +		else
> +			host->max_clk = mmc_clock;
> +	}
> +
> +	sdhci_set_clock(host->mmc, clock);
> +	if (!clock)
> +		return 0;
> +	host->max_clk = max_clk;

Why reassign with max_clk?

> +
> +	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);
> @@ -336,11 +443,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,
> +	},
>  	{ }
>  };
>  
> 



More information about the U-Boot mailing list