public inbox for linux-rockchip@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH v2] mmc: sdhci-of-dwcmshc: Disable clock before DLL configuration
@ 2026-04-08  6:26 Shawn Lin
  2026-04-08  6:39 ` Adrian Hunter
  2026-04-19  0:04 ` kernel test robot
  0 siblings, 2 replies; 3+ messages in thread
From: Shawn Lin @ 2026-04-08  6:26 UTC (permalink / raw)
  To: Ulf Hansson; +Cc: linux-mmc, linux-rockchip, Adrian Hunter, Shawn Lin, Stable

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@vger.kernel.org>
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
---

Changes in v2:
- Add a comment about why passing zero to sdhci_enable_clk()

 drivers/mmc/host/sdhci-of-dwcmshc.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
index 6139516..5af35c9 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,16 @@ 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
+	/*
+	 * The sdclk frequency select bits in SDHCI_CLOCK_CONTROL are not functional
+	 * on Rockchip's SDHCI implementation. Instead, the clock frequency is fully
+	 * controlled via external clk provider by calling clk_set_rate(). Consequently,
+	 * passing 0 to sdhci_enable_clk() only re-enables the already-configured clock,
+	 * which matches the hardware's actual behavior.
+	 */
+	sdhci_enable_clk(host, 0);
 }
 
 static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
-- 
2.7.4


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] mmc: sdhci-of-dwcmshc: Disable clock before DLL configuration
  2026-04-08  6:26 [PATCH v2] mmc: sdhci-of-dwcmshc: Disable clock before DLL configuration Shawn Lin
@ 2026-04-08  6:39 ` Adrian Hunter
  2026-04-19  0:04 ` kernel test robot
  1 sibling, 0 replies; 3+ messages in thread
From: Adrian Hunter @ 2026-04-08  6:39 UTC (permalink / raw)
  To: Shawn Lin, Ulf Hansson; +Cc: linux-mmc, linux-rockchip, Stable

On 08/04/2026 09:26, 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@vger.kernel.org>
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>

Missing colon below, otherwise:

Acked-by: Adrian Hunter <adrian.hunter@intel.com>

> ---
> 
> Changes in v2:
> - Add a comment about why passing zero to sdhci_enable_clk()
> 
>  drivers/mmc/host/sdhci-of-dwcmshc.c | 19 ++++++++++++++++---
>  1 file changed, 16 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
> index 6139516..5af35c9 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,16 @@ 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

Missing colon

> +	/*
> +	 * The sdclk frequency select bits in SDHCI_CLOCK_CONTROL are not functional
> +	 * on Rockchip's SDHCI implementation. Instead, the clock frequency is fully
> +	 * controlled via external clk provider by calling clk_set_rate(). Consequently,
> +	 * passing 0 to sdhci_enable_clk() only re-enables the already-configured clock,
> +	 * which matches the hardware's actual behavior.
> +	 */
> +	sdhci_enable_clk(host, 0);
>  }
>  
>  static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)


_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] mmc: sdhci-of-dwcmshc: Disable clock before DLL configuration
  2026-04-08  6:26 [PATCH v2] mmc: sdhci-of-dwcmshc: Disable clock before DLL configuration Shawn Lin
  2026-04-08  6:39 ` Adrian Hunter
@ 2026-04-19  0:04 ` kernel test robot
  1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2026-04-19  0:04 UTC (permalink / raw)
  To: Shawn Lin, Ulf Hansson
  Cc: oe-kbuild-all, linux-mmc, linux-rockchip, Adrian Hunter,
	Shawn Lin, Stable

Hi Shawn,

kernel test robot noticed the following build errors:

[auto build test ERROR on v7.0]
[cannot apply to linus/master ulf-hansson-mmc-mirror/next next-20260417]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Shawn-Lin/mmc-sdhci-of-dwcmshc-Disable-clock-before-DLL-configuration/20260417-234134
base:   v7.0
patch link:    https://lore.kernel.org/r/1775629564-11267-1-git-send-email-shawn.lin%40rock-chips.com
patch subject: [PATCH v2] mmc: sdhci-of-dwcmshc: Disable clock before DLL configuration
config: i386-allmodconfig (https://download.01.org/0day-ci/archive/20260419/202604190759.51VAkEgC-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260419/202604190759.51VAkEgC-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202604190759.51VAkEgC-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/mmc/host/sdhci-of-dwcmshc.c: In function 'dwcmshc_rk3568_set_clock':
>> drivers/mmc/host/sdhci-of-dwcmshc.c:830:1: error: unknown type name 'enable_clk'
     830 | enable_clk
         | ^~~~~~~~~~
>> drivers/mmc/host/sdhci-of-dwcmshc.c:838:31: error: expected ')' before numeric constant
     838 |         sdhci_enable_clk(host, 0);
         |                               ^~
         |                               )
>> drivers/mmc/host/sdhci-of-dwcmshc.c:796:17: error: label 'enable_clk' used but not defined
     796 |                 goto enable_clk;
         |                 ^~~~


vim +/enable_clk +830 drivers/mmc/host/sdhci-of-dwcmshc.c

   706	
   707	static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock)
   708	{
   709		struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
   710		struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
   711		struct rk35xx_priv *priv = dwc_priv->priv;
   712		u8 txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT;
   713		u32 extra, reg;
   714		int err;
   715	
   716		host->mmc->actual_clock = 0;
   717	
   718		if (clock == 0) {
   719			/* Disable interface clock at initial state. */
   720			sdhci_set_clock(host, clock);
   721			return;
   722		}
   723	
   724		/* Rockchip platform only support 375KHz for identify mode */
   725		if (clock <= 400000)
   726			clock = 375000;
   727	
   728		err = clk_set_rate(pltfm_host->clk, clock);
   729		if (err)
   730			dev_err(mmc_dev(host->mmc), "fail to set clock %d", clock);
   731	
   732		sdhci_set_clock(host, clock);
   733	
   734		/* Disable cmd conflict check and internal clock gate */
   735		reg = dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3;
   736		extra = sdhci_readl(host, reg);
   737		extra &= ~BIT(0);
   738		extra |= BIT(4);
   739		sdhci_writel(host, extra, reg);
   740	
   741		/* Disable clock while config DLL */
   742		sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
   743	
   744		if (clock <= 52000000) {
   745			if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
   746			    host->mmc->ios.timing == MMC_TIMING_MMC_HS400) {
   747				dev_err(mmc_dev(host->mmc),
   748					"Can't reduce the clock below 52MHz in HS200/HS400 mode");
   749				goto enable_clk;
   750			}
   751	
   752			/*
   753			 * Disable DLL and reset both of sample and drive clock.
   754			 * The bypass bit and start bit need to be set if DLL is not locked.
   755			 */
   756			sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START, DWCMSHC_EMMC_DLL_CTRL);
   757			sdhci_writel(host, DLL_RXCLK_ORI_GATE, DWCMSHC_EMMC_DLL_RXCLK);
   758			sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
   759			sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
   760			/*
   761			 * Before switching to hs400es mode, the driver will enable
   762			 * enhanced strobe first. PHY needs to configure the parameters
   763			 * of enhanced strobe first.
   764			 */
   765			extra = DWCMSHC_EMMC_DLL_DLYENA |
   766				DLL_STRBIN_DELAY_NUM_SEL |
   767				DLL_STRBIN_DELAY_NUM_DEFAULT << DLL_STRBIN_DELAY_NUM_OFFSET;
   768			sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
   769			goto enable_clk;
   770		}
   771	
   772		/* Reset DLL */
   773		sdhci_writel(host, BIT(1), DWCMSHC_EMMC_DLL_CTRL);
   774		udelay(1);
   775		sdhci_writel(host, 0x0, DWCMSHC_EMMC_DLL_CTRL);
   776	
   777		/*
   778		 * We shouldn't set DLL_RXCLK_NO_INVERTER for identify mode but
   779		 * we must set it in higher speed mode.
   780		 */
   781		extra = DWCMSHC_EMMC_DLL_DLYENA;
   782		if (priv->devtype == DWCMSHC_RK3568)
   783			extra |= DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
   784		sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
   785	
   786		/* Init DLL settings */
   787		extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT |
   788			0x2 << DWCMSHC_EMMC_DLL_INC |
   789			DWCMSHC_EMMC_DLL_START;
   790		sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL);
   791		err = readl_poll_timeout(host->ioaddr + DWCMSHC_EMMC_DLL_STATUS0,
   792					 extra, DLL_LOCK_WO_TMOUT(extra), 1,
   793					 500 * USEC_PER_MSEC);
   794		if (err) {
   795			dev_err(mmc_dev(host->mmc), "DLL lock timeout!\n");
 > 796			goto enable_clk;
   797		}
   798	
   799		extra = 0x1 << 16 | /* tune clock stop en */
   800			0x3 << 17 | /* pre-change delay */
   801			0x3 << 19;  /* post-change delay */
   802		sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
   803	
   804		if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
   805		    host->mmc->ios.timing == MMC_TIMING_MMC_HS400)
   806			txclk_tapnum = priv->txclk_tapnum;
   807	
   808		if ((priv->devtype == DWCMSHC_RK3588) && host->mmc->ios.timing == MMC_TIMING_MMC_HS400) {
   809			txclk_tapnum = DLL_TXCLK_TAPNUM_90_DEGREES;
   810	
   811			extra = DLL_CMDOUT_SRC_CLK_NEG |
   812				DLL_CMDOUT_EN_SRC_CLK_NEG |
   813				DWCMSHC_EMMC_DLL_DLYENA |
   814				DLL_CMDOUT_TAPNUM_90_DEGREES |
   815				DLL_CMDOUT_TAPNUM_FROM_SW;
   816			sdhci_writel(host, extra, DECMSHC_EMMC_DLL_CMDOUT);
   817		}
   818	
   819		extra = DWCMSHC_EMMC_DLL_DLYENA |
   820			DLL_TXCLK_TAPNUM_FROM_SW |
   821			DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL |
   822			txclk_tapnum;
   823		sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
   824	
   825		extra = DWCMSHC_EMMC_DLL_DLYENA |
   826			DLL_STRBIN_TAPNUM_DEFAULT |
   827			DLL_STRBIN_TAPNUM_FROM_SW;
   828		sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
   829	
 > 830	enable_clk
   831		/*
   832		 * The sdclk frequency select bits in SDHCI_CLOCK_CONTROL are not functional
   833		 * on Rockchip's SDHCI implementation. Instead, the clock frequency is fully
   834		 * controlled via external clk provider by calling clk_set_rate(). Consequently,
   835		 * passing 0 to sdhci_enable_clk() only re-enables the already-configured clock,
   836		 * which matches the hardware's actual behavior.
   837		 */
 > 838		sdhci_enable_clk(host, 0);
   839	}
   840	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-04-19  0:05 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-08  6:26 [PATCH v2] mmc: sdhci-of-dwcmshc: Disable clock before DLL configuration Shawn Lin
2026-04-08  6:39 ` Adrian Hunter
2026-04-19  0:04 ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox