diff mbox series

rockchip: sdhci: rk3568: bypass DLL when clk <= 52 MHz

Message ID 20230309012830.235782-1-anarsoul@gmail.com
State Accepted
Commit 2321a991bbb5f0de0781df09d332ee068426e264
Delegated to: Kever Yang
Headers show
Series rockchip: sdhci: rk3568: bypass DLL when clk <= 52 MHz | expand

Commit Message

Vasily Khoruzhick March 9, 2023, 1:28 a.m. UTC
For Rockchip platform, DLL bypass bit and start bit need to be set if
DLL is not locked.

With this change applied eMMC in my NanoPi R5S can run at 52 MHz.

Based on linux commit b75a52b0dda3 ("mmc: sdhci-of-dwcmshc: Update DLL
and pre-change delay for rockchip platform")

Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
---
 drivers/mmc/rockchip_sdhci.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

Comments

Kever Yang March 14, 2023, 3:10 a.m. UTC | #1
On 2023/3/9 09:28, Vasily Khoruzhick wrote:
> For Rockchip platform, DLL bypass bit and start bit need to be set if
> DLL is not locked.
>
> With this change applied eMMC in my NanoPi R5S can run at 52 MHz.
>
> Based on linux commit b75a52b0dda3 ("mmc: sdhci-of-dwcmshc: Update DLL
> and pre-change delay for rockchip platform")
>
> Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever
> ---
>   drivers/mmc/rockchip_sdhci.c | 15 +++++++++++----
>   1 file changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
> index 1ac95f32b3..fef23f593e 100644
> --- a/drivers/mmc/rockchip_sdhci.c
> +++ b/drivers/mmc/rockchip_sdhci.c
> @@ -61,6 +61,7 @@
>   #define DWCMSHC_EMMC_DLL_RXCLK		0x804
>   #define DWCMSHC_EMMC_DLL_TXCLK		0x808
>   #define DWCMSHC_EMMC_DLL_STRBIN		0x80c
> +#define DECMSHC_EMMC_DLL_CMDOUT		0x810
>   #define DWCMSHC_EMMC_DLL_STATUS0	0x840
>   #define DWCMSHC_EMMC_DLL_STATUS1	0x844
>   #define DWCMSHC_EMMC_DLL_START		BIT(0)
> @@ -69,6 +70,7 @@
>   #define DWCMSHC_EMMC_DLL_START_DEFAULT	5
>   #define DWCMSHC_EMMC_DLL_INC_VALUE	2
>   #define DWCMSHC_EMMC_DLL_INC		8
> +#define DWCMSHC_EMMC_DLL_BYPASS		BIT(24)
>   #define DWCMSHC_EMMC_DLL_DLYENA		BIT(27)
>   #define DLL_TXCLK_TAPNUM_DEFAULT	0xA
>   
> @@ -83,6 +85,7 @@
>   #define DWCMSHC_EMMC_DLL_TIMEOUT	BIT(9)
>   #define DLL_RXCLK_NO_INVERTER		1
>   #define DLL_RXCLK_INVERTER		0
> +#define DLL_RXCLK_ORI_GATE		BIT(31)
>   #define DWCMSHC_ENHANCED_STROBE		BIT(8)
>   #define DLL_LOCK_WO_TMOUT(x) \
>   	((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
> @@ -348,10 +351,14 @@ static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
>   			DLL_STRBIN_TAPNUM_FROM_SW;
>   		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);
> +		/*
> +		 * Disable DLL and reset both of sample and drive clock.
> +		 * The bypass bit and start bit need to be set if DLL is not locked.
> +		 */
> +		sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START,
> +			     DWCMSHC_EMMC_DLL_CTRL);
> +		sdhci_writel(host, DLL_RXCLK_ORI_GATE, DWCMSHC_EMMC_DLL_RXCLK);
> +		sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
>   		sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
>   		/*
>   		 * Before switching to hs400es mode, the driver will enable
diff mbox series

Patch

diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index 1ac95f32b3..fef23f593e 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -61,6 +61,7 @@ 
 #define DWCMSHC_EMMC_DLL_RXCLK		0x804
 #define DWCMSHC_EMMC_DLL_TXCLK		0x808
 #define DWCMSHC_EMMC_DLL_STRBIN		0x80c
+#define DECMSHC_EMMC_DLL_CMDOUT		0x810
 #define DWCMSHC_EMMC_DLL_STATUS0	0x840
 #define DWCMSHC_EMMC_DLL_STATUS1	0x844
 #define DWCMSHC_EMMC_DLL_START		BIT(0)
@@ -69,6 +70,7 @@ 
 #define DWCMSHC_EMMC_DLL_START_DEFAULT	5
 #define DWCMSHC_EMMC_DLL_INC_VALUE	2
 #define DWCMSHC_EMMC_DLL_INC		8
+#define DWCMSHC_EMMC_DLL_BYPASS		BIT(24)
 #define DWCMSHC_EMMC_DLL_DLYENA		BIT(27)
 #define DLL_TXCLK_TAPNUM_DEFAULT	0xA
 
@@ -83,6 +85,7 @@ 
 #define DWCMSHC_EMMC_DLL_TIMEOUT	BIT(9)
 #define DLL_RXCLK_NO_INVERTER		1
 #define DLL_RXCLK_INVERTER		0
+#define DLL_RXCLK_ORI_GATE		BIT(31)
 #define DWCMSHC_ENHANCED_STROBE		BIT(8)
 #define DLL_LOCK_WO_TMOUT(x) \
 	((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
@@ -348,10 +351,14 @@  static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
 			DLL_STRBIN_TAPNUM_FROM_SW;
 		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);
+		/*
+		 * Disable DLL and reset both of sample and drive clock.
+		 * The bypass bit and start bit need to be set if DLL is not locked.
+		 */
+		sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START,
+			     DWCMSHC_EMMC_DLL_CTRL);
+		sdhci_writel(host, DLL_RXCLK_ORI_GATE, DWCMSHC_EMMC_DLL_RXCLK);
+		sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
 		sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
 		/*
 		 * Before switching to hs400es mode, the driver will enable