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.z...@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,



>> +    },



>>      { }



>>  };



>>  



>> 



>



>



>



>


Reply via email to