From eff960303d2727b522276cb86308ce0e3055141b Mon Sep 17 00:00:00 2001 From: AmadeusGhost <42570690+AmadeusGhost@users.noreply.github.com> Date: Wed, 7 Jun 2023 21:15:48 +0800 Subject: [PATCH] rockchip: sync upstream emmc fixes from k6.4 --- .../boot/dts/rockchip/rk3568-photonicat.dts | 1 + ...ci-of-dwcmshc-add-support-for-rk3588.patch | 250 ++++++++++++++++++ ...-sdhci-of-dwcmshc-Update-DLL-and-pre.patch | 60 +++++ ...-sdhci-of-dwcmshc-properly-determine.patch | 52 ++++ ...-sdhci-of-dwcmshc-Update-DLL-and-pre.patch | 60 +++++ ...-sdhci-of-dwcmshc-properly-determine.patch | 52 ++++ 6 files changed, 475 insertions(+) create mode 100644 target/linux/rockchip/patches-5.15/063-v6.0-mmc-sdhci-of-dwcmshc-add-support-for-rk3588.patch create mode 100644 target/linux/rockchip/patches-5.15/080-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch create mode 100644 target/linux/rockchip/patches-5.15/081-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch create mode 100644 target/linux/rockchip/patches-6.1/019-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch create mode 100644 target/linux/rockchip/patches-6.1/020-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch diff --git a/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts b/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts index ac83d8fa0..2b5e30051 100644 --- a/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts +++ b/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts @@ -459,6 +459,7 @@ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd>; vmmc-supply = <&vcc_3v3>; vqmmc-supply = <&vcc_1v8>; + status = "okay"; }; &sdmmc0 { diff --git a/target/linux/rockchip/patches-5.15/063-v6.0-mmc-sdhci-of-dwcmshc-add-support-for-rk3588.patch b/target/linux/rockchip/patches-5.15/063-v6.0-mmc-sdhci-of-dwcmshc-add-support-for-rk3588.patch new file mode 100644 index 000000000..430a233d2 --- /dev/null +++ b/target/linux/rockchip/patches-5.15/063-v6.0-mmc-sdhci-of-dwcmshc-add-support-for-rk3588.patch @@ -0,0 +1,250 @@ +From c6f361cba51c536e7a6af31973c6a4e5d7e4e2e4 Mon Sep 17 00:00:00 2001 +From: Yifeng Zhao +Date: Wed, 4 May 2022 23:32:41 +0200 +Subject: [PATCH] mmc: sdhci-of-dwcmshc: add support for rk3588 + +Add support for RK3588's DWCMSHC controller, which is used for +providing the rootfs on the RK3588 evaluation board. + +Signed-off-by: Yifeng Zhao +[port from vendor BSP] +Acked-by: Adrian Hunter +Signed-off-by: Sebastian Reichel +Link: https://lore.kernel.org/r/20220504213251.264819-12-sebastian.reichel@collabora.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 121 +++++++++++++++++++++++----- + 1 file changed, 103 insertions(+), 18 deletions(-) + +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -31,6 +31,7 @@ + /* Offset inside the vendor area 1 */ + #define DWCMSHC_HOST_CTRL3 0x8 + #define DWCMSHC_EMMC_CONTROL 0x2c ++#define DWCMSHC_CARD_IS_EMMC BIT(0) + #define DWCMSHC_ENHANCED_STROBE BIT(8) + #define DWCMSHC_EMMC_ATCTRL 0x40 + +@@ -39,7 +40,7 @@ + #define DWCMSHC_EMMC_DLL_RXCLK 0x804 + #define DWCMSHC_EMMC_DLL_TXCLK 0x808 + #define DWCMSHC_EMMC_DLL_STRBIN 0x80c +-#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24) ++#define DECMSHC_EMMC_DLL_CMDOUT 0x810 + #define DWCMSHC_EMMC_DLL_STATUS0 0x840 + #define DWCMSHC_EMMC_DLL_START BIT(0) + #define DWCMSHC_EMMC_DLL_LOCKED BIT(8) +@@ -48,11 +49,21 @@ + #define DWCMSHC_EMMC_DLL_START_POINT 16 + #define DWCMSHC_EMMC_DLL_INC 8 + #define DWCMSHC_EMMC_DLL_DLYENA BIT(27) +-#define DLL_TXCLK_TAPNUM_DEFAULT 0x8 +-#define DLL_STRBIN_TAPNUM_DEFAULT 0x8 ++#define DLL_TXCLK_TAPNUM_DEFAULT 0x10 ++#define DLL_TXCLK_TAPNUM_90_DEGREES 0xA + #define DLL_TXCLK_TAPNUM_FROM_SW BIT(24) ++#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_RXCLK_NO_INVERTER 1 + #define DLL_RXCLK_INVERTER 0 ++#define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8 ++#define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24) ++#define DLL_CMDOUT_SRC_CLK_NEG BIT(28) ++#define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29) ++ + #define DLL_LOCK_WO_TMOUT(x) \ + ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ + (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0)) +@@ -61,10 +72,16 @@ + #define BOUNDARY_OK(addr, len) \ + ((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1))) + ++enum dwcmshc_rk_type { ++ DWCMSHC_RK3568, ++ DWCMSHC_RK3588, ++}; ++ + struct rk35xx_priv { + /* Rockchip specified optional clocks */ + struct clk_bulk_data rockchip_clks[RK35xx_MAX_CLKS]; + struct reset_control *reset; ++ enum dwcmshc_rk_type devtype; + u8 txclk_tapnum; + }; + +@@ -133,7 +150,9 @@ static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq) + static void dwcmshc_set_uhs_signaling(struct sdhci_host *host, + unsigned int timing) + { +- u16 ctrl_2; ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); ++ u16 ctrl, ctrl_2; + + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + /* Select Bus Speed Mode for host */ +@@ -151,8 +170,15 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host, + else if ((timing == MMC_TIMING_UHS_DDR50) || + (timing == MMC_TIMING_MMC_DDR52)) + ctrl_2 |= SDHCI_CTRL_UHS_DDR50; +- else if (timing == MMC_TIMING_MMC_HS400) ++ else if (timing == MMC_TIMING_MMC_HS400) { ++ /* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */ ++ ctrl = sdhci_readw(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL); ++ ctrl |= DWCMSHC_CARD_IS_EMMC; ++ sdhci_writew(host, ctrl, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL); ++ + ctrl_2 |= DWCMSHC_CTRL_HS400; ++ } ++ + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); + } + +@@ -185,17 +211,11 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock + + host->mmc->actual_clock = 0; + +- /* +- * DO NOT TOUCH THIS SETTING. RX clk inverter unit is enabled +- * by default, but it shouldn't be enabled. We should anyway +- * disable it before issuing any cmds. +- */ +- extra = DWCMSHC_EMMC_DLL_DLYENA | +- DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; +- sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); +- +- if (clock == 0) ++ if (clock == 0) { ++ /* Disable interface clock at initial state. */ ++ sdhci_set_clock(host, clock); + return; ++ } + + /* Rockchip platform only support 375KHz for identify mode */ + if (clock <= 400000) +@@ -213,9 +233,21 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock + extra &= ~BIT(0); + sdhci_writel(host, extra, reg); + +- if (clock <= 400000) { +- /* Disable DLL to reset sample clock */ ++ if (clock <= 52000000) { ++ /* Disable DLL and reset both of sample and drive clock */ + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); ++ sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_RXCLK); ++ sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK); ++ sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT); ++ /* ++ * 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; + } + +@@ -224,6 +256,15 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock + udelay(1); + sdhci_writel(host, 0x0, DWCMSHC_EMMC_DLL_CTRL); + ++ /* ++ * We shouldn't set DLL_RXCLK_NO_INVERTER for identify mode but ++ * we must set it in higher speed mode. ++ */ ++ extra = DWCMSHC_EMMC_DLL_DLYENA; ++ if (priv->devtype == DWCMSHC_RK3568) ++ extra |= DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; ++ sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); ++ + /* Init DLL settings */ + extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT | + 0x2 << DWCMSHC_EMMC_DLL_INC | +@@ -246,8 +287,20 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock + host->mmc->ios.timing == MMC_TIMING_MMC_HS400) + txclk_tapnum = priv->txclk_tapnum; + ++ if ((priv->devtype == DWCMSHC_RK3588) && host->mmc->ios.timing == MMC_TIMING_MMC_HS400) { ++ txclk_tapnum = DLL_TXCLK_TAPNUM_90_DEGREES; ++ ++ extra = DLL_CMDOUT_SRC_CLK_NEG | ++ DLL_CMDOUT_EN_SRC_CLK_NEG | ++ DWCMSHC_EMMC_DLL_DLYENA | ++ DLL_CMDOUT_TAPNUM_90_DEGREES | ++ DLL_CMDOUT_TAPNUM_FROM_SW; ++ sdhci_writel(host, extra, DECMSHC_EMMC_DLL_CMDOUT); ++ } ++ + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_TXCLK_TAPNUM_FROM_SW | ++ DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL | + txclk_tapnum; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK); + +@@ -345,7 +398,25 @@ static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc + return 0; + } + ++static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv) ++{ ++ /* ++ * Don't support highspeed bus mode with low clk speed as we ++ * cannot use DLL for this condition. ++ */ ++ if (host->mmc->f_max <= 52000000) { ++ dev_info(mmc_dev(host->mmc), "Disabling HS200/HS400, frequency too low (%d)\n", ++ host->mmc->f_max); ++ host->mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400); ++ host->mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR); ++ } ++} ++ + static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { ++ { ++ .compatible = "rockchip,rk3588-dwcmshc", ++ .data = &sdhci_dwcmshc_rk35xx_pdata, ++ }, + { + .compatible = "rockchip,rk3568-dwcmshc", + .data = &sdhci_dwcmshc_rk35xx_pdata, +@@ -433,6 +504,11 @@ static int dwcmshc_probe(struct platform_device *pdev) + goto err_clk; + } + ++ if (of_device_is_compatible(pdev->dev.of_node, "rockchip,rk3588-dwcmshc")) ++ rk_priv->devtype = DWCMSHC_RK3588; ++ else ++ rk_priv->devtype = DWCMSHC_RK3568; ++ + priv->priv = rk_priv; + + err = dwcmshc_rk35xx_init(host, priv); +@@ -442,12 +518,21 @@ static int dwcmshc_probe(struct platform_device *pdev) + + host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; + +- err = sdhci_add_host(host); ++ err = sdhci_setup_host(host); + if (err) + goto err_clk; + ++ if (rk_priv) ++ dwcmshc_rk35xx_postinit(host, priv); ++ ++ err = __sdhci_add_host(host); ++ if (err) ++ goto err_setup_host; ++ + return 0; + ++err_setup_host: ++ sdhci_cleanup_host(host); + err_clk: + clk_disable_unprepare(pltfm_host->clk); + clk_disable_unprepare(priv->bus_clk); diff --git a/target/linux/rockchip/patches-5.15/080-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch b/target/linux/rockchip/patches-5.15/080-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch new file mode 100644 index 000000000..ff4c32c67 --- /dev/null +++ b/target/linux/rockchip/patches-5.15/080-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch @@ -0,0 +1,60 @@ +From b75a52b0dda353aeefb4830a320589a363f49579 Mon Sep 17 00:00:00 2001 +From: Shawn Lin +Date: Thu, 2 Feb 2023 08:35:16 +0800 +Subject: [PATCH] mmc: sdhci-of-dwcmshc: Update DLL and pre-change delay for + rockchip platform + +For Rockchip platform, DLL bypass bit and start bit need to be set if +DLL is not locked. And adjust pre-change delay to 0x3 for better signal +test result. + +Signed-off-by: Shawn Lin +Link: https://lore.kernel.org/r/1675298118-64243-2-git-send-email-shawn.lin@rock-chips.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -48,6 +48,7 @@ + #define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29 + #define DWCMSHC_EMMC_DLL_START_POINT 16 + #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 0x10 + #define DLL_TXCLK_TAPNUM_90_DEGREES 0xA +@@ -60,6 +61,7 @@ + #define DLL_RXCLK_NO_INVERTER 1 + #define DLL_RXCLK_INVERTER 0 + #define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8 ++#define DLL_RXCLK_ORI_GATE BIT(31) + #define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24) + #define DLL_CMDOUT_SRC_CLK_NEG BIT(28) + #define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29) +@@ -234,9 +236,12 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock + sdhci_writel(host, extra, reg); + + if (clock <= 52000000) { +- /* Disable DLL and reset both of sample and drive clock */ +- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); +- sdhci_writel(host, 0, 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, DWCMSHC_EMMC_DLL_TXCLK); + sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT); + /* +@@ -279,7 +284,7 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock + } + + extra = 0x1 << 16 | /* tune clock stop en */ +- 0x2 << 17 | /* pre-change delay */ ++ 0x3 << 17 | /* pre-change delay */ + 0x3 << 19; /* post-change delay */ + sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL); + diff --git a/target/linux/rockchip/patches-5.15/081-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch b/target/linux/rockchip/patches-5.15/081-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch new file mode 100644 index 000000000..aa77403cf --- /dev/null +++ b/target/linux/rockchip/patches-5.15/081-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch @@ -0,0 +1,52 @@ +From 49502408007b77ff290ce62e6218cefaeedcb31a Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Thu, 9 Mar 2023 17:03:49 -0800 +Subject: [PATCH] mmc: sdhci-of-dwcmshc: properly determine max clock on + Rockchip + +Currently .get_max_clock returns the current clock rate for cclk_emmc +on rk35xx, thus max clock gets set to whatever bootloader set it to. + +In case of u-boot, it is intentionally reset to 50 MHz if it boots +from eMMC, see mmc_deinit() in u-boot sources. As a result, HS200 and +HS400 modes are never selected by Linux, because dwcmshc_rk35xx_postinit +clears appropriate caps if host->mmc->f_max is < 52MHz + +cclk_emmc is not a fixed clock on rk35xx, so using +sdhci_pltfm_clk_get_max_clock is not appropriate here. + +Implement rk35xx_get_max_clock that returns actual max clock for cclk_emmc. + +Signed-off-by: Vasily Khoruzhick +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20230310010349.509132-1-anarsoul@gmail.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -126,6 +126,13 @@ static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host) + return pltfm_host->clock; + } + ++static unsigned int rk35xx_get_max_clock(struct sdhci_host *host) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ ++ return clk_round_rate(pltfm_host->clk, ULONG_MAX); ++} ++ + static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc, + struct mmc_request *mrq) + { +@@ -343,7 +350,7 @@ static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = { + .set_clock = dwcmshc_rk3568_set_clock, + .set_bus_width = sdhci_set_bus_width, + .set_uhs_signaling = dwcmshc_set_uhs_signaling, +- .get_max_clock = sdhci_pltfm_clk_get_max_clock, ++ .get_max_clock = rk35xx_get_max_clock, + .reset = rk35xx_sdhci_reset, + .adma_write_desc = dwcmshc_adma_write_desc, + }; diff --git a/target/linux/rockchip/patches-6.1/019-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch b/target/linux/rockchip/patches-6.1/019-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch new file mode 100644 index 000000000..ff4c32c67 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/019-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch @@ -0,0 +1,60 @@ +From b75a52b0dda353aeefb4830a320589a363f49579 Mon Sep 17 00:00:00 2001 +From: Shawn Lin +Date: Thu, 2 Feb 2023 08:35:16 +0800 +Subject: [PATCH] mmc: sdhci-of-dwcmshc: Update DLL and pre-change delay for + rockchip platform + +For Rockchip platform, DLL bypass bit and start bit need to be set if +DLL is not locked. And adjust pre-change delay to 0x3 for better signal +test result. + +Signed-off-by: Shawn Lin +Link: https://lore.kernel.org/r/1675298118-64243-2-git-send-email-shawn.lin@rock-chips.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -48,6 +48,7 @@ + #define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29 + #define DWCMSHC_EMMC_DLL_START_POINT 16 + #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 0x10 + #define DLL_TXCLK_TAPNUM_90_DEGREES 0xA +@@ -60,6 +61,7 @@ + #define DLL_RXCLK_NO_INVERTER 1 + #define DLL_RXCLK_INVERTER 0 + #define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8 ++#define DLL_RXCLK_ORI_GATE BIT(31) + #define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24) + #define DLL_CMDOUT_SRC_CLK_NEG BIT(28) + #define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29) +@@ -234,9 +236,12 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock + sdhci_writel(host, extra, reg); + + if (clock <= 52000000) { +- /* Disable DLL and reset both of sample and drive clock */ +- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); +- sdhci_writel(host, 0, 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, DWCMSHC_EMMC_DLL_TXCLK); + sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT); + /* +@@ -279,7 +284,7 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock + } + + extra = 0x1 << 16 | /* tune clock stop en */ +- 0x2 << 17 | /* pre-change delay */ ++ 0x3 << 17 | /* pre-change delay */ + 0x3 << 19; /* post-change delay */ + sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL); + diff --git a/target/linux/rockchip/patches-6.1/020-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch b/target/linux/rockchip/patches-6.1/020-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch new file mode 100644 index 000000000..aa77403cf --- /dev/null +++ b/target/linux/rockchip/patches-6.1/020-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch @@ -0,0 +1,52 @@ +From 49502408007b77ff290ce62e6218cefaeedcb31a Mon Sep 17 00:00:00 2001 +From: Vasily Khoruzhick +Date: Thu, 9 Mar 2023 17:03:49 -0800 +Subject: [PATCH] mmc: sdhci-of-dwcmshc: properly determine max clock on + Rockchip + +Currently .get_max_clock returns the current clock rate for cclk_emmc +on rk35xx, thus max clock gets set to whatever bootloader set it to. + +In case of u-boot, it is intentionally reset to 50 MHz if it boots +from eMMC, see mmc_deinit() in u-boot sources. As a result, HS200 and +HS400 modes are never selected by Linux, because dwcmshc_rk35xx_postinit +clears appropriate caps if host->mmc->f_max is < 52MHz + +cclk_emmc is not a fixed clock on rk35xx, so using +sdhci_pltfm_clk_get_max_clock is not appropriate here. + +Implement rk35xx_get_max_clock that returns actual max clock for cclk_emmc. + +Signed-off-by: Vasily Khoruzhick +Acked-by: Adrian Hunter +Link: https://lore.kernel.org/r/20230310010349.509132-1-anarsoul@gmail.com +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/sdhci-of-dwcmshc.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/mmc/host/sdhci-of-dwcmshc.c ++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c +@@ -126,6 +126,13 @@ static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host) + return pltfm_host->clock; + } + ++static unsigned int rk35xx_get_max_clock(struct sdhci_host *host) ++{ ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ ++ return clk_round_rate(pltfm_host->clk, ULONG_MAX); ++} ++ + static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc, + struct mmc_request *mrq) + { +@@ -343,7 +350,7 @@ static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = { + .set_clock = dwcmshc_rk3568_set_clock, + .set_bus_width = sdhci_set_bus_width, + .set_uhs_signaling = dwcmshc_set_uhs_signaling, +- .get_max_clock = sdhci_pltfm_clk_get_max_clock, ++ .get_max_clock = rk35xx_get_max_clock, + .reset = rk35xx_sdhci_reset, + .adma_write_desc = dwcmshc_adma_write_desc, + };