[PATCH v5 3/3] rockchip: sdhci: Add HS400 Enhanced Strobe support for RK3568
Kever Yang
kever.yang at rock-chips.com
Wed Mar 16 02:56:43 CET 2022
On 2022/3/16 01:46, Alper Nebi Yasak wrote:
> 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>
Reviewed-by: Kever Yang <kever.yang at rock-chips.com>
Thanks,
- Kever
> ---
> 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[] = {
More information about the U-Boot
mailing list