From 3009738a855cf938bbfc9078bec725031ae623a4 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Mon, 22 Dec 2025 15:11:25 +0800 Subject: mmc: sdhci-of-dwcmshc: Prevent illegal clock reduction in HS200/HS400 mode When operating in HS200 or HS400 timing modes, reducing the clock frequency below 52MHz will lead to link broken as the Rockchip DWC MSHC controller requires maintaining a minimum clock of 52MHz in these modes. Add a check to prevent illegal clock reduction through debugfs: root@debian:/# echo 50000000 > /sys/kernel/debug/mmc0/clock root@debian:/# [ 30.090146] mmc0: running CQE recovery mmc0: cqhci: Failed to halt mmc0: cqhci: spurious TCN for tag 0 WARNING: drivers/mmc/host/cqhci-core.c:797 at cqhci_irq+0x254/0x818, CPU#1: kworker/1:0H/24 Modules linked in: CPU: 1 UID: 0 PID: 24 Comm: kworker/1:0H Not tainted 6.19.0-rc1-00001-g09db0998649d-dirty #204 PREEMPT Hardware name: Rockchip RK3588 EVB1 V10 Board (DT) Workqueue: kblockd blk_mq_run_work_fn pstate: 604000c9 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : cqhci_irq+0x254/0x818 lr : cqhci_irq+0x254/0x818 ... Fixes: c6f361cba51c ("mmc: sdhci-of-dwcmshc: add support for rk3588") Cc: Sebastian Reichel Cc: Yifeng Zhao Signed-off-by: Shawn Lin Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-dwcmshc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 51949cde0958..204830b40587 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -739,6 +739,13 @@ static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock sdhci_writel(host, extra, reg); 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; + } + /* * 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. -- cgit v1.2.3 From 122610220134b32c742cc056eaf64f7017ac8cd9 Mon Sep 17 00:00:00 2001 From: Matthew Schwartz Date: Mon, 29 Dec 2025 12:45:26 -0800 Subject: mmc: rtsx_pci_sdmmc: implement sdmmc_card_busy function rtsx_pci_sdmmc does not have an sdmmc_card_busy function, so any voltage switches cause a kernel warning, "mmc0: cannot verify signal voltage switch." Copy the sdmmc_card_busy function from rtsx_pci_usb to rtsx_pci_sdmmc to fix this. Fixes: ff984e57d36e ("mmc: Add realtek pcie sdmmc host driver") Signed-off-by: Matthew Schwartz Tested-by: Ricky WU Reviewed-by: Ricky WU Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/rtsx_pci_sdmmc.c | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index dc2587ff8519..4db3328f46df 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -1306,6 +1306,46 @@ out: return err; } +static int sdmmc_card_busy(struct mmc_host *mmc) +{ + struct realtek_pci_sdmmc *host = mmc_priv(mmc); + struct rtsx_pcr *pcr = host->pcr; + int err; + u8 stat; + u8 mask = SD_DAT3_STATUS | SD_DAT2_STATUS | SD_DAT1_STATUS + | SD_DAT0_STATUS; + + mutex_lock(&pcr->pcr_mutex); + + rtsx_pci_start_run(pcr); + + err = rtsx_pci_write_register(pcr, SD_BUS_STAT, + SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, + SD_CLK_TOGGLE_EN); + if (err) + goto out; + + mdelay(1); + + err = rtsx_pci_read_register(pcr, SD_BUS_STAT, &stat); + if (err) + goto out; + + err = rtsx_pci_write_register(pcr, SD_BUS_STAT, + SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); +out: + mutex_unlock(&pcr->pcr_mutex); + + if (err) + return err; + + /* check if any pin between dat[0:3] is low */ + if ((stat & mask) != mask) + return 1; + else + return 0; +} + static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) { struct realtek_pci_sdmmc *host = mmc_priv(mmc); @@ -1418,6 +1458,7 @@ static const struct mmc_host_ops realtek_pci_sdmmc_ops = { .get_ro = sdmmc_get_ro, .get_cd = sdmmc_get_cd, .start_signal_voltage_switch = sdmmc_switch_voltage, + .card_busy = sdmmc_card_busy, .execute_tuning = sdmmc_execute_tuning, .init_sd_express = sdmmc_init_sd_express, }; -- cgit v1.2.3 From fd9809ec6704db0c162b4510b11f877ec7b72065 Mon Sep 17 00:00:00 2001 From: Huan He Date: Wed, 14 Jan 2026 20:21:41 +0800 Subject: mmc: sdhci-of-dwcmshc: Fix init for AXI clock for Eswin EIC7700 Accessing the High-Speed registers requires the AXI clock to be enabled. Signed-off-by: Huan He Acked-by: Adrian Hunter Fixes: 32b2633219d3 ("mmc: sdhci-of-dwcmshc: Add support for Eswin EIC7700") Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-dwcmshc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 204830b40587..629ff6fa29a2 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -1595,6 +1595,7 @@ static int eic7700_init(struct device *dev, struct sdhci_host *host, struct dwcm { u32 emmc_caps = MMC_CAP2_NO_SD | MMC_CAP2_NO_SDIO; unsigned int val, hsp_int_status, hsp_pwr_ctrl; + static const char * const clk_ids[] = {"axi"}; struct of_phandle_args args; struct eic7700_priv *priv; struct regmap *hsp_regmap; @@ -1612,6 +1613,11 @@ static int eic7700_init(struct device *dev, struct sdhci_host *host, struct dwcm return ret; } + ret = dwcmshc_get_enable_other_clks(mmc_dev(host->mmc), dwc_priv, + ARRAY_SIZE(clk_ids), clk_ids); + if (ret) + return ret; + ret = of_parse_phandle_with_fixed_args(dev->of_node, "eswin,hsp-sp-csr", 2, 0, &args); if (ret) { dev_err(dev, "Fail to parse 'eswin,hsp-sp-csr' phandle (%d)\n", ret); -- cgit v1.2.3 From 5cfc828502cbd0c827113bdb5694c2658af2c37c Mon Sep 17 00:00:00 2001 From: Huan He Date: Wed, 14 Jan 2026 20:22:56 +0800 Subject: mmc: sdhci-of-dwcmshc: Fix DMA 128MB boundary for Eswin EIC7700 This DWC MSHC has a 128MB limitation where the data buffer size and start address must not exceed the 128MB boundary. Registering the missing 'adma_write_desc' callback function. Signed-off-by: Huan He Acked-by: Adrian Hunter Fixes: 32b2633219d3 ("mmc: sdhci-of-dwcmshc: Add support for Eswin EIC7700") Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-dwcmshc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 629ff6fa29a2..2b75a36c096b 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -1739,6 +1739,7 @@ static const struct sdhci_ops sdhci_dwcmshc_eic7700_ops = { .set_uhs_signaling = sdhci_eic7700_set_uhs_wrapper, .set_power = sdhci_set_power_and_bus_voltage, .irq = dwcmshc_cqe_irq_handler, + .adma_write_desc = dwcmshc_adma_write_desc, .platform_execute_tuning = sdhci_eic7700_executing_tuning, }; -- cgit v1.2.3