From 6bc022653d514bd898f23c5f3e48773438e3d5dd Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 29 Jan 2025 21:43:35 +0000 Subject: [PATCH 01/27] mmc: slot-gpio: Remove unused mmc_gpio_set_cd_isr mmc_gpio_set_cd_isr() last use was removed in 2018 by commit 7838a8ddc80b ("mmc: omap_hsmmc: Kill off cover detection") Remove it. Signed-off-by: Dr. David Alan Gilbert Link: https://lore.kernel.org/r/20250129214335.125292-1-linux@treblig.org Signed-off-by: Ulf Hansson --- drivers/mmc/core/slot-gpio.c | 12 ------------ include/linux/mmc/slot-gpio.h | 1 - 2 files changed, 13 deletions(-) diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 12247219e1c2..5fd455816393 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c @@ -159,18 +159,6 @@ int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on) } EXPORT_SYMBOL(mmc_gpio_set_cd_wake); -/* Register an alternate interrupt service routine for - * the card-detect GPIO. - */ -void mmc_gpio_set_cd_isr(struct mmc_host *host, irq_handler_t isr) -{ - struct mmc_gpio *ctx = host->slot.handler_priv; - - WARN_ON(ctx->cd_gpio_isr); - ctx->cd_gpio_isr = isr; -} -EXPORT_SYMBOL(mmc_gpio_set_cd_isr); - /** * mmc_gpiod_request_cd - request a gpio descriptor for card-detection * @host: mmc host diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h index 274a2767ea49..1ed7b0d1e4f9 100644 --- a/include/linux/mmc/slot-gpio.h +++ b/include/linux/mmc/slot-gpio.h @@ -22,7 +22,6 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, unsigned int idx, unsigned int debounce); int mmc_gpiod_set_cd_config(struct mmc_host *host, unsigned long config); -void mmc_gpio_set_cd_isr(struct mmc_host *host, irq_handler_t isr); int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on); void mmc_gpiod_request_cd_irq(struct mmc_host *host); bool mmc_can_gpio_cd(struct mmc_host *host); From 4e35c611eed74ad6a127853f7c2f7dec08458bbb Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Fri, 31 Jan 2025 11:54:06 +0900 Subject: [PATCH 02/27] mmc: sdhci-of-dwcmshc: Change to dwcmshc_phy_init for reusing codes dwcmshc_phy_1_8v_init and dwcmshc_phy_3_3v_init differ only by a few lines of code. This allow us to reuse code depending on voltage. Signed-off-by: Jaehoon Chung Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20250131025406.1753513-1-jh80.chung@samsung.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-dwcmshc.c | 72 ++++++----------------------- 1 file changed, 15 insertions(+), 57 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 7ea3da45db32..09b9ab15e499 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -328,12 +328,17 @@ static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq) sdhci_request(mmc, mrq); } -static void dwcmshc_phy_1_8v_init(struct sdhci_host *host) +static void dwcmshc_phy_init(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); + u32 rxsel = PHY_PAD_RXSEL_3V3; u32 val; + if (priv->flags & FLAG_IO_FIXED_1V8 || + host->mmc->ios.timing & MMC_SIGNAL_VOLTAGE_180) + rxsel = PHY_PAD_RXSEL_1V8; + /* deassert phy reset & set tx drive strength */ val = PHY_CNFG_RSTN_DEASSERT; val |= FIELD_PREP(PHY_CNFG_PAD_SP_MASK, PHY_CNFG_PAD_SP); @@ -353,7 +358,7 @@ static void dwcmshc_phy_1_8v_init(struct sdhci_host *host) sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R); /* configure phy pads */ - val = PHY_PAD_RXSEL_1V8; + val = rxsel; val |= FIELD_PREP(PHY_PAD_WEAKPULL_MASK, PHY_PAD_WEAKPULL_PULLUP); val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_P_MASK, PHY_PAD_TXSLEW_CTRL_P); val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N); @@ -365,65 +370,22 @@ static void dwcmshc_phy_1_8v_init(struct sdhci_host *host) val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N); sdhci_writew(host, val, PHY_CLKPAD_CNFG_R); - val = PHY_PAD_RXSEL_1V8; + val = rxsel; val |= FIELD_PREP(PHY_PAD_WEAKPULL_MASK, PHY_PAD_WEAKPULL_PULLDOWN); val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_P_MASK, PHY_PAD_TXSLEW_CTRL_P); val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N); sdhci_writew(host, val, PHY_STBPAD_CNFG_R); /* enable data strobe mode */ - sdhci_writeb(host, FIELD_PREP(PHY_DLLDL_CNFG_SLV_INPSEL_MASK, PHY_DLLDL_CNFG_SLV_INPSEL), - PHY_DLLDL_CNFG_R); + if (rxsel == PHY_PAD_RXSEL_1V8) { + u8 sel = FIELD_PREP(PHY_DLLDL_CNFG_SLV_INPSEL_MASK, PHY_DLLDL_CNFG_SLV_INPSEL); + + sdhci_writeb(host, sel, PHY_DLLDL_CNFG_R); + } /* enable phy dll */ sdhci_writeb(host, PHY_DLL_CTRL_ENABLE, PHY_DLL_CTRL_R); -} -static void dwcmshc_phy_3_3v_init(struct sdhci_host *host) -{ - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); - u32 val; - - /* deassert phy reset & set tx drive strength */ - val = PHY_CNFG_RSTN_DEASSERT; - val |= FIELD_PREP(PHY_CNFG_PAD_SP_MASK, PHY_CNFG_PAD_SP); - val |= FIELD_PREP(PHY_CNFG_PAD_SN_MASK, PHY_CNFG_PAD_SN); - sdhci_writel(host, val, PHY_CNFG_R); - - /* disable delay line */ - sdhci_writeb(host, PHY_SDCLKDL_CNFG_UPDATE, PHY_SDCLKDL_CNFG_R); - - /* set delay line */ - sdhci_writeb(host, priv->delay_line, PHY_SDCLKDL_DC_R); - sdhci_writeb(host, PHY_DLL_CNFG2_JUMPSTEP, PHY_DLL_CNFG2_R); - - /* enable delay lane */ - val = sdhci_readb(host, PHY_SDCLKDL_CNFG_R); - val &= ~(PHY_SDCLKDL_CNFG_UPDATE); - sdhci_writeb(host, val, PHY_SDCLKDL_CNFG_R); - - /* configure phy pads */ - val = PHY_PAD_RXSEL_3V3; - val |= FIELD_PREP(PHY_PAD_WEAKPULL_MASK, PHY_PAD_WEAKPULL_PULLUP); - val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_P_MASK, PHY_PAD_TXSLEW_CTRL_P); - val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N); - sdhci_writew(host, val, PHY_CMDPAD_CNFG_R); - sdhci_writew(host, val, PHY_DATAPAD_CNFG_R); - sdhci_writew(host, val, PHY_RSTNPAD_CNFG_R); - - val = FIELD_PREP(PHY_PAD_TXSLEW_CTRL_P_MASK, PHY_PAD_TXSLEW_CTRL_P); - val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N); - sdhci_writew(host, val, PHY_CLKPAD_CNFG_R); - - val = PHY_PAD_RXSEL_3V3; - val |= FIELD_PREP(PHY_PAD_WEAKPULL_MASK, PHY_PAD_WEAKPULL_PULLDOWN); - val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_P_MASK, PHY_PAD_TXSLEW_CTRL_P); - val |= FIELD_PREP(PHY_PAD_TXSLEW_CTRL_N_MASK, PHY_PAD_TXSLEW_CTRL_N); - sdhci_writew(host, val, PHY_STBPAD_CNFG_R); - - /* enable phy dll */ - sdhci_writeb(host, PHY_DLL_CTRL_ENABLE, PHY_DLL_CTRL_R); } static void th1520_sdhci_set_phy(struct sdhci_host *host) @@ -433,11 +395,7 @@ static void th1520_sdhci_set_phy(struct sdhci_host *host) u32 emmc_caps = MMC_CAP2_NO_SD | MMC_CAP2_NO_SDIO; u16 emmc_ctrl; - /* Before power on, set PHY configs */ - if (priv->flags & FLAG_IO_FIXED_1V8) - dwcmshc_phy_1_8v_init(host); - else - dwcmshc_phy_3_3v_init(host); + dwcmshc_phy_init(host); if ((host->mmc->caps2 & emmc_caps) == emmc_caps) { emmc_ctrl = sdhci_readw(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL); @@ -1163,7 +1121,7 @@ static const struct sdhci_ops sdhci_dwcmshc_th1520_ops = { .get_max_clock = dwcmshc_get_max_clock, .reset = th1520_sdhci_reset, .adma_write_desc = dwcmshc_adma_write_desc, - .voltage_switch = dwcmshc_phy_1_8v_init, + .voltage_switch = dwcmshc_phy_init, .platform_execute_tuning = th1520_execute_tuning, }; From fb3bbc46c94f261b6156ee863c1b06c84cf157dc Mon Sep 17 00:00:00 2001 From: Erick Shepherd Date: Tue, 11 Feb 2025 15:46:45 -0600 Subject: [PATCH 03/27] mmc: sdhci: Disable SD card clock before changing parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the SD Host Controller Simplified Specification v4.20 §3.2.3, change the SD card clock parameters only after first disabling the external card clock. Doing this fixes a spurious clock pulse on Baytrail and Apollo Lake SD controllers which otherwise breaks voltage switching with a specific Swissbit SD card. Signed-off-by: Kyle Roeschley Signed-off-by: Brad Mouring Signed-off-by: Erick Shepherd Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20250211214645.469279-1-erick.shepherd@ni.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index f4a7733a8ad2..5f91b44891f9 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2065,10 +2065,15 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) host->mmc->actual_clock = 0; - sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + if (clk & SDHCI_CLOCK_CARD_EN) + sdhci_writew(host, clk & ~SDHCI_CLOCK_CARD_EN, + SDHCI_CLOCK_CONTROL); - if (clock == 0) + if (clock == 0) { + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); return; + } clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); sdhci_enable_clk(host, clk); From 63dde9c39374edab42d23439633b21b132e51039 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Wed, 19 Feb 2025 00:17:47 +0530 Subject: [PATCH 04/27] dt-bindings: mmc: samsung,exynos-dw-mshc: add exynos7870 support Document the compatibles for Exynos7870's DW MMC driver, for both non-SMU and SMU variants. Signed-off-by: Kaustabh Chakraborty Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250219-exynos7870-mmc-v2-1-b4255a3e39ed@disroot.org Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml index ef2d1d7c92fc..e8bd49d46794 100644 --- a/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml +++ b/Documentation/devicetree/bindings/mmc/samsung,exynos-dw-mshc.yaml @@ -24,6 +24,8 @@ properties: - samsung,exynos5420-dw-mshc-smu - samsung,exynos7-dw-mshc - samsung,exynos7-dw-mshc-smu + - samsung,exynos7870-dw-mshc + - samsung,exynos7870-dw-mshc-smu - items: - enum: - samsung,exynos5433-dw-mshc-smu From 57c0902f8bec51add5a1eb908d8b876592725d81 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Wed, 19 Feb 2025 00:17:48 +0530 Subject: [PATCH 05/27] mmc: dw_mmc: add a quirk for accessing 64-bit FIFOs in two halves In certain DW MMC implementations (such as in some Exynos7870 controllers), 64-bit read/write is not allowed from a 64-bit FIFO. Add a quirk which facilitates accessing the 64-bit FIFO registers in two 32-bit halves. Signed-off-by: Kaustabh Chakraborty Link: https://lore.kernel.org/r/20250219-exynos7870-mmc-v2-2-b4255a3e39ed@disroot.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.c | 94 ++++++++++++++++++++++++++++++++++++++- drivers/mmc/host/dw_mmc.h | 27 +++++++++++ 2 files changed, 119 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 3cbda98d08d2..74f224647bf1 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2579,6 +2579,91 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt) } } +static void dw_mci_push_data64_32(struct dw_mci *host, void *buf, int cnt) +{ + struct mmc_data *data = host->data; + int init_cnt = cnt; + + /* try and push anything in the part_buf */ + if (unlikely(host->part_buf_count)) { + int len = dw_mci_push_part_bytes(host, buf, cnt); + + buf += len; + cnt -= len; + + if (host->part_buf_count == 8) { + mci_fifo_l_writeq(host->fifo_reg, host->part_buf); + host->part_buf_count = 0; + } + } +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + if (unlikely((unsigned long)buf & 0x7)) { + while (cnt >= 8) { + u64 aligned_buf[16]; + int len = min(cnt & -8, (int)sizeof(aligned_buf)); + int items = len >> 3; + int i; + /* memcpy from input buffer into aligned buffer */ + memcpy(aligned_buf, buf, len); + buf += len; + cnt -= len; + /* push data from aligned buffer into fifo */ + for (i = 0; i < items; ++i) + mci_fifo_l_writeq(host->fifo_reg, aligned_buf[i]); + } + } else +#endif + { + u64 *pdata = buf; + + for (; cnt >= 8; cnt -= 8) + mci_fifo_l_writeq(host->fifo_reg, *pdata++); + buf = pdata; + } + /* put anything remaining in the part_buf */ + if (cnt) { + dw_mci_set_part_bytes(host, buf, cnt); + /* Push data if we have reached the expected data length */ + if ((data->bytes_xfered + init_cnt) == + (data->blksz * data->blocks)) + mci_fifo_l_writeq(host->fifo_reg, host->part_buf); + } +} + +static void dw_mci_pull_data64_32(struct dw_mci *host, void *buf, int cnt) +{ +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + if (unlikely((unsigned long)buf & 0x7)) { + while (cnt >= 8) { + /* pull data from fifo into aligned buffer */ + u64 aligned_buf[16]; + int len = min(cnt & -8, (int)sizeof(aligned_buf)); + int items = len >> 3; + int i; + + for (i = 0; i < items; ++i) + aligned_buf[i] = mci_fifo_l_readq(host->fifo_reg); + + /* memcpy from aligned buffer into output buffer */ + memcpy(buf, aligned_buf, len); + buf += len; + cnt -= len; + } + } else +#endif + { + u64 *pdata = buf; + + for (; cnt >= 8; cnt -= 8) + *pdata++ = mci_fifo_l_readq(host->fifo_reg); + buf = pdata; + } + if (cnt) { + host->part_buf = mci_fifo_l_readq(host->fifo_reg); + dw_mci_pull_final_bytes(host, buf, cnt); + } +} + static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt) { int len; @@ -3379,8 +3464,13 @@ int dw_mci_probe(struct dw_mci *host) width = 16; host->data_shift = 1; } else if (i == 2) { - host->push_data = dw_mci_push_data64; - host->pull_data = dw_mci_pull_data64; + if ((host->quirks & DW_MMC_QUIRK_FIFO64_32)) { + host->push_data = dw_mci_push_data64_32; + host->pull_data = dw_mci_pull_data64_32; + } else { + host->push_data = dw_mci_push_data64; + host->pull_data = dw_mci_pull_data64; + } width = 64; host->data_shift = 3; } else { diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 6447b916990d..5463392dc811 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -281,6 +281,8 @@ struct dw_mci_board { /* Support for longer data read timeout */ #define DW_MMC_QUIRK_EXTENDED_TMOUT BIT(0) +/* Force 32-bit access to the FIFO */ +#define DW_MMC_QUIRK_FIFO64_32 BIT(1) #define DW_MMC_240A 0x240a #define DW_MMC_280A 0x280a @@ -472,6 +474,31 @@ struct dw_mci_board { #define mci_fifo_writel(__value, __reg) __raw_writel(__reg, __value) #define mci_fifo_writeq(__value, __reg) __raw_writeq(__reg, __value) +/* + * Some dw_mmc devices have 64-bit FIFOs, but expect them to be + * accessed using two 32-bit accesses. If such controller is used + * with a 64-bit kernel, this has to be done explicitly. + */ +static inline u64 mci_fifo_l_readq(void __iomem *addr) +{ + u64 ans; + u32 proxy[2]; + + proxy[0] = mci_fifo_readl(addr); + proxy[1] = mci_fifo_readl(addr + 4); + memcpy(&ans, proxy, 8); + return ans; +} + +static inline void mci_fifo_l_writeq(void __iomem *addr, u64 value) +{ + u32 proxy[2]; + + memcpy(proxy, &value, 8); + mci_fifo_writel(addr, proxy[0]); + mci_fifo_writel(addr + 4, proxy[1]); +} + /* Register access macros */ #define mci_readl(dev, reg) \ readl_relaxed((dev)->regs + SDMMC_##reg) From 7cbe799ac10fd8be85af5e0615c4337f81e575f3 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Wed, 19 Feb 2025 00:17:49 +0530 Subject: [PATCH 06/27] mmc: dw_mmc: add exynos7870 DW MMC support Add support for Exynos7870 DW MMC controllers, for both SMU and non-SMU variants. These controllers require a quirk to access 64-bit FIFO in 32-bit accesses (DW_MMC_QUIRK_FIFO64_32). Signed-off-by: Kaustabh Chakraborty Link: https://lore.kernel.org/r/20250219-exynos7870-mmc-v2-3-b4255a3e39ed@disroot.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc-exynos.c | 41 +++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 53d32d0f2709..e3548408ca39 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -27,6 +27,8 @@ enum dw_mci_exynos_type { DW_MCI_TYPE_EXYNOS5420_SMU, DW_MCI_TYPE_EXYNOS7, DW_MCI_TYPE_EXYNOS7_SMU, + DW_MCI_TYPE_EXYNOS7870, + DW_MCI_TYPE_EXYNOS7870_SMU, DW_MCI_TYPE_ARTPEC8, }; @@ -69,6 +71,12 @@ static struct dw_mci_exynos_compatible { }, { .compatible = "samsung,exynos7-dw-mshc-smu", .ctrl_type = DW_MCI_TYPE_EXYNOS7_SMU, + }, { + .compatible = "samsung,exynos7870-dw-mshc", + .ctrl_type = DW_MCI_TYPE_EXYNOS7870, + }, { + .compatible = "samsung,exynos7870-dw-mshc-smu", + .ctrl_type = DW_MCI_TYPE_EXYNOS7870_SMU, }, { .compatible = "axis,artpec8-dw-mshc", .ctrl_type = DW_MCI_TYPE_ARTPEC8, @@ -85,6 +93,8 @@ static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host) return EXYNOS4210_FIXED_CIU_CLK_DIV; else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL64)) + 1; else @@ -100,7 +110,8 @@ static void dw_mci_exynos_config_smu(struct dw_mci *host) * set for non-ecryption mode at this time. */ if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU || - priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU) { + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) { mci_writel(host, MPSBEGIN0, 0); mci_writel(host, MPSEND0, SDMMC_ENDING_SEC_NR_MAX); mci_writel(host, MPSCTRL0, SDMMC_MPSCTRL_SECURE_WRITE_BIT | @@ -126,6 +137,12 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) DQS_CTRL_GET_RD_DELAY(priv->saved_strobe_ctrl); } + if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) { + /* Quirk needed for certain Exynos SoCs */ + host->quirks |= DW_MMC_QUIRK_FIFO64_32; + } + if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) { /* Quirk needed for the ARTPEC-8 SoC */ host->quirks |= DW_MMC_QUIRK_EXTENDED_TMOUT; @@ -143,6 +160,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing) if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) clksel = mci_readl(host, CLKSEL64); else @@ -152,6 +171,8 @@ static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing) if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) mci_writel(host, CLKSEL64, clksel); else @@ -222,6 +243,8 @@ static int dw_mci_exynos_resume_noirq(struct device *dev) if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) clksel = mci_readl(host, CLKSEL64); else @@ -230,6 +253,8 @@ static int dw_mci_exynos_resume_noirq(struct device *dev) if (clksel & SDMMC_CLKSEL_WAKEUP_INT) { if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) mci_writel(host, CLKSEL64, clksel); else @@ -409,6 +434,8 @@ static inline u8 dw_mci_exynos_get_clksmpl(struct dw_mci *host) if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) return SDMMC_CLKSEL_CCLK_SAMPLE(mci_readl(host, CLKSEL64)); else @@ -422,6 +449,8 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample) if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) clksel = mci_readl(host, CLKSEL64); else @@ -429,6 +458,8 @@ static inline void dw_mci_exynos_set_clksmpl(struct dw_mci *host, u8 sample) clksel = SDMMC_CLKSEL_UP_SAMPLE(clksel, sample); if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) mci_writel(host, CLKSEL64, clksel); else @@ -443,6 +474,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host) if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) clksel = mci_readl(host, CLKSEL64); else @@ -453,6 +486,8 @@ static inline u8 dw_mci_exynos_move_next_clksmpl(struct dw_mci *host) if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS7 || priv->ctrl_type == DW_MCI_TYPE_EXYNOS7_SMU || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870 || + priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU || priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) mci_writel(host, CLKSEL64, clksel); else @@ -632,6 +667,10 @@ static const struct of_device_id dw_mci_exynos_match[] = { .data = &exynos_drv_data, }, { .compatible = "samsung,exynos7-dw-mshc-smu", .data = &exynos_drv_data, }, + { .compatible = "samsung,exynos7870-dw-mshc", + .data = &exynos_drv_data, }, + { .compatible = "samsung,exynos7870-dw-mshc-smu", + .data = &exynos_drv_data, }, { .compatible = "axis,artpec8-dw-mshc", .data = &artpec_drv_data, }, {}, From 7597794706952db4adada29b2a6593251cddcd85 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 20 Feb 2025 11:46:54 -0500 Subject: [PATCH 07/27] dt-bindings: mmc: Change to additionalProperties to fix fail detect Unevaluated property mmc-controller.yaml is common schema file. According to writing-schema.rst, * additionalProperties: true Rare case, used for schemas implementing common set of properties. Such schemas are supposed to be referenced by other schemas, which then use 'unevaluatedProperties: false'. Typically bus or common-part schemas. Reproduce steps: 1. Add unevaluated property 'abc' at example of fsl-imx-esdhc.yaml 2. Run make dt_binding_check DT_SCHEMA_FILES=fsl-imx-esdhc.yaml No any warning report. But suppose report below warning: mmc@70004000: Unevaluated properties are not allowed ('abc' was unexpected) Signed-off-by: Frank Li Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250220164655.2081224-1-Frank.Li@nxp.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/mmc-controller.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml index 9d7a1298c455..26e4f0f8dc1c 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml +++ b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml @@ -24,7 +24,7 @@ properties: $nodename: pattern: "^mmc(@.*)?$" -unevaluatedProperties: true +additionalProperties: true examples: - | From e01578e0a437f0eddcf39f9fbd68103544058db8 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 6 Mar 2025 12:09:37 -0500 Subject: [PATCH 08/27] dt-bindings: mmc: fsl-imx-esdhc: Add i.MX94 support Add compatible string "fsl,imx94-usdhc" for the i.MX94 chip, which is backward compatible with i.MX8mm. Set it to fall back to "fsl,imx8mm-usdhc". Signed-off-by: Frank Li Acked-by: Conor Dooley Link: https://lore.kernel.org/r/20250306170937.242183-1-Frank.Li@nxp.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml index b9b999570529..b98a84f93277 100644 --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml @@ -57,6 +57,7 @@ properties: - fsl,imx8mp-usdhc - fsl,imx8ulp-usdhc - fsl,imx93-usdhc + - fsl,imx94-usdhc - fsl,imx95-usdhc - const: fsl,imx8mm-usdhc - items: From ec53e2ea6b86f28f491b10dcee00d6c7077065b4 Mon Sep 17 00:00:00 2001 From: Dharma Balasubiramani Date: Mon, 24 Feb 2025 08:22:27 +0530 Subject: [PATCH 09/27] dt-bindings: mmc: mmc-slot: Make compatible property optional The compatible property is required for some vendor-specific device trees, such as Amlogic's meson-mx-sdio, but is unnecessary for others, like Microchip's DTS. To resolve unintended warnings for configurations that do not require it, remove compatible from the required properties in mmc-slot.yaml. Since meson-mx-sdio still requires compatible, explicitly add it to its required list in amlogic,meson-mx-sdio.yaml. Signed-off-by: Dharma Balasubiramani Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250224-mmc-slot-v4-1-231620a31e88@microchip.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/amlogic,meson-mx-sdio.yaml | 3 +++ Documentation/devicetree/bindings/mmc/mmc-slot.yaml | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/amlogic,meson-mx-sdio.yaml b/Documentation/devicetree/bindings/mmc/amlogic,meson-mx-sdio.yaml index 022682a977c6..0d4d9ca6a8d9 100644 --- a/Documentation/devicetree/bindings/mmc/amlogic,meson-mx-sdio.yaml +++ b/Documentation/devicetree/bindings/mmc/amlogic,meson-mx-sdio.yaml @@ -60,6 +60,9 @@ patternProperties: bus-width: enum: [1, 4] + required: + - compatible + unevaluatedProperties: false required: diff --git a/Documentation/devicetree/bindings/mmc/mmc-slot.yaml b/Documentation/devicetree/bindings/mmc/mmc-slot.yaml index 1f0667828063..ca3d0114bfc6 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-slot.yaml +++ b/Documentation/devicetree/bindings/mmc/mmc-slot.yaml @@ -29,7 +29,6 @@ properties: maxItems: 1 required: - - compatible - reg unevaluatedProperties: false From c784b7617c9e0e31e363cb2d1ce961c122c25d21 Mon Sep 17 00:00:00 2001 From: Dharma Balasubiramani Date: Mon, 24 Feb 2025 08:22:28 +0530 Subject: [PATCH 10/27] dt-bindings: mmc: atmel,hsmci: Convert to json schema Convert atmel,hsmci documentation to yaml format. The new file will inherit from mmc-controller.yaml. Signed-off-by: Dharma Balasubiramani Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250224-mmc-slot-v4-2-231620a31e88@microchip.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/atmel,hsmci.yaml | 106 ++++++++++++++++++ .../devicetree/bindings/mmc/atmel-hsmci.txt | 73 ------------ 2 files changed, 106 insertions(+), 73 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/atmel,hsmci.yaml delete mode 100644 Documentation/devicetree/bindings/mmc/atmel-hsmci.txt diff --git a/Documentation/devicetree/bindings/mmc/atmel,hsmci.yaml b/Documentation/devicetree/bindings/mmc/atmel,hsmci.yaml new file mode 100644 index 000000000000..151b414b9d27 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/atmel,hsmci.yaml @@ -0,0 +1,106 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/atmel,hsmci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Atmel High-Speed MultiMedia Card Interface (HSMCI) + +description: + The Atmel HSMCI controller provides an interface for MMC, SD, and SDIO memory + cards. + +maintainers: + - Nicolas Ferre + - Aubin Constans + +allOf: + - $ref: mmc-controller.yaml + +properties: + compatible: + const: atmel,hsmci + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + dmas: + maxItems: 1 + + dma-names: + const: rxtx + + clocks: + maxItems: 1 + + clock-names: + const: mci_clk + + "#address-cells": + const: 1 + description: Used for slot IDs. + + "#size-cells": + const: 0 + +patternProperties: + "slot@[0-2]$": + $ref: mmc-slot.yaml + description: A slot node representing an MMC, SD, or SDIO slot. + + properties: + reg: + enum: [0, 1] + + required: + - reg + - bus-width + + unevaluatedProperties: false + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - "#address-cells" + - "#size-cells" + +anyOf: + - required: + - slot@0 + - required: + - slot@1 + +unevaluatedProperties: false + +examples: + - | + #include + #include + mmc@f0008000 { + compatible = "atmel,hsmci"; + reg = <0xf0008000 0x600>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mci0_clk>; + clock-names = "mci_clk"; + #address-cells = <1>; + #size-cells = <0>; + + slot@0 { + reg = <0>; + bus-width = <4>; + cd-gpios = <&pioD 15 0>; + cd-inverted; + }; + + slot@1 { + reg = <1>; + bus-width = <4>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt deleted file mode 100644 index 07ad02075a93..000000000000 --- a/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt +++ /dev/null @@ -1,73 +0,0 @@ -* Atmel High Speed MultiMedia Card Interface - -This controller on atmel products provides an interface for MMC, SD and SDIO -types of memory cards. - -This file documents differences between the core properties described -by mmc.txt and the properties used by the atmel-mci driver. - -1) MCI node - -Required properties: -- compatible: should be "atmel,hsmci" -- #address-cells: should be one. The cell is the slot id. -- #size-cells: should be zero. -- at least one slot node -- clock-names: tuple listing input clock names. - Required elements: "mci_clk" -- clocks: phandles to input clocks. - -The node contains child nodes for each slot that the platform uses - -Example MCI node: - -mmc0: mmc@f0008000 { - compatible = "atmel,hsmci"; - reg = <0xf0008000 0x600>; - interrupts = <12 4>; - #address-cells = <1>; - #size-cells = <0>; - clock-names = "mci_clk"; - clocks = <&mci0_clk>; - - [ child node definitions...] -}; - -2) slot nodes - -Required properties: -- reg: should contain the slot id. -- bus-width: number of data lines connected to the controller - -Optional properties: -- cd-gpios: specify GPIOs for card detection -- cd-inverted: invert the value of external card detect gpio line -- wp-gpios: specify GPIOs for write protection - -Example slot node: - -slot@0 { - reg = <0>; - bus-width = <4>; - cd-gpios = <&pioD 15 0> - cd-inverted; -}; - -Example full MCI node: -mmc0: mmc@f0008000 { - compatible = "atmel,hsmci"; - reg = <0xf0008000 0x600>; - interrupts = <12 4>; - #address-cells = <1>; - #size-cells = <0>; - slot@0 { - reg = <0>; - bus-width = <4>; - cd-gpios = <&pioD 15 0> - cd-inverted; - }; - slot@1 { - reg = <1>; - bus-width = <4>; - }; -}; From 3b791214c8bc1bc0eb3153a195c342b8a98f767b Mon Sep 17 00:00:00 2001 From: Dragan Simic Date: Wed, 26 Feb 2025 20:26:18 +0100 Subject: [PATCH 11/27] mmc: core: Trim trailing whitespace from card product names Product names for some eMMC chips can include trailing whitespace, which seems to be rather uncommon, but makes emitted messages and /sys properties somewhat unsightly. Here's such an example from a Pine64 PineNote, in which "Biwin ", as the eMMC product name, contains trailing whitespace: mmc0: new HS200 MMC card at address 0001 mmcblk0: mmc0:0001 Biwin 115 GiB mmcblk0: p1 p2 p3 p4 p5 p6 p7 mmcblk0boot0: mmc0:0001 Biwin 4.00 MiB mmcblk0boot1: mmc0:0001 Biwin 4.00 MiB mmcblk0rpmb: mmc0:0001 Biwin 4.00 MiB, chardev (249:0) Trailing whitespace in /sys properties may even cause some unforeseen issues with some scripts, so let's have the trailing whitespace trimmed in product names for eMMC chips. Although not observed yet by the author of these changes, the same trailing whitespace may appear in SD card product names, so let's trim them as well, which can't hurt. Touch-up one comment as well, by using proper capitalization. Signed-off-by: Dragan Simic Acked-by: Avri Altman Link: https://lore.kernel.org/r/fb7fcecae737f3e8b279854d7c853000527cba9a.1740597891.git.dsimic@manjaro.org Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc.c | 6 +++++- drivers/mmc/core/sd.c | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 6a23be214543..1522fd2b517d 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,7 @@ static int mmc_decode_cid(struct mmc_card *card) /* * The selection of the format here is based upon published - * specs from sandisk and from what people have reported. + * specs from SanDisk and from what people have reported. */ switch (card->csd.mmca_vsn) { case 0: /* MMC v1.0 - v1.2 */ @@ -109,6 +110,9 @@ static int mmc_decode_cid(struct mmc_card *card) return -EINVAL; } + /* some product names include trailing whitespace */ + strim(card->cid.prod_name); + return 0; } diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index cc757b850e79..8eba697d3d86 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,9 @@ void mmc_decode_cid(struct mmc_card *card) card->cid.month = unstuff_bits(resp, 8, 4); card->cid.year += 2000; /* SD cards year offset */ + + /* some product names may include trailing whitespace */ + strim(card->cid.prod_name); } /* From e50bbfe98251093c3d11c17d0b2b31e16340b6bf Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Thu, 27 Feb 2025 19:19:00 +0800 Subject: [PATCH 12/27] dt-bindings: mmc: Add support for rk3562 eMMC The eMMC core on Rockchip's RK3562 is the same as the one already included in RK3588. Extend the binding accordingly to allow compatible = "rockchip,rk3562-dwcmshc", "rockchip,rk3588-dwcmshc"; Signed-off-by: Kever Yang Acked-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250227111913.2344207-3-kever.yang@rock-chips.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml index c3d5e0230af1..2d5c9931f623 100644 --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml @@ -14,7 +14,9 @@ properties: compatible: oneOf: - items: - - const: rockchip,rk3576-dwcmshc + - enum: + - rockchip,rk3562-dwcmshc + - rockchip,rk3576-dwcmshc - const: rockchip,rk3588-dwcmshc - enum: - rockchip,rk3568-dwcmshc From ab5d7073adba76b2d91f7e557faa554bfb41275c Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Thu, 27 Feb 2025 19:19:01 +0800 Subject: [PATCH 13/27] dt-bindings: mmc: rockchip-dw-mshc: Add support for rk3562 The dw-mshc core on Rockchip's RK3562 is the same as the one already included in RK3288. Extend the binding accordingly to allow compatible = "rockchip,rk3562-dw-mshc", "rockchip,rk3288-dw-mshc"; Signed-off-by: Kever Yang Acked-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250227111913.2344207-4-kever.yang@rock-chips.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml index 06df1269f247..772f592291bf 100644 --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml @@ -38,6 +38,7 @@ properties: - rockchip,rk3328-dw-mshc - rockchip,rk3368-dw-mshc - rockchip,rk3399-dw-mshc + - rockchip,rk3562-dw-mshc - rockchip,rk3568-dw-mshc - rockchip,rk3588-dw-mshc - rockchip,rv1108-dw-mshc From 93745285ad9ba11ef68922787e0f46da408ab0b7 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 5 Mar 2025 09:29:51 +0000 Subject: [PATCH 14/27] dt-bindings: mmc: renesas,sdhi: Document RZ/G3E support The SD/MMC block on the RZ/G3E ("R9A09G047") SoC is similar to that of the RZ/V2H, but the SD0 channel has only dedicated pins, so we must use SD_STATUS register to control voltage and power enable (internal regulator), for non-fixed voltage (SD) MMC interface. However, it is optional for fixed voltage MMC interface (eMMC). For SD1 and SD2 channels, we can either use gpio regulator or internal regulator (using SD_STATUS register) for voltage switching. Document RZ/G3E SDHI IP support with optional internal regulator for both RZ/G3E and RZ/V2H SoC. Acked-by: Conor Dooley Reviewed-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20250305092958.21865-2-biju.das.jz@bp.renesas.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/renesas,sdhi.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml index af378b9ff3f4..773baa6c2656 100644 --- a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml +++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml @@ -68,6 +68,9 @@ properties: - renesas,sdhi-r9a08g045 # RZ/G3S - renesas,sdhi-r9a09g011 # RZ/V2M - const: renesas,rzg2l-sdhi + - items: + - const: renesas,sdhi-r9a09g047 # RZ/G3E + - const: renesas,sdhi-r9a09g057 # RZ/V2H(P) reg: maxItems: 1 @@ -211,6 +214,19 @@ allOf: sectioned off to be run by a separate second clock source to allow the main core clock to be turned off to save power. + - if: + properties: + compatible: + contains: + const: renesas,sdhi-r9a09g057 + then: + properties: + vqmmc-regulator: + type: object + description: VQMMC SD regulator + $ref: /schemas/regulator/regulator.yaml# + unevaluatedProperties: false + required: - compatible - reg From fae80a99dc0320be854aa789cbe7ed0e1e574c61 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 5 Mar 2025 09:29:52 +0000 Subject: [PATCH 15/27] mmc: renesas_sdhi: Add support for RZ/G3E SoC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SDHI/eMMC IPs in the RZ/G3E SoC are similar to those in R-Car Gen3. However, the RZ/G3E SD0 channel has Voltage level control and PWEN pin support via SD_STATUS register. internal regulator support is added to control the voltage levels of the SD pins via sd_iovs/sd_pwen bits in SD_STATUS register by populating vqmmc-regulator child node. SD1 and SD2 channels have gpio regulator support and internal regulator support. Selection of the regulator is based on the regulator phandle. Similar case for SD0 fixed voltage (eMMC) that uses fixed regulator and SD0 non-fixed voltage (SD0) that uses internal regulator. Reviewed-by: Wolfram Sang Signed-off-by: Biju Das Link: https://lore.kernel.org/r/20250305092958.21865-3-biju.das.jz@bp.renesas.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi.h | 1 + drivers/mmc/host/renesas_sdhi_core.c | 130 +++++++++++++++++++++++++++ drivers/mmc/host/tmio_mmc.h | 10 +++ 3 files changed, 141 insertions(+) diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index f12a87442338..291ddb4ad9be 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -95,6 +95,7 @@ struct renesas_sdhi { struct reset_control *rstc; struct tmio_mmc_host *host; + struct regulator_dev *rdev; }; #define host_to_priv(host) \ diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index f73b84bae0c4..396fa2816a15 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include #include @@ -581,12 +583,24 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host, bool preserve) if (!preserve) { if (priv->rstc) { + u32 sd_status; + /* + * HW reset might have toggled the regulator state in + * HW which regulator core might be unaware of so save + * and restore the regulator state during HW reset. + */ + if (priv->rdev) + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); + reset_control_reset(priv->rstc); /* Unknown why but without polling reset status, it will hang */ read_poll_timeout(reset_control_status, ret, ret == 0, 1, 100, false, priv->rstc); /* At least SDHI_VER_GEN2_SDR50 needs manual release of reset */ sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); + if (priv->rdev) + sd_ctrl_write32(host, CTL_SD_STATUS, sd_status); + priv->needs_adjust_hs400 = false; renesas_sdhi_set_clock(host, host->clk_cache); @@ -904,6 +918,102 @@ static void renesas_sdhi_enable_dma(struct tmio_mmc_host *host, bool enable) renesas_sdhi_sdbuf_width(host, enable ? width : 16); } +static const unsigned int renesas_sdhi_vqmmc_voltages[] = { + 3300000, 1800000 +}; + +static int renesas_sdhi_regulator_disable(struct regulator_dev *rdev) +{ + struct tmio_mmc_host *host = rdev_get_drvdata(rdev); + u32 sd_status; + + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); + sd_status &= ~SD_STATUS_PWEN; + sd_ctrl_write32(host, CTL_SD_STATUS, sd_status); + + return 0; +} + +static int renesas_sdhi_regulator_enable(struct regulator_dev *rdev) +{ + struct tmio_mmc_host *host = rdev_get_drvdata(rdev); + u32 sd_status; + + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); + sd_status |= SD_STATUS_PWEN; + sd_ctrl_write32(host, CTL_SD_STATUS, sd_status); + + return 0; +} + +static int renesas_sdhi_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct tmio_mmc_host *host = rdev_get_drvdata(rdev); + u32 sd_status; + + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); + + return (sd_status & SD_STATUS_PWEN) ? 1 : 0; +} + +static int renesas_sdhi_regulator_get_voltage(struct regulator_dev *rdev) +{ + struct tmio_mmc_host *host = rdev_get_drvdata(rdev); + u32 sd_status; + + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); + + return (sd_status & SD_STATUS_IOVS) ? 1800000 : 3300000; +} + +static int renesas_sdhi_regulator_set_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV, + unsigned int *selector) +{ + struct tmio_mmc_host *host = rdev_get_drvdata(rdev); + u32 sd_status; + + sd_status = sd_ctrl_read32(host, CTL_SD_STATUS); + if (min_uV >= 1700000 && max_uV <= 1950000) { + sd_status |= SD_STATUS_IOVS; + *selector = 1; + } else { + sd_status &= ~SD_STATUS_IOVS; + *selector = 0; + } + sd_ctrl_write32(host, CTL_SD_STATUS, sd_status); + + return 0; +} + +static int renesas_sdhi_regulator_list_voltage(struct regulator_dev *rdev, + unsigned int selector) +{ + if (selector >= ARRAY_SIZE(renesas_sdhi_vqmmc_voltages)) + return -EINVAL; + + return renesas_sdhi_vqmmc_voltages[selector]; +} + +static const struct regulator_ops renesas_sdhi_regulator_voltage_ops = { + .enable = renesas_sdhi_regulator_enable, + .disable = renesas_sdhi_regulator_disable, + .is_enabled = renesas_sdhi_regulator_is_enabled, + .list_voltage = renesas_sdhi_regulator_list_voltage, + .get_voltage = renesas_sdhi_regulator_get_voltage, + .set_voltage = renesas_sdhi_regulator_set_voltage, +}; + +static const struct regulator_desc renesas_sdhi_vqmmc_regulator = { + .name = "sdhi-vqmmc-regulator", + .of_match = of_match_ptr("vqmmc-regulator"), + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .ops = &renesas_sdhi_regulator_voltage_ops, + .volt_table = renesas_sdhi_vqmmc_voltages, + .n_voltages = ARRAY_SIZE(renesas_sdhi_vqmmc_voltages), +}; + int renesas_sdhi_probe(struct platform_device *pdev, const struct tmio_mmc_dma_ops *dma_ops, const struct renesas_sdhi_of_data *of_data, @@ -911,7 +1021,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, { struct tmio_mmc_data *mmd = pdev->dev.platform_data; struct tmio_mmc_data *mmc_data; + struct regulator_config rcfg = { .dev = &pdev->dev, }; + struct regulator_dev *rdev; struct renesas_sdhi_dma *dma_priv; + struct device *dev = &pdev->dev; struct tmio_mmc_host *host; struct renesas_sdhi *priv; int num_irqs, irq, ret, i; @@ -1053,6 +1166,23 @@ int renesas_sdhi_probe(struct platform_device *pdev, if (ret) goto efree; + rcfg.of_node = of_get_child_by_name(dev->of_node, "vqmmc-regulator"); + if (!of_device_is_available(rcfg.of_node)) { + of_node_put(rcfg.of_node); + rcfg.of_node = NULL; + } + + if (rcfg.of_node) { + rcfg.driver_data = priv->host; + rdev = devm_regulator_register(dev, &renesas_sdhi_vqmmc_regulator, &rcfg); + of_node_put(rcfg.of_node); + if (IS_ERR(rdev)) { + dev_err(dev, "regulator register failed err=%ld", PTR_ERR(rdev)); + goto efree; + } + priv->rdev = rdev; + } + ver = sd_ctrl_read16(host, CTL_VERSION); /* GEN2_SDR104 is first known SDHI to use 32bit block count */ if (ver < SDHI_VER_GEN2_SDR104 && mmc_data->max_blk_count > U16_MAX) diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index a75755f31d31..41787ea77a13 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -44,6 +44,7 @@ #define CTL_RESET_SD 0xe0 #define CTL_VERSION 0xe2 #define CTL_SDIF_MODE 0xe6 /* only known on R-Car 2+ */ +#define CTL_SD_STATUS 0xf2 /* only known on RZ/{G2L,G3E,V2H} */ /* Definitions for values the CTL_STOP_INTERNAL_ACTION register can take */ #define TMIO_STOP_STP BIT(0) @@ -103,6 +104,10 @@ /* Definitions for values the CTL_SDIF_MODE register can take */ #define SDIF_MODE_HS400 BIT(0) /* only known on R-Car 2+ */ +/* Definitions for values the CTL_SD_STATUS register can take */ +#define SD_STATUS_PWEN BIT(0) /* only known on RZ/{G3E,V2H} */ +#define SD_STATUS_IOVS BIT(16) /* only known on RZ/{G3E,V2H} */ + /* Define some IRQ masks */ /* This is the mask used at reset by the chip */ #define TMIO_MASK_ALL 0x837f031d @@ -226,6 +231,11 @@ static inline u32 sd_ctrl_read16_and_16_as_32(struct tmio_mmc_host *host, ioread16(host->ctl + ((addr + 2) << host->bus_shift)) << 16; } +static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) +{ + return ioread32(host->ctl + (addr << host->bus_shift)); +} + static inline void sd_ctrl_read32_rep(struct tmio_mmc_host *host, int addr, u32 *buf, int count) { From 8d83327918d974703e2b619513636535cd262039 Mon Sep 17 00:00:00 2001 From: Yao Zi Date: Sun, 9 Mar 2025 05:53:43 +0000 Subject: [PATCH 16/27] dt-bindings: mmc: rockchip-dw-mshc: Add compatible string for RK3528 Add RK3528 compatible string for SD/SDIO interface. Signed-off-by: Yao Zi Acked-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20250309055348.9299-2-ziyao@disroot.org Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml index 772f592291bf..bf273115235b 100644 --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml @@ -38,6 +38,7 @@ properties: - rockchip,rk3328-dw-mshc - rockchip,rk3368-dw-mshc - rockchip,rk3399-dw-mshc + - rockchip,rk3528-dw-mshc - rockchip,rk3562-dw-mshc - rockchip,rk3568-dw-mshc - rockchip,rk3588-dw-mshc From 75aaf6cc1a1ffcc87c17e4356578a659e9950962 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Wed, 5 Mar 2025 21:41:02 +0000 Subject: [PATCH 17/27] dt-bindings: mmc: sdhci-of-dwcmhsc: Add compatible string for RK3528 The SDHCI controller in Rockchip RK3528 is similar to the one included in RK3588. Add compatible string for the SDHCI controller in RK3528. Signed-off-by: Jonas Karlman Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20250305214108.1327208-2-jonas@kwiboo.se Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml index 2d5c9931f623..e6e604072d3c 100644 --- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml @@ -15,6 +15,7 @@ properties: oneOf: - items: - enum: + - rockchip,rk3528-dwcmshc - rockchip,rk3562-dwcmshc - rockchip,rk3576-dwcmshc - const: rockchip,rk3588-dwcmshc From 0f7a4a167aa6b715c69dcc6b41c07779c7f7319c Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 7 Mar 2025 00:56:58 +0000 Subject: [PATCH 18/27] dt-bindings: mmc: sunxi: Simplify compatible string listing New Allwinner SoCs only occasionally update their MMC IP, leading to many pairs of compatible strings, though there are sometimes a number of them being compatible with one particular SoC. Collate the compatible string listing in the binding, to group those being compatible together. This makes the list more readable, and allows for easier addition of new SoC's MMC devices. Signed-off-by: Andre Przywara Acked-by: Conor Dooley Link: https://lore.kernel.org/r/20250307005712.16828-2-andre.przywara@arm.com Signed-off-by: Ulf Hansson --- .../bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml index 0ccd632d5620..8e4c77b7e4ab 100644 --- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml +++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml @@ -30,38 +30,30 @@ properties: - const: allwinner,sun50i-a100-emmc - const: allwinner,sun50i-a100-mmc - items: - - const: allwinner,sun8i-a83t-mmc + - enum: + - allwinner,sun8i-a83t-mmc + - allwinner,suniv-f1c100s-mmc - const: allwinner,sun7i-a20-mmc - items: - - const: allwinner,sun8i-r40-emmc + - enum: + - allwinner,sun8i-r40-emmc + - allwinner,sun50i-h5-emmc + - allwinner,sun50i-h6-emmc - const: allwinner,sun50i-a64-emmc - items: - - const: allwinner,sun8i-r40-mmc + - enum: + - allwinner,sun8i-r40-mmc + - allwinner,sun50i-h5-mmc + - allwinner,sun50i-h6-mmc - const: allwinner,sun50i-a64-mmc - items: - - const: allwinner,sun50i-h5-emmc - - const: allwinner,sun50i-a64-emmc - - items: - - const: allwinner,sun50i-h5-mmc - - const: allwinner,sun50i-a64-mmc - - items: - - const: allwinner,sun50i-h6-emmc - - const: allwinner,sun50i-a64-emmc - - items: - - const: allwinner,sun50i-h6-mmc - - const: allwinner,sun50i-a64-mmc - - items: - - const: allwinner,sun20i-d1-emmc - - const: allwinner,sun50i-a100-emmc - - items: - - const: allwinner,sun50i-h616-emmc + - enum: + - allwinner,sun20i-d1-emmc + - allwinner,sun50i-h616-emmc - const: allwinner,sun50i-a100-emmc - items: - const: allwinner,sun50i-h616-mmc - const: allwinner,sun50i-a100-mmc - - items: - - const: allwinner,suniv-f1c100s-mmc - - const: allwinner,sun7i-a20-mmc reg: maxItems: 1 From 63ddfb9c3a1237b5ebf2feb541544d1b837af78f Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 7 Mar 2025 00:56:59 +0000 Subject: [PATCH 19/27] dt-bindings: mmc: sunxi: add compatible strings for Allwinner A523 The Allwinner A523 uses the same MMC IP as the D1. Introduce the new specific compatible strings, and use them with fallbacks to the D1 strings. Signed-off-by: Andre Przywara Acked-by: Conor Dooley Link: https://lore.kernel.org/r/20250307005712.16828-3-andre.przywara@arm.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml index 8e4c77b7e4ab..9f3b1edacaa0 100644 --- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml +++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml @@ -50,10 +50,14 @@ properties: - enum: - allwinner,sun20i-d1-emmc - allwinner,sun50i-h616-emmc + - allwinner,sun55i-a523-emmc - const: allwinner,sun50i-a100-emmc - items: - const: allwinner,sun50i-h616-mmc - const: allwinner,sun50i-a100-mmc + - items: + - const: allwinner,sun55i-a523-mmc + - const: allwinner,sun20i-d1-mmc reg: maxItems: 1 From 38e7047a4dac5be9599ac3679e971c73e7b61196 Mon Sep 17 00:00:00 2001 From: "Jiri Slaby (SUSE)" Date: Mon, 17 Mar 2025 08:00:32 +0100 Subject: [PATCH 20/27] tty: mmc: sdio: use bool for cts and remove parentheses 'cts' in sdio_uart_check_modem_status() is considered a 'bool', but typed as signed 'int'. Make it 'bool' so it is clear the code does not care about the masked value, but true/false. Signed-off-by: Jiri Slaby (SUSE) Link: https://lore.kernel.org/r/20250317070046.24386-18-jirislaby@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/core/sdio_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/sdio_uart.c b/drivers/mmc/core/sdio_uart.c index 6b7471dba3bf..7423a601e1e5 100644 --- a/drivers/mmc/core/sdio_uart.c +++ b/drivers/mmc/core/sdio_uart.c @@ -471,7 +471,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) port->icount.cts++; tty = tty_port_tty_get(&port->port); if (tty && C_CRTSCTS(tty)) { - int cts = (status & UART_MSR_CTS); + bool cts = status & UART_MSR_CTS; if (tty->hw_stopped) { if (cts) { tty->hw_stopped = false; From 49d162635151d0dd04935070d7cf67137ab863aa Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 12 Mar 2025 13:17:12 +0100 Subject: [PATCH 21/27] mmc: sdhci-omap: Disable MMC_CAP_AGGRESSIVE_PM for eMMC/SD We have received reports about cards can become corrupt related to the aggressive PM support. Let's make a partial revert of the change that enabled the feature. Reported-by: David Owens Reported-by: Romain Naour Reported-by: Robert Nelson Tested-by: Robert Nelson Fixes: 3edf588e7fe0 ("mmc: sdhci-omap: Allow SDIO card power off and enable aggressive PM") Cc: stable@vger.kernel.org Signed-off-by: Ulf Hansson Acked-by: Adrian Hunter Reviewed-by: Tony Lindgren Link: https://lore.kernel.org/r/20250312121712.1168007-1-ulf.hansson@linaro.org --- drivers/mmc/host/sdhci-omap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 54d795205fb4..26a9a8b5682a 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -1339,8 +1339,8 @@ static int sdhci_omap_probe(struct platform_device *pdev) /* R1B responses is required to properly manage HW busy detection. */ mmc->caps |= MMC_CAP_NEED_RSP_BUSY; - /* Allow card power off and runtime PM for eMMC/SD card devices */ - mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_AGGRESSIVE_PM; + /* Enable SDIO card power off. */ + mmc->caps |= MMC_CAP_POWER_OFF_CARD; ret = sdhci_setup_host(host); if (ret) From a41fcca4b342811b473bbaa4b44f1d34d87fcce6 Mon Sep 17 00:00:00 2001 From: Karel Balej Date: Mon, 10 Mar 2025 15:07:04 +0100 Subject: [PATCH 22/27] mmc: sdhci-pxav3: set NEED_RSP_BUSY capability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the MMC_CAP_NEED_RSP_BUSY capability for the sdhci-pxav3 host to prevent conversion of R1B responses to R1. Without this, the eMMC card in the samsung,coreprimevelte smartphone using the Marvell PXA1908 SoC with this mmc host doesn't probe with the ETIMEDOUT error originating in __mmc_poll_for_busy. Note that the other issues reported for this phone and host, namely floods of "Tuning failed, falling back to fixed sampling clock" dmesg messages for the eMMC and unstable SDIO are not mitigated by this change. Link: https://lore.kernel.org/r/20200310153340.5593-1-ulf.hansson@linaro.org/ Link: https://lore.kernel.org/r/D7204PWIGQGI.1FRFQPPIEE2P9@matfyz.cz/ Link: https://lore.kernel.org/r/20250115-pxa1908-lkml-v14-0-847d24f3665a@skole.hr/ Cc: stable@vger.kernel.org Signed-off-by: Karel Balej Acked-by: Adrian Hunter Tested-by: Duje Mihanović Link: https://lore.kernel.org/r/20250310140707.23459-1-balejk@matfyz.cz Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pxav3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 990723a008ae..3fb56face3d8 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -399,6 +399,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) if (!IS_ERR(pxa->clk_core)) clk_prepare_enable(pxa->clk_core); + host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY; /* enable 1/8V DDR capable */ host->mmc->caps |= MMC_CAP_1_8V_DDR; From ede057759b8363e2a0e6b1560ed6e131fbe443bd Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 14 Mar 2025 13:11:09 +0300 Subject: [PATCH 23/27] mmc: renesas_sdhi: fix error code in renesas_sdhi_probe() If devm_regulator_register() fails then propagate the error code. Don't return success. Fixes: fae80a99dc03 ("mmc: renesas_sdhi: Add support for RZ/G3E SoC") Signed-off-by: Dan Carpenter Reviewed-by: Biju Das Reviewed-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Link: https://lore.kernel.org/r/dc39e555-8ef7-4a39-9253-65bcf3e50c01@stanley.mountain Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 396fa2816a15..fa6526be3638 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -1178,6 +1178,7 @@ int renesas_sdhi_probe(struct platform_device *pdev, of_node_put(rcfg.of_node); if (IS_ERR(rdev)) { dev_err(dev, "regulator register failed err=%ld", PTR_ERR(rdev)); + ret = PTR_ERR(rdev); goto efree; } priv->rdev = rdev; From 4676741a3464b300b486e70585c3c9b692be1632 Mon Sep 17 00:00:00 2001 From: Luo Qiu Date: Mon, 17 Mar 2025 18:14:38 +0800 Subject: [PATCH 24/27] memstick: rtsx_usb_ms: Fix slab-use-after-free in rtsx_usb_ms_drv_remove This fixes the following crash: ================================================================== BUG: KASAN: slab-use-after-free in rtsx_usb_ms_poll_card+0x159/0x200 [rtsx_usb_ms] Read of size 8 at addr ffff888136335380 by task kworker/6:0/140241 CPU: 6 UID: 0 PID: 140241 Comm: kworker/6:0 Kdump: loaded Tainted: G E 6.14.0-rc6+ #1 Tainted: [E]=UNSIGNED_MODULE Hardware name: LENOVO 30FNA1V7CW/1057, BIOS S0EKT54A 07/01/2024 Workqueue: events rtsx_usb_ms_poll_card [rtsx_usb_ms] Call Trace: dump_stack_lvl+0x51/0x70 print_address_description.constprop.0+0x27/0x320 ? rtsx_usb_ms_poll_card+0x159/0x200 [rtsx_usb_ms] print_report+0x3e/0x70 kasan_report+0xab/0xe0 ? rtsx_usb_ms_poll_card+0x159/0x200 [rtsx_usb_ms] rtsx_usb_ms_poll_card+0x159/0x200 [rtsx_usb_ms] ? __pfx_rtsx_usb_ms_poll_card+0x10/0x10 [rtsx_usb_ms] ? __pfx___schedule+0x10/0x10 ? kick_pool+0x3b/0x270 process_one_work+0x357/0x660 worker_thread+0x390/0x4c0 ? __pfx_worker_thread+0x10/0x10 kthread+0x190/0x1d0 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x2d/0x50 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30 Allocated by task 161446: kasan_save_stack+0x20/0x40 kasan_save_track+0x10/0x30 __kasan_kmalloc+0x7b/0x90 __kmalloc_noprof+0x1a7/0x470 memstick_alloc_host+0x1f/0xe0 [memstick] rtsx_usb_ms_drv_probe+0x47/0x320 [rtsx_usb_ms] platform_probe+0x60/0xe0 call_driver_probe+0x35/0x120 really_probe+0x123/0x410 __driver_probe_device+0xc7/0x1e0 driver_probe_device+0x49/0xf0 __device_attach_driver+0xc6/0x160 bus_for_each_drv+0xe4/0x160 __device_attach+0x13a/0x2b0 bus_probe_device+0xbd/0xd0 device_add+0x4a5/0x760 platform_device_add+0x189/0x370 mfd_add_device+0x587/0x5e0 mfd_add_devices+0xb1/0x130 rtsx_usb_probe+0x28e/0x2e0 [rtsx_usb] usb_probe_interface+0x15c/0x460 call_driver_probe+0x35/0x120 really_probe+0x123/0x410 __driver_probe_device+0xc7/0x1e0 driver_probe_device+0x49/0xf0 __device_attach_driver+0xc6/0x160 bus_for_each_drv+0xe4/0x160 __device_attach+0x13a/0x2b0 rebind_marked_interfaces.isra.0+0xcc/0x110 usb_reset_device+0x352/0x410 usbdev_do_ioctl+0xe5c/0x1860 usbdev_ioctl+0xa/0x20 __x64_sys_ioctl+0xc5/0xf0 do_syscall_64+0x59/0x170 entry_SYSCALL_64_after_hwframe+0x76/0x7e Freed by task 161506: kasan_save_stack+0x20/0x40 kasan_save_track+0x10/0x30 kasan_save_free_info+0x36/0x60 __kasan_slab_free+0x34/0x50 kfree+0x1fd/0x3b0 device_release+0x56/0xf0 kobject_cleanup+0x73/0x1c0 rtsx_usb_ms_drv_remove+0x13d/0x220 [rtsx_usb_ms] platform_remove+0x2f/0x50 device_release_driver_internal+0x24b/0x2e0 bus_remove_device+0x124/0x1d0 device_del+0x239/0x530 platform_device_del.part.0+0x19/0xe0 platform_device_unregister+0x1c/0x40 mfd_remove_devices_fn+0x167/0x170 device_for_each_child_reverse+0xc9/0x130 mfd_remove_devices+0x6e/0xa0 rtsx_usb_disconnect+0x2e/0xd0 [rtsx_usb] usb_unbind_interface+0xf3/0x3f0 device_release_driver_internal+0x24b/0x2e0 proc_disconnect_claim+0x13d/0x220 usbdev_do_ioctl+0xb5e/0x1860 usbdev_ioctl+0xa/0x20 __x64_sys_ioctl+0xc5/0xf0 do_syscall_64+0x59/0x170 entry_SYSCALL_64_after_hwframe+0x76/0x7e Last potentially related work creation: kasan_save_stack+0x20/0x40 kasan_record_aux_stack+0x85/0x90 insert_work+0x29/0x100 __queue_work+0x34a/0x540 call_timer_fn+0x2a/0x160 expire_timers+0x5f/0x1f0 __run_timer_base.part.0+0x1b6/0x1e0 run_timer_softirq+0x8b/0xe0 handle_softirqs+0xf9/0x360 __irq_exit_rcu+0x114/0x130 sysvec_apic_timer_interrupt+0x72/0x90 asm_sysvec_apic_timer_interrupt+0x16/0x20 Second to last potentially related work creation: kasan_save_stack+0x20/0x40 kasan_record_aux_stack+0x85/0x90 insert_work+0x29/0x100 __queue_work+0x34a/0x540 call_timer_fn+0x2a/0x160 expire_timers+0x5f/0x1f0 __run_timer_base.part.0+0x1b6/0x1e0 run_timer_softirq+0x8b/0xe0 handle_softirqs+0xf9/0x360 __irq_exit_rcu+0x114/0x130 sysvec_apic_timer_interrupt+0x72/0x90 asm_sysvec_apic_timer_interrupt+0x16/0x20 The buggy address belongs to the object at ffff888136335000 which belongs to the cache kmalloc-2k of size 2048 The buggy address is located 896 bytes inside of freed 2048-byte region [ffff888136335000, ffff888136335800) The buggy address belongs to the physical page: page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x136330 head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 flags: 0x17ffffc0000040(head|node=0|zone=2|lastcpupid=0x1fffff) page_type: f5(slab) raw: 0017ffffc0000040 ffff888100042f00 ffffea000417a000 dead000000000002 raw: 0000000000000000 0000000000080008 00000000f5000000 0000000000000000 head: 0017ffffc0000040 ffff888100042f00 ffffea000417a000 dead000000000002 head: 0000000000000000 0000000000080008 00000000f5000000 0000000000000000 head: 0017ffffc0000003 ffffea0004d8cc01 ffffffffffffffff 0000000000000000 head: 0000000000000008 0000000000000000 00000000ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff888136335280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff888136335300: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >ffff888136335380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff888136335400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff888136335480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ================================================================== Fixes: 6827ca573c03 ("memstick: rtsx_usb_ms: Support runtime power management") Signed-off-by: Luo Qiu Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/4B7BC3E6E291E6F2+20250317101438.25650-1-luoqiu@kylinsec.com.cn Signed-off-by: Ulf Hansson --- drivers/memstick/host/rtsx_usb_ms.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c index 6eb892fd4d34..3878136227e4 100644 --- a/drivers/memstick/host/rtsx_usb_ms.c +++ b/drivers/memstick/host/rtsx_usb_ms.c @@ -813,6 +813,7 @@ static void rtsx_usb_ms_drv_remove(struct platform_device *pdev) host->eject = true; cancel_work_sync(&host->handle_req); + cancel_delayed_work_sync(&host->poll_card); mutex_lock(&host->host_mutex); if (host->req) { From 3834a759afb817e23a7a2f09c2c9911b0ce5c588 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Tue, 18 Mar 2025 22:02:25 +0800 Subject: [PATCH 25/27] mmc: omap: Fix memory leak in mmc_omap_new_slot Add err_free_host label to properly pair mmc_alloc_host() with mmc_free_host() in GPIO error paths. The allocated host memory was leaked when GPIO lookups failed. Fixes: e519f0bb64ef ("ARM/mmc: Convert old mmci-omap to GPIO descriptors") Signed-off-by: Miaoqian Lin Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250318140226.19650-1-linmq006@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/omap.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 62252ad4e20d..3cdb2fc44965 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1272,19 +1272,25 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id) /* Check for some optional GPIO controls */ slot->vsd = devm_gpiod_get_index_optional(host->dev, "vsd", id, GPIOD_OUT_LOW); - if (IS_ERR(slot->vsd)) - return dev_err_probe(host->dev, PTR_ERR(slot->vsd), + if (IS_ERR(slot->vsd)) { + r = dev_err_probe(host->dev, PTR_ERR(slot->vsd), "error looking up VSD GPIO\n"); + goto err_free_host; + } slot->vio = devm_gpiod_get_index_optional(host->dev, "vio", id, GPIOD_OUT_LOW); - if (IS_ERR(slot->vio)) - return dev_err_probe(host->dev, PTR_ERR(slot->vio), + if (IS_ERR(slot->vio)) { + r = dev_err_probe(host->dev, PTR_ERR(slot->vio), "error looking up VIO GPIO\n"); + goto err_free_host; + } slot->cover = devm_gpiod_get_index_optional(host->dev, "cover", id, GPIOD_IN); - if (IS_ERR(slot->cover)) - return dev_err_probe(host->dev, PTR_ERR(slot->cover), + if (IS_ERR(slot->cover)) { + r = dev_err_probe(host->dev, PTR_ERR(slot->cover), "error looking up cover switch GPIO\n"); + goto err_free_host; + } host->slots[id] = slot; @@ -1344,6 +1350,7 @@ err_remove_slot_name: device_remove_file(&mmc->class_dev, &dev_attr_slot_name); err_remove_host: mmc_remove_host(mmc); +err_free_host: mmc_free_host(mmc); return r; } From 31e75ed964582257f59156ce6a42860e1ae4cc39 Mon Sep 17 00:00:00 2001 From: Erick Shepherd Date: Fri, 14 Mar 2025 14:50:21 -0500 Subject: [PATCH 26/27] mmc: host: Wait for Vdd to settle on card power off The SD spec version 6.0 section 6.4.1.5 requires that Vdd must be lowered to less than 0.5V for a minimum of 1 ms when powering off a card. Increase wait to 15 ms so that voltage has time to drain down to 0.5V and cards can power off correctly. Issues with voltage drain time were only observed on Apollo Lake and Bay Trail host controllers so this fix is limited to those devices. Signed-off-by: Erick Shepherd Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20250314195021.1588090-1-erick.shepherd@ni.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 1f0bd723f011..13a84b9309e0 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -610,8 +610,12 @@ static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode, sdhci_set_power(host, mode, vdd); - if (mode == MMC_POWER_OFF) + if (mode == MMC_POWER_OFF) { + if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD || + slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BYT_SD) + usleep_range(15000, 17500); return; + } /* * Bus power might not enable after D3 -> D0 transition due to the From c48e13e83513bd7eb4efffeeb562df9e4e1452d0 Mon Sep 17 00:00:00 2001 From: Avri Altman Date: Wed, 19 Mar 2025 22:36:42 +0200 Subject: [PATCH 27/27] mmc: core: Remove redundant null check This change removes a redundant null check found by Smatch. Fixes: 403a0293f1c2 ("mmc: core: Add open-ended Ext memory addressing") Reported-by: Dan Carpenter Closes: https://lore.kernel.org/linux-mmc/345be6cd-f2f3-472e-a897-ca4b7c4cf826@stanley.mountain/ Signed-off-by: Avri Altman Link: https://lore.kernel.org/r/20250319203642.778016-1-avri.altman@sandisk.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5241528f8b90..ce08e0ea7fc1 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -335,7 +335,7 @@ int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { int err; - if (mrq->cmd && mrq->cmd->has_ext_addr) + if (mrq->cmd->has_ext_addr) mmc_send_ext_addr(host, mrq->cmd->ext_addr); init_completion(&mrq->cmd_completion);