[PATCH v2 2/3] mmc: rockchip_sdhci: Add support for RK3568
赵仪峰
yifeng.zhao at rock-chips.com
Tue Jun 29 04:07:28 CEST 2021
Hi Jeahoon,
>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;
The variable types are different, IS_ERR_VALUE(host->max_clk) will not got the right results.
unsigned int max_clk;
#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
>> + 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?
The host->max_clk is config by dts and need to reassign.
I will recheck the div config in sdhci_set_clock, it maybe work and no need to call clk_set_rate() to chang the source 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);
>> @@ -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