[PATCH v5 3/3] rockchip: sdhci: Add HS400 Enhanced Strobe support for RK3568

zyf at rock-chips.com zyf at rock-chips.com
Wed Mar 16 02:12:24 CET 2022


Hi all,

This series have been tested successfully on the RK3568 EVB1.

Test info:
=> mmc list 
mmc at fe2b0000: 1
mmc at fe310000: 0 (eMMC)
mmc info 
Device: mmc at fe310000
Manufacturer ID: 45
OEM: 100
Name: DA601 
Bus Speed: 200000000
Mode: HS400ES (200MHz)
Rd Block Len: 512
MMC version 5.1
High Capacity: Yes
Capacity: 14.7 GiB
Bus Width: 8-bit DDR
Erase Group Size: 512 KiB
HC WP Group Size: 8 MiB
User Capacity: 14.7 GiB WRREL
Boot Capacity: 4 MiB ENH
RPMB Capacity: 4 MiB ENH
Boot area 0 is not write protected
Boot area 1 is not write protected
=> mmc read 0x30000000 0 100000
MMC read: dev # 0, block # 0, count 1048576 ... 1048576 blocks read: OK
=> mmc write 0x30000000 0 100000
MMC write: dev # 0, block # 0, count 1048576 ... 1048576 blocks written: OK

Test config:
diff --git a/arch/arm/dts/rk3568-u-boot.dtsi b/arch/arm/dts/rk3568-u-boot.dtsi
index 5a80dda275..bd98bd6191 100644
--- a/arch/arm/dts/rk3568-u-boot.dtsi
+++ b/arch/arm/dts/rk3568-u-boot.dtsi
@@ -49,6 +49,8 @@
        bus-width = <8>;
        u-boot,dm-spl;
        mmc-hs200-1_8v;
+       mmc-hs400-1_8v;
+       mmc-hs400-enhanced-strobe;
        status = "okay";
 };
 
diff --git a/configs/evb-rk3568_defconfig b/configs/evb-rk3568_defconfig
index 435be99edf..313f618723 100644
--- a/configs/evb-rk3568_defconfig
+++ b/configs/evb-rk3568_defconfig
@@ -41,6 +41,10 @@ CONFIG_ROCKCHIP_GPIO=y
 CONFIG_SYS_I2C_ROCKCHIP=y
 CONFIG_MISC=y
 CONFIG_SUPPORT_EMMC_RPMB=y
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_MMC_HS400_ES_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
+CONFIG_MMC_VERBOSE=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y

Best regards,
Yifeng

>On RK3568, a register bit must be set to enable Enhanced Strobe.
>However, it appears that the address of this register may differ from
>vendor to vendor and should be read from the underlying MMC IP. Let the
>Rockchip SDHCI driver read this address and set the relevant bit when
>Enhanced Strobe configuration is requested.
>
>The IP uses a custom mode select value (0x7) for HS400, use that instead
>of the common but non-standard SDHCI_CTRL_HS400 value (0x5). Also add
>some necessary DLL_STRBIN and DLL_TXCLK configuration for HS400.
>
>Additionally, a bit signifying that the connected hardware is an eMMC
>chip must be set to enable Data Strobe for HS400 and HS400ES modes. Also
>make the driver set this bit as appropriate.
>
>This is partly ported from Linux's Synopsys DWC MSHC driver which
>happens to be the underlying IP. (drivers/mmc/host/sdhci-of-dwcmshc.c in
>Linux tree).
>
>Co-developed-by: Yifeng Zhao <yifeng.zhao at rock-chips.com>
>Signed-off-by: Yifeng Zhao <yifeng.zhao at rock-chips.com>
>Signed-off-by: Alper Nebi Yasak <alpernebiyasak at gmail.com>
>---
>This is a fixed version I received off-list from Yifeng. I didn't modify
>the diff, but added a paragraph in the commit message mentioning their
>changes and adjusted the signoffs in the end.
>
>Didn't add the Reviewed-by tag due to changes.
>
>Changes in v5:
>- Incorporate RK3568 HS400ES fixes from Yifeng Zhao:
>  - Use DWCMSHC_CTRL_HS400 = 0x7, instead of SDHCI_CTRL_HS400 = 0x5
>  - Configure DWCMSHC_CARD_IS_EMMC in rk3568_sdhci_set_ios_post()
>  - Configure DLL_STRBIN and DLL_TXCLK for HS400.
>
>Changes in v3:
>- Set DWCMSHC_CARD_IS_EMMC bit in rk3568_emmc_phy_init()
>
>Changes in v2:
>- Rename rk3568_set_enhanced_strobe -> rk3568_sdhci_set_enhanced_strobe
>- Let set_enhanced_strobe() unset the ES bit if mode is not HS400_ES
>
>drivers/mmc/rockchip_sdhci.c | 64 ++++++++++++++++++++++++++++++++----
>1 file changed, 58 insertions(+), 6 deletions(-)
>
>diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
>index f4d5a59036a2..f3f9d83ba36f 100644
>--- a/drivers/mmc/rockchip_sdhci.c
>+++ b/drivers/mmc/rockchip_sdhci.c
>@@ -22,6 +22,8 @@
>#include <asm/arch-rockchip/clock.h>
>#include <asm/arch-rockchip/hardware.h>
>+/* DWCMSHC specific Mode Select value */
>+#define DWCMSHC_CTRL_HS400	0x7
>/* 400KHz is max freq for card ID etc. Use that as min */
>#define EMMC_MIN_FREQ	400000
>#define KHz	(1000)
>@@ -45,6 +47,14 @@
>#define ARASAN_VENDOR_REGISTER	0x78
>#define ARASAN_VENDOR_ENHANCED_STROBE	BIT(0)
>+/* DWC IP vendor area 1 pointer */
>+#define DWCMSHC_P_VENDOR_AREA1	0xe8
>+#define DWCMSHC_AREA1_MASK	GENMASK(11, 0)
>+/* Offset inside the vendor area 1 */
>+#define DWCMSHC_EMMC_CONTROL	0x2c
>+#define DWCMSHC_CARD_IS_EMMC	BIT(0)
>+#define DWCMSHC_ENHANCED_STROBE	BIT(8)
>+
>/* Rockchip specific Registers */
>#define DWCMSHC_EMMC_DLL_CTRL	0x800
>#define DWCMSHC_EMMC_DLL_CTRL_RESET	BIT(1)
>@@ -60,8 +70,14 @@
>#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_DEFAULT	0xA
>+
>+#define DLL_STRBIN_TAPNUM_DEFAULT	0x8
>+#define DLL_STRBIN_TAPNUM_FROM_SW	BIT(24)
>+#define DLL_STRBIN_DELAY_NUM_SEL	BIT(26)
>+#define DLL_STRBIN_DELAY_NUM_OFFSET	16
>+#define DLL_STRBIN_DELAY_NUM_DEFAULT	0x16
>+
>#define DLL_TXCLK_TAPNUM_FROM_SW	BIT(24)
>#define DWCMSHC_EMMC_DLL_LOCKED	BIT(8)
>#define DWCMSHC_EMMC_DLL_TIMEOUT	BIT(9)
>@@ -327,7 +343,8 @@ static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
>sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
>extra = DWCMSHC_EMMC_DLL_DLYENA |
>-	DLL_STRBIN_TAPNUM_DEFAULT;
>+	DLL_STRBIN_TAPNUM_DEFAULT |
>+	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 */
>@@ -335,7 +352,15 @@ static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
>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);
>+	/*
>+	* Before switching to hs400es mode, the driver will enable
>+	* enhanced strobe first. PHY needs to configure the parameters
>+	* of enhanced strobe first.
>+	*/
>+	extra = DWCMSHC_EMMC_DLL_DLYENA |
>+	DLL_STRBIN_DELAY_NUM_SEL |
>+	DLL_STRBIN_DELAY_NUM_DEFAULT << DLL_STRBIN_DELAY_NUM_OFFSET;
>+	sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
>}
>return 0;
>@@ -346,11 +371,30 @@ static int rk3568_emmc_get_phy(struct udevice *dev)
>return 0;
>}
>+static int rk3568_sdhci_set_enhanced_strobe(struct sdhci_host *host)
>+{
>+	struct mmc *mmc = host->mmc;
>+	u32 vendor;
>+	int reg;
>+
>+	reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK)
>+	      + DWCMSHC_EMMC_CONTROL;
>+
>+	vendor = sdhci_readl(host, reg);
>+	if (mmc->selected_mode == MMC_HS_400_ES)
>+	vendor |= DWCMSHC_ENHANCED_STROBE;
>+	else
>+	vendor &= ~DWCMSHC_ENHANCED_STROBE;
>+	sdhci_writel(host, vendor, reg);
>+
>+	return 0;
>+}
>+
>static int rk3568_sdhci_set_ios_post(struct sdhci_host *host)
>{
>struct mmc *mmc = host->mmc;
>uint clock = mmc->tran_speed;
>-	u32 reg;
>+	u32 reg, vendor_reg;
>if (!clock)
>clock = mmc->clock;
>@@ -360,8 +404,15 @@ static int rk3568_sdhci_set_ios_post(struct sdhci_host *host)
>if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES) {
>reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
>reg &= ~SDHCI_CTRL_UHS_MASK;
>-	reg |= SDHCI_CTRL_HS400;
>+	reg |= DWCMSHC_CTRL_HS400;
>sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
>+
>+	vendor_reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK)
>+	     + DWCMSHC_EMMC_CONTROL;
>+	/* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */
>+	reg = sdhci_readw(host, vendor_reg);
>+	reg |= DWCMSHC_CARD_IS_EMMC;
>+	sdhci_writew(host, reg, vendor_reg);
>} else {
>sdhci_set_uhs_timing(host);
>}
>@@ -554,6 +605,7 @@ static const struct sdhci_data rk3568_data = {
>.get_phy = rk3568_emmc_get_phy,
>.emmc_phy_init = rk3568_emmc_phy_init,
>.set_ios_post = rk3568_sdhci_set_ios_post,
>+	.set_enhanced_strobe = rk3568_sdhci_set_enhanced_strobe,
>};
>static const struct udevice_id sdhci_ids[] = {
>--
>2.35.1


More information about the U-Boot mailing list