From 2b76e0cc7803e5ab561c875edaba7f6bbd87fbb0 Mon Sep 17 00:00:00 2001 From: Matthew Schwartz Date: Mon, 2 Mar 2026 13:07:17 -0800 Subject: [PATCH 1/2] mmc: sdhci-pci-gli: fix GL9750 DMA write corruption The GL9750 SD host controller has intermittent data corruption during DMA write operations. The GM_BURST register's R_OSRC_Lmt field (bits 17:16), which limits outstanding DMA read requests from system memory, is not being cleared during initialization. The Windows driver sets R_OSRC_Lmt to zero, limiting requests to the smallest unit. Clear R_OSRC_Lmt to match the Windows driver behavior. This eliminates write corruption verified with f3write/f3read tests while maintaining DMA performance. Cc: stable@vger.kernel.org Fixes: e51df6ce668a ("mmc: host: sdhci-pci: Add Genesys Logic GL975x support") Closes: https://lore.kernel.org/linux-mmc/33d12807-5c72-41ce-8679-57aa11831fad@linux.dev/ Acked-by: Adrian Hunter Signed-off-by: Matthew Schwartz Reviewed-by: Ben Chuang Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-gli.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index b0f91cc9e40e..6e4084407662 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -68,6 +68,9 @@ #define GLI_9750_MISC_TX1_DLY_VALUE 0x5 #define SDHCI_GLI_9750_MISC_SSC_OFF BIT(26) +#define SDHCI_GLI_9750_GM_BURST_SIZE 0x510 +#define SDHCI_GLI_9750_GM_BURST_SIZE_R_OSRC_LMT GENMASK(17, 16) + #define SDHCI_GLI_9750_TUNING_CONTROL 0x540 #define SDHCI_GLI_9750_TUNING_CONTROL_EN BIT(4) #define GLI_9750_TUNING_CONTROL_EN_ON 0x1 @@ -345,10 +348,16 @@ static void gli_set_9750(struct sdhci_host *host) u32 misc_value; u32 parameter_value; u32 control_value; + u32 burst_value; u16 ctrl2; gl9750_wt_on(host); + /* clear R_OSRC_Lmt to avoid DMA write corruption */ + burst_value = sdhci_readl(host, SDHCI_GLI_9750_GM_BURST_SIZE); + burst_value &= ~SDHCI_GLI_9750_GM_BURST_SIZE_R_OSRC_LMT; + sdhci_writel(host, burst_value, SDHCI_GLI_9750_GM_BURST_SIZE); + driving_value = sdhci_readl(host, SDHCI_GLI_9750_DRIVING); pll_value = sdhci_readl(host, SDHCI_GLI_9750_PLL); sw_ctrl_value = sdhci_readl(host, SDHCI_GLI_9750_SW_CTRL); From 5e3486e64094c28a526543f1e8aa0d5964b7f02d Mon Sep 17 00:00:00 2001 From: Luke Wang Date: Wed, 11 Mar 2026 17:50:06 +0800 Subject: [PATCH 2/2] mmc: sdhci: fix timing selection for 1-bit bus width When 1-bit bus width is used with HS200/HS400 capabilities set, mmc_select_hs200() returns 0 without actually switching. This causes mmc_select_timing() to skip mmc_select_hs(), leaving eMMC in legacy mode (26MHz) instead of High Speed SDR (52MHz). Per JEDEC eMMC spec section 5.3.2, 1-bit mode supports High Speed SDR. Drop incompatible HS200/HS400/UHS/DDR caps early so timing selection falls through to mmc_select_hs() correctly. Fixes: f2119df6b764 ("mmc: sd: add support for signal voltage switch procedure") Signed-off-by: Luke Wang Acked-by: Adrian Hunter Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ac7e11f37af7..fec9329e1edb 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -4532,8 +4532,15 @@ int sdhci_setup_host(struct sdhci_host *host) * their platform code before calling sdhci_add_host(), and we * won't assume 8-bit width for hosts without that CAP. */ - if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) + if (host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA) { + host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); + if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400) + host->caps1 &= ~SDHCI_SUPPORT_HS400; + mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400 | MMC_CAP2_HS400_ES); + mmc->caps &= ~(MMC_CAP_DDR | MMC_CAP_UHS); + } else { mmc->caps |= MMC_CAP_4_BIT_DATA; + } if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) mmc->caps &= ~MMC_CAP_CMD23;