[PATCH] mmc: sdhci-of-dwcmshc: Disable clock before DLL configuration

Adrian Hunter adrian.hunter at intel.com
Tue Apr 7 22:06:28 PDT 2026


On 08/04/2026 05:18, Shawn Lin wrote:
> 在 2026/04/07 星期二 14:38, Adrian Hunter 写道:
>> On 01/04/2026 06:39, Shawn Lin wrote:
>>> According to the ASIC design recommendations, the clock must be
>>> disabled before operating the DLL to prevent glitches that could
>>> affect the internal digital logic. In extreme cases, failing to
>>> do so may cause the controller to malfunction completely.
>>>
>>> Adds a step to disable the clock before DLL configuration and
>>> re-enables it at the end.
>>>
>>> Fixes: 08f3dff799d4 ("mmc: sdhci-of-dwcmshc: add rockchip platform support")
>>> Cc: <Stable at vger.kernel.org>
>>> Signed-off-by: Shawn Lin <shawn.lin at rock-chips.com>
>>> ---
>>> This is bascially a code sync with the downstream vendor kernel which was been
>>> done this way and tested for some years to confirm it could fix the issues in
>>> all corner cases.
>>>
>>>   drivers/mmc/host/sdhci-of-dwcmshc.c | 12 +++++++++---
>>>   1 file changed, 9 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
>>> index 6139516..e3ae334 100644
>>> --- a/drivers/mmc/host/sdhci-of-dwcmshc.c
>>> +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
>>> @@ -783,12 +783,15 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock
>>>       extra |= BIT(4);
>>>       sdhci_writel(host, extra, reg);
>>>   +    /* Disable clock while config DLL */
>>> +    sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
>>> +
>>>       if (clock <= 52000000) {
>>>           if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
>>>               host->mmc->ios.timing == MMC_TIMING_MMC_HS400) {
>>>               dev_err(mmc_dev(host->mmc),
>>>                   "Can't reduce the clock below 52MHz in HS200/HS400 mode");
>>> -            return;
>>> +            goto enable_clk;
>>>           }
>>>             /*
>>> @@ -808,7 +811,7 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock
>>>               DLL_STRBIN_DELAY_NUM_SEL |
>>>               DLL_STRBIN_DELAY_NUM_DEFAULT << DLL_STRBIN_DELAY_NUM_OFFSET;
>>>           sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
>>> -        return;
>>> +        goto enable_clk;
>>>       }
>>>         /* Reset DLL */
>>> @@ -835,7 +838,7 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock
>>>                    500 * USEC_PER_MSEC);
>>>       if (err) {
>>>           dev_err(mmc_dev(host->mmc), "DLL lock timeout!\n");
>>> -        return;
>>> +        goto enable_clk;
>>>       }
>>>         extra = 0x1 << 16 | /* tune clock stop en */
>>> @@ -868,6 +871,9 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock
>>>           DLL_STRBIN_TAPNUM_DEFAULT |
>>>           DLL_STRBIN_TAPNUM_FROM_SW;
>>>       sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
>>> +
>>> +enable_clk:
>>> +    sdhci_enable_clk(host, 0);
>>
>> Should this be 0?  If so, needs some explanation.
> 
> Yes, passing 0 is intentional for the Rockchip platform.
> This controller on Rockchip has SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN
> set, indicating that the base clock capability reporting is unreliable.
> More importantly, the sdclk frequency select bits in the
> SDHCI_CLOCK_CONTROL register are actually non-functional on this hardware. The sdclk frequency is instead set via clk_set_rate()for all
> modes. From this point, all of the sdhci_set_clock() calls and in
> dwcmshc_rk3568_set_clock() are also served as enabling and disabling
> clk only.
> 
> Therefore, sdhci_enable_clk(host, 0) is simply re-enabling the
> clock without modifying the frequency selection bits, which aligns with
> the hardware's actual behavior.
> 
> Technically speaking, we could save the previously calculated sdclk
> value and pass it to sdhci_enable_clk(). However, since the frequency
> select bits are ignored by the hardware, passing 0 is safe and
> functionally equivalent. I could add a comment for just this line change

Yes please

> or would you like me to add a comment for the whole sdclk stuff in
> dwcmshc_rk3568_set_clock()?
> 
> 
>>
>>>   }
>>>     static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
>>
>>




More information about the Linux-rockchip mailing list