From 3e0483e93a8be320f70a1ff68d835f7f015af311 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Thu, 9 Apr 2026 15:48:11 +0800 Subject: mmc: core: Add validation for host-provided max_segs The max_segs field is of type unsigned short, and if a host driver sets an excessively large value, it may be truncated to zero. This can cause mmc_alloc_sg() to call kmalloc_objs() with a zero size allocation request, which leads to undefined behavior. Under the SLUB allocator, kmalloc(0) returns a special pointer (ZERO_SIZE_PTR). The subsequent 'if (sg)' check will evaluate to true, and sg_init_table() will then attempt to access invalid memory, resulting in a crash: dwmmc_rockchip 2a310000.mmc: Successfully tuned phase to 133 mmc1: new UHS-I speed SDR104 SDHC card at address aaaa Unable to handle kernel paging request at virtual address 0000001ffffffff0 Mem abort info: ESR = 0x0000000096000004 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x04: level 0 translation fault Data abort info: ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000 CM = 0, WnR = 0, TnD = 0, TagAccess = 0 GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 user pgtable: 4k pages, 48-bit VAs, pgdp=0000000102c88000 [0000001ffffffff0] pgd=0000000000000000, p4d=0000000000000000 Internal error: Oops: 0000000096000004 [#1] SMP Modules linked in: CPU: 2 UID: 0 PID: 102 Comm: kworker/2:1 Not tainted 7.0.0-rc6-next-20260331-00013-g4d93c25963c5-dirty #80 PREEMPT Hardware name: Rockchip RK3576 EVB V10 Board (DT) Workqueue: events_freezable mmc_rescan pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : sg_init_table+0x2c/0x50 lr : sg_init_table+0x24/0x50 sp : ffff8000837db710 x29: ffff8000837db710 x28: 000000000000c000 x27: 0000000000000300 x26: 0000000000000000 x25: 0000000000000040 x24: ffff0000c46a0000 x23: 0000000000000000 x22: ffff0000c0c73c00 x21: 0000000000000010 x20: 0000000000000010 x19: 0000000000000000 x18: 000000000000002c x17: 0000000000000000 x16: 0000000000000001 x15: 0000000000000000 x14: 0000000000000400 x13: ffff8000837dc000 x12: 0000000000000000 x11: ffff0000c0c73ca0 x10: 0000000000000040 x9 : 459ec1f0abbdbb00 x8 : 0000001fffffffe0 x7 : 0000000000000000 x6 : 000000000000003f x5 : 0000000000035579 x4 : 0000000000000901 x3 : 0000000000000000 x2 : 0000000000000000 x1 : 0000000000000000 x0 : 0000000000000010 Call trace: sg_init_table+0x2c/0x50 (P) mmc_mq_init_request+0x64/0x90 blk_mq_alloc_map_and_rqs+0x3ac/0x480 blk_mq_alloc_set_map_and_rqs+0x98/0x1e0 blk_mq_alloc_tag_set+0x1c0/0x290 mmc_init_queue+0x120/0x370 mmc_blk_alloc_req+0x150/0x420 To prevent this, add a validation check in mmc_mq_init_request() to detect when sg_len (derived from max_segs) is zero. If sg_len is zero, we return an error and print an error message, allowing host driver developers to identify and fix incorrect max_segs configuration. This is a defensive measure that ensures the MMC core fails gracefully when host drivers provide invalid max_segs values, rather than crashing with a page fault. Signed-off-by: Shawn Lin Signed-off-by: Ulf Hansson --- drivers/mmc/core/queue.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 39fcb662c43f..c9028e4a7e56 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -214,8 +214,14 @@ static int mmc_mq_init_request(struct blk_mq_tag_set *set, struct request *req, struct mmc_queue *mq = set->driver_data; struct mmc_card *card = mq->card; struct mmc_host *host = card->host; + u16 sg_len = mmc_get_max_segments(host); - mq_rq->sg = mmc_alloc_sg(mmc_get_max_segments(host), GFP_KERNEL); + if (!sg_len) { + dev_err(mmc_dev(host), "Wrong max_segs assigned\n"); + return -EINVAL; + } + + mq_rq->sg = mmc_alloc_sg(sg_len, GFP_KERNEL); if (!mq_rq->sg) return -ENOMEM; -- cgit v1.2.3 From 915b559f7aca7612ab943f7905011e3e1bd131a2 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Thu, 9 Apr 2026 15:48:12 +0800 Subject: mmc: dw_mmc: Move misplaced comment It was originally part of the @cmd_status field description but became separated and now appears between @ring_size and @dms without proper context. Signed-off-by: Shawn Lin Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 42e58be74ce0..14fb2b309c7c 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -78,8 +78,8 @@ struct dw_mci_dma_slave { * @sg_cpu: Virtual address of DMA buffer. * @dma_ops: Pointer to DMA callbacks. * @cmd_status: Snapshot of SR taken upon completion of the current - * @ring_size: Buffer size for idma descriptors. * command. Only valid when EVENT_CMD_COMPLETE is pending. + * @ring_size: Buffer size for idma descriptors. * @dms: structure of slave-dma private data. * @phy_regs: physical address of controller's register map * @data_status: Snapshot of SR taken upon completion of the current -- cgit v1.2.3 From 4bac6b89e3cc8bd728aa40c3879e31ff85b8217e Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Wed, 15 Apr 2026 20:32:08 +0530 Subject: mmc: dw_mmc: implement option for configuring DMA threshold Some controllers, such as certain Exynos SDIO ones, are unable to perform DMA transfers of small amount of bytes properly. Following the device tree schema, implement the property to define the DMA transfer threshold (from a hard coded value of 16 bytes) so that lesser number of bytes can be transferred safely skipping DMA in such controllers. The value of 16 bytes stays as the default for controllers which do not define it. This value can be overridden by implementation-specific init sequences. Signed-off-by: Kaustabh Chakraborty Reviewed-by: Shawn Lin Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.c | 4 ++-- drivers/mmc/host/dw_mmc.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 20193ee7b73e..3b4157f34d11 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -40,7 +40,6 @@ SDMMC_INT_RESP_ERR | SDMMC_INT_HLE) #define DW_MCI_ERROR_FLAGS (DW_MCI_DATA_ERROR_FLAGS | \ DW_MCI_CMD_ERROR_FLAGS) -#define DW_MCI_DMA_THRESHOLD 16 #define DW_MCI_FREQ_MAX 200000000 /* unit: HZ */ #define DW_MCI_FREQ_MIN 100000 /* unit: HZ */ @@ -821,7 +820,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host, * non-word-aligned buffers or lengths. Also, we don't bother * with all the DMA setup overhead for short transfers. */ - if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD) + if (data->blocks * data->blksz < host->dma_threshold) return -EINVAL; if (data->blksz & 3) @@ -3185,6 +3184,7 @@ struct dw_mci *dw_mci_alloc_host(struct device *dev) host = mmc_priv(mmc); host->mmc = mmc; host->dev = dev; + host->dma_threshold = 16; return host; } diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 14fb2b309c7c..2ce8585e2c1e 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -107,6 +107,7 @@ struct dw_mci_dma_slave { * @ciu_clk: Pointer to card interface unit clock instance. * @fifo_depth: depth of FIFO. * @data_addr_override: override fifo reg offset with this value. + * @dma_threshold: data threshold value in bytes to carry out a DMA transfer. * @wm_aligned: force fifo watermark equal with data length in PIO mode. * Set as true if alignment is needed. * @data_shift: log2 of FIFO item size. @@ -163,6 +164,7 @@ struct dw_mci { void __iomem *regs; void __iomem *fifo_reg; u32 data_addr_override; + u32 dma_threshold; bool wm_aligned; struct scatterlist *sg; -- cgit v1.2.3 From 65c132fa8c93a75b27860c3f03593937d8dc2c41 Mon Sep 17 00:00:00 2001 From: Kaustabh Chakraborty Date: Wed, 15 Apr 2026 20:32:09 +0530 Subject: mmc: dw_mmc: exynos: increase DMA threshold value for exynos7870 Exynos 7870 compatible controllers, such as SDIO ones are not able to perform DMA transfers for small sizes of data (~16 to ~512 bytes), resulting in cache issues in subsequent transfers. Increase the DMA transfer threshold to 512 to allow the shorter transfers to take place, bypassing DMA. Signed-off-by: Kaustabh Chakraborty Reviewed-by: Shawn Lin Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc-exynos.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 261344d3a8cf..4b76b997ddc1 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -141,6 +141,7 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) priv->ctrl_type == DW_MCI_TYPE_EXYNOS7870_SMU) { /* Quirk needed for certain Exynos SoCs */ host->quirks |= DW_MMC_QUIRK_FIFO64_32; + host->dma_threshold = 512; } if (priv->ctrl_type == DW_MCI_TYPE_ARTPEC8) { -- cgit v1.2.3 From eb0ff5d010cf451deb810f9628396d43ad119147 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 4 May 2026 16:43:23 +0200 Subject: dt-bindings: mmc: renesas,sdhi: Document R-Car M3Le support Document support for the SD Card/MMC Interface in the Renesas R-Car M3Le (R8A779MD) SoC. Signed-off-by: Marek Vasut Acked-by: Conor Dooley Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml index 64fac0d11329..4d66966ce290 100644 --- a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml +++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml @@ -52,6 +52,7 @@ properties: - renesas,sdhi-r8a77980 # R-Car V3H - renesas,sdhi-r8a77990 # R-Car E3 - renesas,sdhi-r8a77995 # R-Car D3 + - renesas,sdhi-r8a779md # R-Car M3Le - const: renesas,rcar-gen3-sdhi # R-Car Gen3 or RZ/G2 - items: - enum: -- cgit v1.2.3 From 2c7210ded06da18b439b3a08b8a3caa42f2f1f72 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 4 May 2026 16:43:24 +0200 Subject: mmc: renesas_sdhi: add R-Car M3Le compatibility string Add support for the SD Card/MMC Interface in the Renesas R-Car M3Le (R8A779MD) SoC. R19UH0260EJ0100 Rev.1.00 , Dec 25, 2025 Notes 7.70. indicates that HS400 mode is not supported. Signed-off-by: Marek Vasut Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index f6ebb7bc7ede..b716a518f265 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -285,6 +285,7 @@ static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = { { .compatible = "renesas,sdhi-r8a77970", .data = &of_r8a77970_compatible, }, { .compatible = "renesas,sdhi-r8a77990", .data = &of_r8a77990_compatible, }, { .compatible = "renesas,sdhi-r8a77995", .data = &of_rcar_gen3_nohs400_compatible, }, + { .compatible = "renesas,sdhi-r8a779md", .data = &of_rcar_gen3_nohs400_compatible, }, { .compatible = "renesas,sdhi-r9a09g011", .data = &of_rzg2l_compatible, }, { .compatible = "renesas,sdhi-r9a09g057", .data = &of_rzg2l_compatible, }, { .compatible = "renesas,rzg2l-sdhi", .data = &of_rzg2l_compatible, }, -- cgit v1.2.3 From 4a3e92e8cfb9741cb687b14fc6ca81714b4c2c26 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 5 May 2026 12:33:24 +0200 Subject: mmc: host: Move MODULE_DEVICE_TABLE next to the table itself By convention MODULE_DEVICE_TABLE() immediately follows the ID table it exports, because this is easier to read and verify. It also makes more sense since #ifdef for ACPI or OF could hide both of them. Most of the privers already have this correctly placed, so adjust the missing ones. No functional impact. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Ulf Hansson --- drivers/mmc/host/cavium-thunderx.c | 2 +- drivers/mmc/host/tifm_sd.c | 2 +- drivers/mmc/host/wmt-sdmmc.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/cavium-thunderx.c b/drivers/mmc/host/cavium-thunderx.c index 1373deb3f531..84ff6d82ae3c 100644 --- a/drivers/mmc/host/cavium-thunderx.c +++ b/drivers/mmc/host/cavium-thunderx.c @@ -188,6 +188,7 @@ static const struct pci_device_id thunder_mmc_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa010) }, { 0, } /* end of table */ }; +MODULE_DEVICE_TABLE(pci, thunder_mmc_id_table); static struct pci_driver thunder_mmc_driver = { .name = KBUILD_MODNAME, @@ -201,4 +202,3 @@ module_pci_driver(thunder_mmc_driver); MODULE_AUTHOR("Cavium Inc."); MODULE_DESCRIPTION("Cavium ThunderX eMMC Driver"); MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, thunder_mmc_id_table); diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index c1f7d5b37911..aebffd3ebf60 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c @@ -1044,6 +1044,7 @@ static int tifm_sd_resume(struct tifm_dev *sock) static struct tifm_device_id tifm_sd_id_tbl[] = { { TIFM_TYPE_SD }, { } }; +MODULE_DEVICE_TABLE(tifm, tifm_sd_id_tbl); static struct tifm_driver tifm_sd_driver = { .driver = { @@ -1070,7 +1071,6 @@ static void __exit tifm_sd_exit(void) MODULE_AUTHOR("Alex Dubov"); MODULE_DESCRIPTION("TI FlashMedia SD driver"); MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(tifm, tifm_sd_id_tbl); MODULE_VERSION(DRIVER_VERSION); module_init(tifm_sd_init); diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index 1b1d691e19fc..489daee4f4fc 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c @@ -744,6 +744,7 @@ static const struct of_device_id wmt_mci_dt_ids[] = { { .compatible = "wm,wm8505-sdhc", .data = &wm8505_caps }, { /* Sentinel */ }, }; +MODULE_DEVICE_TABLE(of, wmt_mci_dt_ids); static int wmt_mci_probe(struct platform_device *pdev) { @@ -980,4 +981,3 @@ module_platform_driver(wmt_mci_driver); MODULE_DESCRIPTION("Wondermedia MMC/SD Driver"); MODULE_AUTHOR("Tony Prisk"); MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(of, wmt_mci_dt_ids); -- cgit v1.2.3 From 5808ef063b5e9342cb223bb9d07a6d5f6ac8711d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 5 May 2026 12:39:28 +0200 Subject: memstick: Constify the driver id_table Just like all other driver structures, the id_table should never be modified by core subsystem parts. Constify this member and actual data structures for increased code safety. Signed-off-by: Krzysztof Kozlowski Acked-by: Greg Kroah-Hartman Signed-off-by: Ulf Hansson --- drivers/memstick/host/tifm_ms.c | 2 +- drivers/misc/tifm_core.c | 4 ++-- drivers/mmc/host/tifm_sd.c | 2 +- include/linux/tifm.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index 0b6a90661eee..0a54586aa54e 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c @@ -647,7 +647,7 @@ static int tifm_ms_resume(struct tifm_dev *sock) #endif /* CONFIG_PM */ -static struct tifm_device_id tifm_ms_id_tbl[] = { +static const struct tifm_device_id tifm_ms_id_tbl[] = { { TIFM_TYPE_MS }, { 0 } }; diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index da0827724a61..aac8f0933e43 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -31,7 +31,7 @@ static const char *tifm_media_type_name(unsigned char type, unsigned char nt) return card_type_name[nt][type - 1]; } -static int tifm_dev_match(struct tifm_dev *sock, struct tifm_device_id *id) +static int tifm_dev_match(struct tifm_dev *sock, const struct tifm_device_id *id) { if (sock->type == id->type) return 1; @@ -43,7 +43,7 @@ static int tifm_bus_match(struct device *dev, const struct device_driver *drv) struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); const struct tifm_driver *fm_drv = container_of_const(drv, struct tifm_driver, driver); - struct tifm_device_id *ids = fm_drv->id_table; + const struct tifm_device_id *ids = fm_drv->id_table; if (ids) { while (ids->type) { diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index aebffd3ebf60..28ab2526dab1 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c @@ -1041,7 +1041,7 @@ static int tifm_sd_resume(struct tifm_dev *sock) #endif /* CONFIG_PM */ -static struct tifm_device_id tifm_sd_id_tbl[] = { +static const struct tifm_device_id tifm_sd_id_tbl[] = { { TIFM_TYPE_SD }, { } }; MODULE_DEVICE_TABLE(tifm, tifm_sd_id_tbl); diff --git a/include/linux/tifm.h b/include/linux/tifm.h index 44073d06710f..752fcfae27fe 100644 --- a/include/linux/tifm.h +++ b/include/linux/tifm.h @@ -97,7 +97,7 @@ struct tifm_dev { }; struct tifm_driver { - struct tifm_device_id *id_table; + const struct tifm_device_id *id_table; int (*probe)(struct tifm_dev *dev); void (*remove)(struct tifm_dev *dev); int (*suspend)(struct tifm_dev *dev, -- cgit v1.2.3 From 4f28846aaf8db9668e338b8987973f8935edff34 Mon Sep 17 00:00:00 2001 From: Stepan Ionichev Date: Thu, 7 May 2026 00:05:37 +0500 Subject: mmc: davinci: avoid NULL deref of host->data in IRQ handler mmc_davinci_irq() returns early only when both host->cmd and host->data are NULL: if (host->cmd == NULL && host->data == NULL) { ... return IRQ_NONE; } So we may legitimately reach the rest of the handler with host->data == NULL (and therefore data == NULL). The DATDNE branch already guards against this with an explicit "if (data != NULL)" check, but the subsequent TOUTRD ("read data timeout") and CRCWR/CRCRD ("data CRC error") branches dereference data unconditionally: if (qstatus & MMCST0_TOUTRD) { data->error = -ETIMEDOUT; <-- NULL deref ... davinci_abort_data(host, data); } if (qstatus & (MMCST0_CRCWR | MMCST0_CRCRD)) { data->error = -EILSEQ; <-- NULL deref ... } If either bit is set in qstatus while host->data is NULL, the kernel will crash inside the IRQ handler. smatch flags this: drivers/mmc/host/davinci_mmc.c:933 mmc_davinci_irq() error: we previously assumed 'data' could be null (see line 914) Gate both branches on a non-NULL data, matching the existing pattern used by the DATDNE branch. No functional change for callers where data is non-NULL, which is the only case in which these branches did meaningful work before this change. Signed-off-by: Stepan Ionichev Reviewed-by: Bartosz Golaszewski Signed-off-by: Ulf Hansson --- drivers/mmc/host/davinci_mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 42b0118a45a8..42ad87aa48f5 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -928,7 +928,7 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) } } - if (qstatus & MMCST0_TOUTRD) { + if (data && (qstatus & MMCST0_TOUTRD)) { /* Read data timeout */ data->error = -ETIMEDOUT; end_transfer = 1; @@ -940,7 +940,7 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) davinci_abort_data(host, data); } - if (qstatus & (MMCST0_CRCWR | MMCST0_CRCRD)) { + if (data && (qstatus & (MMCST0_CRCWR | MMCST0_CRCRD))) { /* Data CRC error */ data->error = -EILSEQ; end_transfer = 1; -- cgit v1.2.3 From d11f110c4ad2d431f4440baba9afb5b8e4190977 Mon Sep 17 00:00:00 2001 From: "Uwe Kleine-König (The Capable Hub)" Date: Thu, 7 May 2026 18:10:07 +0200 Subject: mmc: via-sdmmc: Simplify initialisation of pci_device_id array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of assigning the pci_device_id members using a list (which is hard to read as you need to look at the order of the members in that struct in parallel) use the PCI_VDEVICE() convenience macro to compact the initialisation while improving readability. Also drop trailing zeros that the compiler will care about then. The change doesn't introduce binary changes to the compiled driver, verified on both ARCH=x86 and ARCH=arm64. Signed-off-by: Uwe Kleine-König (The Capable Hub) Signed-off-by: Ulf Hansson --- drivers/mmc/host/via-sdmmc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index c628b3bbfd7a..8c049f8355cd 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -323,9 +323,8 @@ struct via_crdr_mmc_host { #define VIA_CMD_TIMEOUT_MS 1000 static const struct pci_device_id via_ids[] = { - {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_9530, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, - {0,} + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_9530) }, + { } }; MODULE_DEVICE_TABLE(pci, via_ids); -- cgit v1.2.3 From 04a8ddc39e5cfebffb06f383350a6ee393ba89a6 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 11 May 2026 10:53:56 +0200 Subject: dt-bindings: mmc: spacemit,sdhci: add pinctrl support for voltage switching Document pinctrl properties to support voltage-dependent pin configuration switching for UHS-I SD card modes. Add optional pinctrl-names property with two states: - "default": For 3.3V operation with standard drive strength - "state_uhs": For 1.8V operation with optimized drive strength These pinctrl states allow the SDHCI driver to coordinate voltage switching with pin configuration changes, ensuring proper signal integrity during UHS-I mode transitions. Acked-by: Conor Dooley Signed-off-by: Iker Pedrosa Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml b/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml index 9a055d963a7f..34d202af909f 100644 --- a/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/spacemit,sdhci.yaml @@ -44,6 +44,18 @@ properties: - const: axi - const: sdh + pinctrl-names: + minItems: 1 + items: + - const: default + - const: uhs + + pinctrl-0: + description: Default pinctrl state for 3.3V operation + + pinctrl-1: + description: Optional pinctrl state for 1.8V UHS operation with "uhs" name + required: - compatible - reg @@ -62,4 +74,7 @@ examples: interrupt-parent = <&plic>; clocks = <&clk_apmu 10>, <&clk_apmu 13>; clock-names = "core", "io"; + pinctrl-names = "default", "uhs"; + pinctrl-0 = <&sdhci_default_cfg>; + pinctrl-1 = <&sdhci_uhs_cfg>; }; -- cgit v1.2.3 From f87b273e4b6dfe57dcd63c24cbe3764d1f6954ae Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 11 May 2026 10:53:57 +0200 Subject: mmc: sdhci-of-k1: enable essential clock infrastructure for SD operation Ensure SD card pins receive clock signals by enabling pad clock generation and overriding automatic clock gating. Required for all SD operation modes. The SDHC_GEN_PAD_CLK_ON setting in LEGACY_CTRL_REG is safe for both SD and eMMC operation as both protocols use the same physical MMC interface pins and require proper clock signal generation at the hardware level for signal integrity and timing. Additional SD-specific clock overrides (SDHC_OVRRD_CLK_OEN and SDHC_FORCE_CLK_ON) are conditionally applied only for SD-only controllers to handle removable card scenarios. Tested-by: Anand Moon Acked-by: Adrian Hunter Tested-by: Trevor Gamblin Reviewed-by: Troy Mitchell Tested-by: Vincent Legoll Signed-off-by: Iker Pedrosa Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-k1.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c index 455656f9842d..0dd06fc19b85 100644 --- a/drivers/mmc/host/sdhci-of-k1.c +++ b/drivers/mmc/host/sdhci-of-k1.c @@ -21,6 +21,13 @@ #include "sdhci.h" #include "sdhci-pltfm.h" +#define SPACEMIT_SDHC_OP_EXT_REG 0x108 +#define SDHC_OVRRD_CLK_OEN BIT(11) +#define SDHC_FORCE_CLK_ON BIT(12) + +#define SPACEMIT_SDHC_LEGACY_CTRL_REG 0x10C +#define SDHC_GEN_PAD_CLK_ON BIT(6) + #define SPACEMIT_SDHC_MMC_CTRL_REG 0x114 #define SDHC_MISC_INT_EN BIT(1) #define SDHC_MISC_INT BIT(2) @@ -101,6 +108,12 @@ static void spacemit_sdhci_reset(struct sdhci_host *host, u8 mask) if (!(host->mmc->caps2 & MMC_CAP2_NO_MMC)) spacemit_sdhci_setbits(host, SDHC_MMC_CARD_MODE, SPACEMIT_SDHC_MMC_CTRL_REG); + + spacemit_sdhci_setbits(host, SDHC_GEN_PAD_CLK_ON, SPACEMIT_SDHC_LEGACY_CTRL_REG); + + if (host->mmc->caps2 & MMC_CAP2_NO_MMC) + spacemit_sdhci_setbits(host, SDHC_OVRRD_CLK_OEN | SDHC_FORCE_CLK_ON, + SPACEMIT_SDHC_OP_EXT_REG); } static void spacemit_sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned int timing) -- cgit v1.2.3 From 00a97fc57c09ff1cf71107753d9b5629caeb8c8a Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 11 May 2026 10:53:58 +0200 Subject: mmc: sdhci-of-k1: add regulator and pinctrl voltage switching support Add voltage switching infrastructure for UHS-I modes by integrating both regulator framework (for supply voltage control) and pinctrl state switching (for pin drive strength optimization). - Add regulator supply parsing and voltage switching callback - Add optional pinctrl state switching between "default" (3.3V) and "state_uhs" (1.8V) configurations - Enable coordinated voltage and pin configuration changes for UHS modes This provides complete voltage switching support while maintaining backward compatibility when pinctrl states are not defined. Tested-by: Anand Moon Tested-by: Trevor Gamblin Acked-by: Adrian Hunter Reviewed-by: Troy Mitchell Tested-by: Vincent Legoll Signed-off-by: Iker Pedrosa Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-k1.c | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c index 0dd06fc19b85..d9144537032a 100644 --- a/drivers/mmc/host/sdhci-of-k1.c +++ b/drivers/mmc/host/sdhci-of-k1.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "sdhci.h" @@ -71,6 +72,9 @@ struct spacemit_sdhci_host { struct clk *clk_core; struct clk *clk_io; + struct pinctrl *pinctrl; + struct pinctrl_state *pinctrl_default; + struct pinctrl_state *pinctrl_uhs; }; /* All helper functions will update clr/set while preserve rest bits */ @@ -219,6 +223,46 @@ static void spacemit_sdhci_pre_hs400_to_hs200(struct mmc_host *mmc) SPACEMIT_SDHC_PHY_CTRL_REG); } +static int spacemit_sdhci_start_signal_voltage_switch(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct spacemit_sdhci_host *sdhst = sdhci_pltfm_priv(pltfm_host); + struct pinctrl_state *state; + int ret; + + ret = sdhci_start_signal_voltage_switch(mmc, ios); + if (ret) + return ret; + + if (!sdhst->pinctrl) + return 0; + + /* Select appropriate pinctrl state based on signal voltage */ + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_330: + state = sdhst->pinctrl_default; + break; + case MMC_SIGNAL_VOLTAGE_180: + state = sdhst->pinctrl_uhs; + break; + default: + dev_warn(mmc_dev(mmc), "unsupported voltage %d\n", ios->signal_voltage); + return 0; + } + + ret = pinctrl_select_state(sdhst->pinctrl, state); + if (ret) { + dev_warn(mmc_dev(mmc), "failed to select pinctrl state: %d\n", ret); + return 0; + } + dev_dbg(mmc_dev(mmc), "switched to %s pinctrl state\n", + ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180 ? "UHS" : "default"); + + return 0; +} + static inline int spacemit_sdhci_get_clocks(struct device *dev, struct sdhci_pltfm_host *pltfm_host) { @@ -252,6 +296,30 @@ static inline int spacemit_sdhci_get_resets(struct device *dev) return 0; } +static inline void spacemit_sdhci_get_pins(struct device *dev, + struct sdhci_pltfm_host *pltfm_host) +{ + struct spacemit_sdhci_host *sdhst = sdhci_pltfm_priv(pltfm_host); + + sdhst->pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(sdhst->pinctrl)) { + sdhst->pinctrl = NULL; + dev_dbg(dev, "pinctrl not available, voltage switching will work without it\n"); + return; + } + + sdhst->pinctrl_default = pinctrl_lookup_state(sdhst->pinctrl, "default"); + if (IS_ERR(sdhst->pinctrl_default)) + sdhst->pinctrl_default = NULL; + + sdhst->pinctrl_uhs = pinctrl_lookup_state(sdhst->pinctrl, "uhs"); + if (IS_ERR(sdhst->pinctrl_uhs)) + sdhst->pinctrl_uhs = NULL; + + dev_dbg(dev, "pinctrl setup: default=%p, uhs=%p\n", + sdhst->pinctrl_default, sdhst->pinctrl_uhs); +} + static const struct sdhci_ops spacemit_sdhci_ops = { .get_max_clock = spacemit_sdhci_clk_get_max_clock, .reset = spacemit_sdhci_reset, @@ -324,6 +392,10 @@ static int spacemit_sdhci_probe(struct platform_device *pdev) host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY; + spacemit_sdhci_get_pins(dev, pltfm_host); + + host->mmc_host_ops.start_signal_voltage_switch = spacemit_sdhci_start_signal_voltage_switch; + ret = spacemit_sdhci_get_clocks(dev, pltfm_host); if (ret) goto err_pltfm; -- cgit v1.2.3 From e9cb83c10071808aa7db4582e007a650aa6aa183 Mon Sep 17 00:00:00 2001 From: Iker Pedrosa Date: Mon, 11 May 2026 10:53:59 +0200 Subject: mmc: sdhci-of-k1: add comprehensive SDR tuning support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement software tuning algorithm to enable UHS-I SDR modes for SD card operation and HS200 mode for eMMC. This adds both TX and RX delay line tuning based on the SpacemiT K1 controller capabilities. Algorithm features: - Add tuning register definitions (RX_CFG, DLINE_CTRL, DLINE_CFG) - Conditional tuning: only for high-speed modes (≥100MHz) - TX tuning: configure transmit delay line with optimal values (dline_reg=0, delaycode=127) to ensure optimal signal output timing - RX tuning: single-pass window detection algorithm testing full delay range (0-255) to find optimal receive timing window - Retry mechanism: multiple fallback delays within optimal window for improved reliability Tested-by: Anand Moon Acked-by: Adrian Hunter Tested-by: Trevor Gamblin Tested-by: Vincent Legoll Signed-off-by: Iker Pedrosa Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-k1.c | 172 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-k1.c b/drivers/mmc/host/sdhci-of-k1.c index d9144537032a..37b0911e7cf2 100644 --- a/drivers/mmc/host/sdhci-of-k1.c +++ b/drivers/mmc/host/sdhci-of-k1.c @@ -69,6 +69,28 @@ #define SDHC_PHY_DRIVE_SEL GENMASK(2, 0) #define SDHC_RX_BIAS_CTRL BIT(5) +#define SPACEMIT_SDHC_RX_CFG_REG 0x118 +#define SDHC_RX_SDCLK_SEL0_MASK GENMASK(1, 0) +#define SDHC_RX_SDCLK_SEL1_MASK GENMASK(3, 2) +#define SDHC_RX_SDCLK_SEL1 FIELD_PREP(SDHC_RX_SDCLK_SEL1_MASK, 1) + +#define SPACEMIT_SDHC_DLINE_CTRL_REG 0x130 +#define SDHC_DLINE_PU BIT(0) +#define SDHC_RX_DLINE_CODE_MASK GENMASK(23, 16) +#define SDHC_TX_DLINE_CODE_MASK GENMASK(31, 24) + +#define SPACEMIT_SDHC_DLINE_CFG_REG 0x134 +#define SDHC_RX_DLINE_REG_MASK GENMASK(7, 0) +#define SDHC_RX_DLINE_GAIN BIT(8) +#define SDHC_TX_DLINE_REG_MASK GENMASK(23, 16) + +#define SPACEMIT_RX_DLINE_REG 9 +#define SPACEMIT_RX_TUNE_DELAY_MIN 0x0 +#define SPACEMIT_RX_TUNE_DELAY_MAX 0xFF + +#define SPACEMIT_TX_TUNING_DLINE_REG 0x00 +#define SPACEMIT_TX_TUNING_DELAYCODE 127 + struct spacemit_sdhci_host { struct clk *clk_core; struct clk *clk_io; @@ -96,6 +118,50 @@ static inline void spacemit_sdhci_clrsetbits(struct sdhci_host *host, u32 clr, u sdhci_writel(host, val, reg); } +static void spacemit_sdhci_set_rx_delay(struct sdhci_host *host, u8 delay) +{ + spacemit_sdhci_clrsetbits(host, SDHC_RX_DLINE_CODE_MASK, + FIELD_PREP(SDHC_RX_DLINE_CODE_MASK, delay), + SPACEMIT_SDHC_DLINE_CTRL_REG); +} + +static void spacemit_sdhci_set_tx_delay(struct sdhci_host *host, u8 delay) +{ + spacemit_sdhci_clrsetbits(host, SDHC_TX_DLINE_CODE_MASK, + FIELD_PREP(SDHC_TX_DLINE_CODE_MASK, delay), + SPACEMIT_SDHC_DLINE_CTRL_REG); +} + +static void spacemit_sdhci_set_tx_dline_reg(struct sdhci_host *host, u8 dline_reg) +{ + spacemit_sdhci_clrsetbits(host, SDHC_TX_DLINE_REG_MASK, + FIELD_PREP(SDHC_TX_DLINE_REG_MASK, dline_reg), + SPACEMIT_SDHC_DLINE_CFG_REG); +} + +static void spacemit_sdhci_tx_tuning_prepare(struct sdhci_host *host) +{ + spacemit_sdhci_setbits(host, SDHC_TX_MUX_SEL, SPACEMIT_SDHC_TX_CFG_REG); + spacemit_sdhci_setbits(host, SDHC_DLINE_PU, SPACEMIT_SDHC_DLINE_CTRL_REG); + udelay(5); +} + +static void spacemit_sdhci_prepare_tuning(struct sdhci_host *host) +{ + spacemit_sdhci_clrsetbits(host, SDHC_RX_DLINE_REG_MASK, + FIELD_PREP(SDHC_RX_DLINE_REG_MASK, SPACEMIT_RX_DLINE_REG), + SPACEMIT_SDHC_DLINE_CFG_REG); + + spacemit_sdhci_setbits(host, SDHC_DLINE_PU, SPACEMIT_SDHC_DLINE_CTRL_REG); + udelay(5); + + spacemit_sdhci_clrsetbits(host, SDHC_RX_SDCLK_SEL1_MASK, SDHC_RX_SDCLK_SEL1, + SPACEMIT_SDHC_RX_CFG_REG); + + if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200) + spacemit_sdhci_setbits(host, SDHC_HS200_USE_RFIFO, SPACEMIT_SDHC_PHY_FUNC_REG); +} + static void spacemit_sdhci_reset(struct sdhci_host *host, u8 mask) { sdhci_reset(host, mask); @@ -191,6 +257,111 @@ static unsigned int spacemit_sdhci_clk_get_max_clock(struct sdhci_host *host) return clk_get_rate(pltfm_host->clk); } +static int spacemit_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) +{ + int current_len = 0, current_start = 0; + int max_pass_len = 0, max_pass_start = 0; + struct mmc_host *mmc = host->mmc; + struct mmc_ios ios = mmc->ios; + u8 final_delay; + int ret = 0; + int i; + + /* + * Tuning is required for SDR50/SDR104, HS200/HS400 cards and + * if clock frequency is greater than 100MHz in these modes. + */ + if (host->clock < 100 * 1000 * 1000 || + !(ios.timing == MMC_TIMING_MMC_HS200 || + ios.timing == MMC_TIMING_UHS_SDR50 || + ios.timing == MMC_TIMING_UHS_SDR104)) + return 0; + + if (mmc->caps2 & MMC_CAP2_NO_MMC) { + spacemit_sdhci_set_tx_dline_reg(host, SPACEMIT_TX_TUNING_DLINE_REG); + spacemit_sdhci_set_tx_delay(host, SPACEMIT_TX_TUNING_DELAYCODE); + spacemit_sdhci_tx_tuning_prepare(host); + + dev_dbg(mmc_dev(host->mmc), "TX tuning: dline_reg=%d, delaycode=%d\n", + SPACEMIT_TX_TUNING_DLINE_REG, SPACEMIT_TX_TUNING_DELAYCODE); + } + + spacemit_sdhci_prepare_tuning(host); + + for (i = SPACEMIT_RX_TUNE_DELAY_MIN; i <= SPACEMIT_RX_TUNE_DELAY_MAX; i++) { + spacemit_sdhci_set_rx_delay(host, i); + ret = mmc_send_tuning(host->mmc, opcode, NULL); + + dev_dbg(mmc_dev(host->mmc), "RX delay %d: %s\n", + i, ret == 0 ? "pass" : "fail"); + + if (ret == 0) { + /* Test passed - extend current window */ + if (current_len == 0) + current_start = i; + current_len++; + } else { + /* Test failed - check if current window is best so far */ + if (current_len > max_pass_len) { + max_pass_len = current_len; + max_pass_start = current_start; + } + current_len = 0; + } + } + + if (current_len > max_pass_len) { + max_pass_len = current_len; + max_pass_start = current_start; + } + + if (max_pass_len < 3) { + dev_err(mmc_dev(host->mmc), "Tuning failed: no stable window found\n"); + return -EIO; + } + + final_delay = max_pass_start + max_pass_len / 2; + spacemit_sdhci_set_rx_delay(host, final_delay); + ret = mmc_send_tuning(host->mmc, opcode, NULL); + if (ret) { + u8 retry_delays[] = { + max_pass_start + max_pass_len / 4, + max_pass_start + (3 * max_pass_len) / 4, + max_pass_start, + max_pass_start + max_pass_len - 1 + }; + int retry_count = ARRAY_SIZE(retry_delays); + + dev_warn(mmc_dev(mmc), "Primary delay %d failed, trying alternatives\n", + final_delay); + + for (i = 0; i < retry_count; i++) { + if (retry_delays[i] >= SPACEMIT_RX_TUNE_DELAY_MIN && + retry_delays[i] <= SPACEMIT_RX_TUNE_DELAY_MAX) { + spacemit_sdhci_set_rx_delay(host, retry_delays[i]); + ret = mmc_send_tuning(host->mmc, opcode, NULL); + if (!ret) { + final_delay = retry_delays[i]; + dev_info(mmc_dev(mmc), "Retry successful with delay %d\n", + final_delay); + break; + } + } + } + + if (ret) { + dev_err(mmc_dev(mmc), "All retry attempts failed\n"); + return -EIO; + } + } + + dev_dbg(mmc_dev(host->mmc), + "Tuning successful: window %d-%d, using delay %d\n", + max_pass_start, max_pass_start + max_pass_len - 1, final_delay); + + return 0; +} + static int spacemit_sdhci_pre_select_hs400(struct mmc_host *mmc) { struct sdhci_host *host = mmc_priv(mmc); @@ -326,6 +497,7 @@ static const struct sdhci_ops spacemit_sdhci_ops = { .set_bus_width = sdhci_set_bus_width, .set_clock = spacemit_sdhci_set_clock, .set_uhs_signaling = spacemit_sdhci_set_uhs_signaling, + .platform_execute_tuning = spacemit_sdhci_execute_tuning, }; static const struct sdhci_pltfm_data spacemit_sdhci_k1_pdata = { -- cgit v1.2.3 From 4401e07263896cf992c5cd080315f46d4621aec4 Mon Sep 17 00:00:00 2001 From: Monish Chunara Date: Fri, 8 May 2026 15:45:44 +0530 Subject: dt-bindings: mmc: sdhci-msm: Document the Shikra compatible Document the Shikra-specific SDHCI compatible in the sdhci-msm binding. Use "qcom,sdhci-msm-v5" as the fallback compatible for the MSM SDHCI v5 controller used on Shikra. Signed-off-by: Monish Chunara Acked-by: Rob Herring (Arm) Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-msm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index 695a95e8f35d..60dc6b0caa21 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -62,6 +62,7 @@ properties: - qcom,sdx55-sdhci - qcom,sdx65-sdhci - qcom,sdx75-sdhci + - qcom,shikra-sdhci - qcom,sm6115-sdhci - qcom,sm6125-sdhci - qcom,sm6350-sdhci -- cgit v1.2.3 From d04e0151d316edbdb4f0397a9b92a1936e4a1421 Mon Sep 17 00:00:00 2001 From: Osama Abdelkader Date: Sun, 10 May 2026 18:29:39 +0200 Subject: mmc: davinci: fix mmc_add_host order in probe mmc_add_host() makes the host visible to the MMC core. Register the interrupt handlers and advertise MMC_CAP_SDIO_IRQ before that, so the core cannot start using the host before IRQ handling is set up. Signed-off-by: Osama Abdelkader Signed-off-by: Ulf Hansson --- drivers/mmc/host/davinci_mmc.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 42ad87aa48f5..cdb9fa94b56d 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -1294,14 +1294,10 @@ static int davinci_mmcsd_probe(struct platform_device *pdev) goto cpu_freq_fail; } - ret = mmc_add_host(mmc); - if (ret < 0) - goto mmc_add_host_fail; - ret = devm_request_irq(&pdev->dev, irq, mmc_davinci_irq, 0, mmc_hostname(mmc), host); if (ret) - goto request_irq_fail; + goto mmc_add_host_fail; if (host->sdio_irq >= 0) { ret = devm_request_irq(&pdev->dev, host->sdio_irq, @@ -1311,6 +1307,10 @@ static int davinci_mmcsd_probe(struct platform_device *pdev) mmc->caps |= MMC_CAP_SDIO_IRQ; } + ret = mmc_add_host(mmc); + if (ret < 0) + goto mmc_add_host_fail; + rename_region(mem, mmc_hostname(mmc)); if (mmc->caps & MMC_CAP_8_BIT_DATA) @@ -1324,8 +1324,6 @@ static int davinci_mmcsd_probe(struct platform_device *pdev) return 0; -request_irq_fail: - mmc_remove_host(mmc); mmc_add_host_fail: mmc_davinci_cpufreq_deregister(host); cpu_freq_fail: -- cgit v1.2.3 From cb4b9aeb3a84149cf9c38942877093bdd8a611bc Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 13 May 2026 14:19:37 +0300 Subject: dt-bindings: mmc: sdhci-msm: Add Eliza compatible Document the compatible string for the SDHCI controller on the Eliza platform. Signed-off-by: Abel Vesa Reviewed-by: Krzysztof Kozlowski Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-msm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index 60dc6b0caa21..0762403d4c8b 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -37,6 +37,7 @@ properties: - const: qcom,sdhci-msm-v4 # for sdcc versions less than 5.0 - items: - enum: + - qcom,eliza-sdhci - qcom,ipq5018-sdhci - qcom,ipq5210-sdhci - qcom,ipq5332-sdhci -- cgit v1.2.3 From 5ce500d31a1625d8fe7ede950201b8df076bdd48 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Tue, 19 May 2026 14:53:41 +0100 Subject: mmc: renesas_sdhi: Add OF entry for RZ/G2N SoC The RZ/G2N (R8A774B1) SoC was previously handled via the generic "renesas,rcar-gen3-sdhi" fallback compatible string. However, because the SDHI IP on RZ/G2N is identical with the R-Car M3-N (R8A77965), it requires the specific quirks and configuration defined in `of_r8a77965_compatible` rather than the generic Gen3 data. Add the explicit "renesas,sdhi-r8a774b1" match entry to map it correctly. Note that the DT binding file renesas,sdhi.yaml does not need an update as the entry for this SoC is already present. Signed-off-by: Lad Prabhakar Reviewed-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 1d3cd4c3da1f..93470aea21df 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -279,6 +279,7 @@ static const struct renesas_sdhi_of_data_with_quirks of_rza2_compatible = { static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = { { .compatible = "renesas,sdhi-r7s9210", .data = &of_rza2_compatible, }, { .compatible = "renesas,sdhi-mmc-r8a77470", .data = &of_rcar_gen3_compatible, }, + { .compatible = "renesas,sdhi-r8a774b1", .data = &of_r8a77965_compatible, }, { .compatible = "renesas,sdhi-r8a774e1", .data = &of_r8a7795_compatible, }, { .compatible = "renesas,sdhi-r8a7795", .data = &of_r8a7795_compatible, }, { .compatible = "renesas,sdhi-r8a77961", .data = &of_r8a77961_compatible, }, -- cgit v1.2.3 From ebf7f2198ac4817bd2929cf83c697cefa8bf36a9 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Tue, 19 May 2026 14:53:42 +0100 Subject: mmc: renesas_sdhi: Add OF entry for RZ/G2E SoC The RZ/G2E (R8A774C0) SoC was previously handled via the generic "renesas,rcar-gen3-sdhi" fallback compatible string. However, because the SDHI IP on RZ/G2E is identical with the R-Car E3 (R8A77990), it requires the specific quirks and configuration defined in `of_r8a77990_compatible` rather than the generic Gen3 data. Add the explicit "renesas,sdhi-r8a774c0" match entry to map it correctly. Note that the DT binding file renesas,sdhi.yaml does not need an update as the entry for this SoC is already present. Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 93470aea21df..024edc4e5fe6 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -280,6 +280,7 @@ static const struct of_device_id renesas_sdhi_internal_dmac_of_match[] = { { .compatible = "renesas,sdhi-r7s9210", .data = &of_rza2_compatible, }, { .compatible = "renesas,sdhi-mmc-r8a77470", .data = &of_rcar_gen3_compatible, }, { .compatible = "renesas,sdhi-r8a774b1", .data = &of_r8a77965_compatible, }, + { .compatible = "renesas,sdhi-r8a774c0", .data = &of_r8a77990_compatible, }, { .compatible = "renesas,sdhi-r8a774e1", .data = &of_r8a7795_compatible, }, { .compatible = "renesas,sdhi-r8a7795", .data = &of_r8a7795_compatible, }, { .compatible = "renesas,sdhi-r8a77961", .data = &of_r8a77961_compatible, }, -- cgit v1.2.3 From 906d715cae80593470926f9fe1105d7d4a1ce14b Mon Sep 17 00:00:00 2001 From: Nitin Rawat Date: Wed, 20 May 2026 13:24:45 +0530 Subject: dt-bindings: mmc: sdhci-msm: qcom: Add Hawi compatible Document the compatible string for the SDHCI controller on the Qualcomm Hawi platform. Signed-off-by: Nitin Rawat Signed-off-by: Mukesh Ojha Reviewed-by: Manivannan Sadhasivam Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-msm.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml index 0762403d4c8b..df81b6accc72 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml @@ -38,6 +38,7 @@ properties: - items: - enum: - qcom,eliza-sdhci + - qcom,hawi-sdhci - qcom,ipq5018-sdhci - qcom,ipq5210-sdhci - qcom,ipq5332-sdhci -- cgit v1.2.3 From 423ab671bb921206bab25ffe61adc5da98a64e6c Mon Sep 17 00:00:00 2001 From: Artem Shimko Date: Fri, 22 May 2026 10:31:31 +0300 Subject: mmc: sdhci-of-dwcmshc: remove redundant IS_ERR() check The clk_disable_unprepare() function has internal protection against ERR_PTR and NULL pointers (IS_ERR_OR_NULL). Remove the redundant IS_ERR() check for bus_clk in dwcmshc_suspend() and in the error path of dwcmshc_resume() to simplify the code. Note that the clk_prepare_enable() call in dwcmshc_resume() must retain its IS_ERR() check because clk_prepare() only handles NULL pointers, not ERR_PTR. No functional change intended. Acked-by: Adrian Hunter Signed-off-by: Artem Shimko Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-dwcmshc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index b9ecd91f44ad..0786304e7a2f 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -2564,8 +2564,7 @@ static int dwcmshc_suspend(struct device *dev) return ret; clk_disable_unprepare(pltfm_host->clk); - if (!IS_ERR(priv->bus_clk)) - clk_disable_unprepare(priv->bus_clk); + clk_disable_unprepare(priv->bus_clk); clk_bulk_disable_unprepare(priv->num_other_clks, priv->other_clks); @@ -2608,8 +2607,7 @@ static int dwcmshc_resume(struct device *dev) disable_other_clks: clk_bulk_disable_unprepare(priv->num_other_clks, priv->other_clks); disable_bus_clk: - if (!IS_ERR(priv->bus_clk)) - clk_disable_unprepare(priv->bus_clk); + clk_disable_unprepare(priv->bus_clk); disable_clk: clk_disable_unprepare(pltfm_host->clk); return ret; -- cgit v1.2.3 From 23d4f4316a71e04c34c7c5e03a662cc59f9ccb80 Mon Sep 17 00:00:00 2001 From: Artem Shimko Date: Fri, 22 May 2026 10:31:32 +0300 Subject: mmc: sdhci-of-dwcmshc: use dev_err_probe() to simplify error paths Replace common pattern of dev_err() + return with dev_err_probe() in probe functions and their callees. This macro provides standardized error message format with symbolic error names and adds deferred probe debugging information. The conversion makes the code more compact and ensures consistent error logging across all initialization paths. Acked-by: Adrian Hunter Signed-off-by: Artem Shimko Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-dwcmshc.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 0786304e7a2f..eef53455b8ee 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -918,11 +918,9 @@ static int dwcmshc_rk35xx_init(struct device *dev, struct sdhci_host *host, return -ENOMEM; priv->reset = devm_reset_control_array_get_optional_exclusive(mmc_dev(host->mmc)); - if (IS_ERR(priv->reset)) { - err = PTR_ERR(priv->reset); - dev_err(mmc_dev(host->mmc), "failed to get reset control %d\n", err); - return err; - } + if (IS_ERR(priv->reset)) + return dev_err_probe(mmc_dev(host->mmc), PTR_ERR(priv->reset), + "failed to get reset control\n"); err = dwcmshc_get_enable_other_clks(mmc_dev(host->mmc), dwc_priv, ARRAY_SIZE(clk_ids), clk_ids); @@ -1779,10 +1777,8 @@ static int eic7700_init(struct device *dev, struct sdhci_host *host, struct dwcm dwc_priv->priv = priv; ret = sdhci_eic7700_reset_init(dev, dwc_priv->priv); - if (ret) { - dev_err(dev, "failed to reset\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to reset\n"); ret = dwcmshc_get_enable_other_clks(mmc_dev(host->mmc), dwc_priv, ARRAY_SIZE(clk_ids), clk_ids); @@ -1790,16 +1786,14 @@ static int eic7700_init(struct device *dev, struct sdhci_host *host, struct dwcm 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); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Fail to parse 'eswin,hsp-sp-csr' phandle\n"); hsp_regmap = syscon_node_to_regmap(args.np); if (IS_ERR(hsp_regmap)) { - dev_err(dev, "Failed to get regmap for 'eswin,hsp-sp-csr'\n"); of_node_put(args.np); - return PTR_ERR(hsp_regmap); + return dev_err_probe(dev, PTR_ERR(hsp_regmap), + "Failed to get regmap for 'eswin,hsp-sp-csr'\n"); } hsp_int_status = args.args[0]; hsp_pwr_ctrl = args.args[1]; @@ -2408,10 +2402,8 @@ static int dwcmshc_probe(struct platform_device *pdev) u32 extra, caps; pltfm_data = device_get_match_data(&pdev->dev); - if (!pltfm_data) { - dev_err(&pdev->dev, "Error: No device match data found\n"); - return -ENODEV; - } + if (!pltfm_data) + return dev_err_probe(&pdev->dev, -ENODEV, "No device match data found\n"); host = sdhci_pltfm_init(pdev, &pltfm_data->pdata, sizeof(struct dwcmshc_priv)); -- cgit v1.2.3 From 94044acc20cdb99a0429723bcca5e1d828dbf47f Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 28 May 2026 15:53:42 +0200 Subject: dt-bindings: mmc: sdhci-msm: Rename the binding to include 'qcom' prefix This is the only Qcom binding that doesn't have 'qcom' prefix in the bindings name. This doesn't match with the regex in MAINTAINERS file and the 'get_maintainer.pl' script fails to list the 'linux-arm-msm' list: Ulf Hansson (maintainer:MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND...) Rob Herring (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS) Krzysztof Kozlowski (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS) Conor Dooley (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS) Bjorn Andersson (in file) Konrad Dybcio (in file) linux-mmc@vger.kernel.org (open list:MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND...) devicetree@vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS) linux-kernel@vger.kernel.org (open list) Hence, rename the binding to include 'qcom' prefix so that the regex matches correctly. Reported-by: Mukesh Ojha Closes: https://lore.kernel.org/all/20260526151003.p4kn2vek3hpv4gzv@hu-mojha-hyd.qualcomm.com Signed-off-by: Manivannan Sadhasivam Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/qcom,sdhci-msm.yaml | 282 +++++++++++++++++++++ .../devicetree/bindings/mmc/sdhci-msm.yaml | 282 --------------------- 2 files changed, 282 insertions(+), 282 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml delete mode 100644 Documentation/devicetree/bindings/mmc/sdhci-msm.yaml diff --git a/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml new file mode 100644 index 000000000000..bd558a11b792 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml @@ -0,0 +1,282 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/qcom,sdhci-msm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SDHCI controller (sdhci-msm) + +maintainers: + - Bjorn Andersson + - Konrad Dybcio + +description: + Secure Digital Host Controller Interface (SDHCI) present on + Qualcomm SOCs supports SD/MMC/SDIO devices. + +properties: + compatible: + oneOf: + - enum: + - qcom,sdhci-msm-v4 + deprecated: true + - items: + - enum: + - qcom,apq8084-sdhci + - qcom,ipq4019-sdhci + - qcom,ipq8074-sdhci + - qcom,msm8226-sdhci + - qcom,msm8953-sdhci + - qcom,msm8974-sdhci + - qcom,msm8976-sdhci + - qcom,msm8916-sdhci + - qcom,msm8992-sdhci + - qcom,msm8994-sdhci + - qcom,msm8996-sdhci + - qcom,msm8998-sdhci + - const: qcom,sdhci-msm-v4 # for sdcc versions less than 5.0 + - items: + - enum: + - qcom,eliza-sdhci + - qcom,hawi-sdhci + - qcom,ipq5018-sdhci + - qcom,ipq5210-sdhci + - qcom,ipq5332-sdhci + - qcom,ipq5424-sdhci + - qcom,ipq6018-sdhci + - qcom,ipq9574-sdhci + - qcom,ipq9650-sdhci + - qcom,kaanapali-sdhci + - qcom,milos-sdhci + - qcom,qcm2290-sdhci + - qcom,qcs404-sdhci + - qcom,qcs615-sdhci + - qcom,qcs8300-sdhci + - qcom,qdu1000-sdhci + - qcom,sa8775p-sdhci + - qcom,sar2130p-sdhci + - qcom,sc7180-sdhci + - qcom,sc7280-sdhci + - qcom,sc8280xp-sdhci + - qcom,sdm630-sdhci + - qcom,sdm670-sdhci + - qcom,sdm845-sdhci + - qcom,sdx55-sdhci + - qcom,sdx65-sdhci + - qcom,sdx75-sdhci + - qcom,shikra-sdhci + - qcom,sm6115-sdhci + - qcom,sm6125-sdhci + - qcom,sm6350-sdhci + - qcom,sm6375-sdhci + - qcom,sm7150-sdhci + - qcom,sm8150-sdhci + - qcom,sm8250-sdhci + - qcom,sm8350-sdhci + - qcom,sm8450-sdhci + - qcom,sm8550-sdhci + - qcom,sm8650-sdhci + - qcom,sm8750-sdhci + - qcom,x1e80100-sdhci + - const: qcom,sdhci-msm-v5 # for sdcc version 5.0 + + reg: + minItems: 1 + maxItems: 4 + + reg-names: + minItems: 1 + maxItems: 4 + + clocks: + minItems: 2 + items: + - description: Main peripheral bus clock, PCLK/HCLK - AHB Bus clock + - description: SDC MMC clock, MCLK + - description: TCXO clock + - description: clock for Inline Crypto Engine + - description: SDCC bus voter clock + - description: reference clock for RCLK delay calibration + - description: sleep clock for RCLK delay calibration + + clock-names: + minItems: 2 + items: + - const: iface + - const: core + - const: xo + - enum: [ice, bus, cal, sleep] + - enum: [ice, bus, cal, sleep] + - enum: [ice, bus, cal, sleep] + - enum: [ice, bus, cal, sleep] + + dma-coherent: true + + interrupts: + maxItems: 2 + + interrupt-names: + items: + - const: hc_irq + - const: pwr_irq + + pinctrl-names: + minItems: 1 + items: + - const: default + - const: sleep + + pinctrl-0: + description: + Should specify pin control groups used for this controller. + + pinctrl-1: + description: + Should specify sleep pin control groups used for this controller. + + resets: + maxItems: 1 + + qcom,ddr-config: + $ref: /schemas/types.yaml#/definitions/uint32 + description: platform specific settings for DDR_CONFIG reg. + + qcom,dll-config: + $ref: /schemas/types.yaml#/definitions/uint32 + description: platform specific settings for DLL_CONFIG reg. + + iommus: + minItems: 1 + maxItems: 8 + description: | + phandle to apps_smmu node with sid mask. + + interconnects: + minItems: 1 + items: + - description: data path, sdhc to ddr + - description: config path, cpu to sdhc + + interconnect-names: + minItems: 1 + items: + - const: sdhc-ddr + - const: cpu-sdhc + + power-domains: + description: A phandle to sdhci power domain node + maxItems: 1 + + operating-points-v2: true + +patternProperties: + '^opp-table(-[a-z0-9]+)?$': + if: + properties: + compatible: + const: operating-points-v2 + then: + patternProperties: + '^opp-?[0-9]+$': + required: + - required-opps + +required: + - compatible + - reg + - clocks + - clock-names + - interrupts + +allOf: + - $ref: sdhci-common.yaml# + + - if: + properties: + compatible: + contains: + enum: + - qcom,sdhci-msm-v4 + then: + properties: + reg: + minItems: 2 + items: + - description: Host controller register map + - description: SD Core register map + - description: CQE register map + - description: Inline Crypto Engine register map + reg-names: + minItems: 2 + items: + - const: hc + - const: core + - const: cqhci + - const: ice + else: + properties: + reg: + minItems: 1 + items: + - description: Host controller register map + - description: CQE register map + - description: Inline Crypto Engine register map + reg-names: + minItems: 1 + items: + - const: hc + - const: cqhci + - const: ice + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + #include + + sdhc_2: mmc@8804000 { + compatible = "qcom,sm8250-sdhci", "qcom,sdhci-msm-v5"; + reg = <0 0x08804000 0 0x1000>; + + interrupts = , + ; + interrupt-names = "hc_irq", "pwr_irq"; + + clocks = <&gcc GCC_SDCC2_AHB_CLK>, + <&gcc GCC_SDCC2_APPS_CLK>, + <&rpmhcc RPMH_CXO_CLK>; + clock-names = "iface", "core", "xo"; + iommus = <&apps_smmu 0x4a0 0x0>; + qcom,dll-config = <0x0007642c>; + qcom,ddr-config = <0x80040868>; + power-domains = <&rpmhpd RPMHPD_CX>; + + operating-points-v2 = <&sdhc2_opp_table>; + + sdhc2_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-19200000 { + opp-hz = /bits/ 64 <19200000>; + required-opps = <&rpmhpd_opp_min_svs>; + }; + + opp-50000000 { + opp-hz = /bits/ 64 <50000000>; + required-opps = <&rpmhpd_opp_low_svs>; + }; + + opp-100000000 { + opp-hz = /bits/ 64 <100000000>; + required-opps = <&rpmhpd_opp_svs>; + }; + + opp-202000000 { + opp-hz = /bits/ 64 <202000000>; + required-opps = <&rpmhpd_opp_svs_l1>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml deleted file mode 100644 index df81b6accc72..000000000000 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml +++ /dev/null @@ -1,282 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/mmc/sdhci-msm.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Qualcomm SDHCI controller (sdhci-msm) - -maintainers: - - Bjorn Andersson - - Konrad Dybcio - -description: - Secure Digital Host Controller Interface (SDHCI) present on - Qualcomm SOCs supports SD/MMC/SDIO devices. - -properties: - compatible: - oneOf: - - enum: - - qcom,sdhci-msm-v4 - deprecated: true - - items: - - enum: - - qcom,apq8084-sdhci - - qcom,ipq4019-sdhci - - qcom,ipq8074-sdhci - - qcom,msm8226-sdhci - - qcom,msm8953-sdhci - - qcom,msm8974-sdhci - - qcom,msm8976-sdhci - - qcom,msm8916-sdhci - - qcom,msm8992-sdhci - - qcom,msm8994-sdhci - - qcom,msm8996-sdhci - - qcom,msm8998-sdhci - - const: qcom,sdhci-msm-v4 # for sdcc versions less than 5.0 - - items: - - enum: - - qcom,eliza-sdhci - - qcom,hawi-sdhci - - qcom,ipq5018-sdhci - - qcom,ipq5210-sdhci - - qcom,ipq5332-sdhci - - qcom,ipq5424-sdhci - - qcom,ipq6018-sdhci - - qcom,ipq9574-sdhci - - qcom,ipq9650-sdhci - - qcom,kaanapali-sdhci - - qcom,milos-sdhci - - qcom,qcm2290-sdhci - - qcom,qcs404-sdhci - - qcom,qcs615-sdhci - - qcom,qcs8300-sdhci - - qcom,qdu1000-sdhci - - qcom,sa8775p-sdhci - - qcom,sar2130p-sdhci - - qcom,sc7180-sdhci - - qcom,sc7280-sdhci - - qcom,sc8280xp-sdhci - - qcom,sdm630-sdhci - - qcom,sdm670-sdhci - - qcom,sdm845-sdhci - - qcom,sdx55-sdhci - - qcom,sdx65-sdhci - - qcom,sdx75-sdhci - - qcom,shikra-sdhci - - qcom,sm6115-sdhci - - qcom,sm6125-sdhci - - qcom,sm6350-sdhci - - qcom,sm6375-sdhci - - qcom,sm7150-sdhci - - qcom,sm8150-sdhci - - qcom,sm8250-sdhci - - qcom,sm8350-sdhci - - qcom,sm8450-sdhci - - qcom,sm8550-sdhci - - qcom,sm8650-sdhci - - qcom,sm8750-sdhci - - qcom,x1e80100-sdhci - - const: qcom,sdhci-msm-v5 # for sdcc version 5.0 - - reg: - minItems: 1 - maxItems: 4 - - reg-names: - minItems: 1 - maxItems: 4 - - clocks: - minItems: 2 - items: - - description: Main peripheral bus clock, PCLK/HCLK - AHB Bus clock - - description: SDC MMC clock, MCLK - - description: TCXO clock - - description: clock for Inline Crypto Engine - - description: SDCC bus voter clock - - description: reference clock for RCLK delay calibration - - description: sleep clock for RCLK delay calibration - - clock-names: - minItems: 2 - items: - - const: iface - - const: core - - const: xo - - enum: [ice, bus, cal, sleep] - - enum: [ice, bus, cal, sleep] - - enum: [ice, bus, cal, sleep] - - enum: [ice, bus, cal, sleep] - - dma-coherent: true - - interrupts: - maxItems: 2 - - interrupt-names: - items: - - const: hc_irq - - const: pwr_irq - - pinctrl-names: - minItems: 1 - items: - - const: default - - const: sleep - - pinctrl-0: - description: - Should specify pin control groups used for this controller. - - pinctrl-1: - description: - Should specify sleep pin control groups used for this controller. - - resets: - maxItems: 1 - - qcom,ddr-config: - $ref: /schemas/types.yaml#/definitions/uint32 - description: platform specific settings for DDR_CONFIG reg. - - qcom,dll-config: - $ref: /schemas/types.yaml#/definitions/uint32 - description: platform specific settings for DLL_CONFIG reg. - - iommus: - minItems: 1 - maxItems: 8 - description: | - phandle to apps_smmu node with sid mask. - - interconnects: - minItems: 1 - items: - - description: data path, sdhc to ddr - - description: config path, cpu to sdhc - - interconnect-names: - minItems: 1 - items: - - const: sdhc-ddr - - const: cpu-sdhc - - power-domains: - description: A phandle to sdhci power domain node - maxItems: 1 - - operating-points-v2: true - -patternProperties: - '^opp-table(-[a-z0-9]+)?$': - if: - properties: - compatible: - const: operating-points-v2 - then: - patternProperties: - '^opp-?[0-9]+$': - required: - - required-opps - -required: - - compatible - - reg - - clocks - - clock-names - - interrupts - -allOf: - - $ref: sdhci-common.yaml# - - - if: - properties: - compatible: - contains: - enum: - - qcom,sdhci-msm-v4 - then: - properties: - reg: - minItems: 2 - items: - - description: Host controller register map - - description: SD Core register map - - description: CQE register map - - description: Inline Crypto Engine register map - reg-names: - minItems: 2 - items: - - const: hc - - const: core - - const: cqhci - - const: ice - else: - properties: - reg: - minItems: 1 - items: - - description: Host controller register map - - description: CQE register map - - description: Inline Crypto Engine register map - reg-names: - minItems: 1 - items: - - const: hc - - const: cqhci - - const: ice - -unevaluatedProperties: false - -examples: - - | - #include - #include - #include - #include - - sdhc_2: mmc@8804000 { - compatible = "qcom,sm8250-sdhci", "qcom,sdhci-msm-v5"; - reg = <0 0x08804000 0 0x1000>; - - interrupts = , - ; - interrupt-names = "hc_irq", "pwr_irq"; - - clocks = <&gcc GCC_SDCC2_AHB_CLK>, - <&gcc GCC_SDCC2_APPS_CLK>, - <&rpmhcc RPMH_CXO_CLK>; - clock-names = "iface", "core", "xo"; - iommus = <&apps_smmu 0x4a0 0x0>; - qcom,dll-config = <0x0007642c>; - qcom,ddr-config = <0x80040868>; - power-domains = <&rpmhpd RPMHPD_CX>; - - operating-points-v2 = <&sdhc2_opp_table>; - - sdhc2_opp_table: opp-table { - compatible = "operating-points-v2"; - - opp-19200000 { - opp-hz = /bits/ 64 <19200000>; - required-opps = <&rpmhpd_opp_min_svs>; - }; - - opp-50000000 { - opp-hz = /bits/ 64 <50000000>; - required-opps = <&rpmhpd_opp_low_svs>; - }; - - opp-100000000 { - opp-hz = /bits/ 64 <100000000>; - required-opps = <&rpmhpd_opp_svs>; - }; - - opp-202000000 { - opp-hz = /bits/ 64 <202000000>; - required-opps = <&rpmhpd_opp_svs_l1>; - }; - }; - }; -- cgit v1.2.3 From b99062da21a3988c6b8f1ed0730bf3587cdc7844 Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Fri, 29 May 2026 09:17:39 +0800 Subject: mmc: dw_mmc: Add desc_num field for clarity The ring_size field in struct dw_mci is misleadingly named. Despite its name, it does not represent the size of the descriptor ring buffer in bytes, but rather the number of descriptors allocated within the fixed-size ring buffer. The actual ring buffer size is fixed at PAGE_SIZE (or DESC_RING_BUF_SZ, which equals PAGE_SIZE). Within this buffer, we allocate either struct idmac_desc or struct idmac_desc_64addr descriptors, and ring_size stores the count of these descriptors. This naming has caused confusion, as it's also used to set mmc->max_segs (the maximum number of scatter-gather segments), which logically corresponds to the number of descriptors, not a size in bytes. No functional change is introduced by this naming-only patch. Signed-off-by: Shawn Lin Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.c | 16 ++++++++-------- drivers/mmc/host/dw_mmc.h | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 3b4157f34d11..d734d010444d 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -490,12 +490,12 @@ static int dw_mci_idmac_init(struct dw_mci *host) if (host->dma_64bit_address == 1) { struct idmac_desc_64addr *p; - /* Number of descriptors in the ring buffer */ - host->ring_size = + + host->desc_num = DESC_RING_BUF_SZ / sizeof(struct idmac_desc_64addr); /* Forward link the descriptor list */ - for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; + for (i = 0, p = host->sg_cpu; i < host->desc_num - 1; i++, p++) { p->des6 = (host->sg_dma + (sizeof(struct idmac_desc_64addr) * @@ -518,13 +518,13 @@ static int dw_mci_idmac_init(struct dw_mci *host) } else { struct idmac_desc *p; - /* Number of descriptors in the ring buffer */ - host->ring_size = + + host->desc_num = DESC_RING_BUF_SZ / sizeof(struct idmac_desc); /* Forward link the descriptor list */ for (i = 0, p = host->sg_cpu; - i < host->ring_size - 1; + i < host->desc_num - 1; i++, p++) { p->des3 = cpu_to_le32(host->sg_dma + (sizeof(struct idmac_desc) * (i + 1))); @@ -2857,10 +2857,10 @@ static int dw_mci_init_host(struct dw_mci *host) /* Useful defaults if platform data is unset. */ if (host->use_dma == TRANS_MODE_IDMAC) { - mmc->max_segs = host->ring_size; + mmc->max_segs = host->desc_num; mmc->max_blk_size = 65535; mmc->max_seg_size = 0x1000; - mmc->max_req_size = mmc->max_seg_size * host->ring_size; + mmc->max_req_size = mmc->max_seg_size * host->desc_num; mmc->max_blk_count = mmc->max_req_size / 512; } else if (host->use_dma == TRANS_MODE_EDMAC) { mmc->max_segs = 64; diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 2ce8585e2c1e..9ffcd3946cff 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -79,7 +79,7 @@ struct dw_mci_dma_slave { * @dma_ops: Pointer to DMA callbacks. * @cmd_status: Snapshot of SR taken upon completion of the current * command. Only valid when EVENT_CMD_COMPLETE is pending. - * @ring_size: Buffer size for idma descriptors. + * @desc_num: Number of idmac descriptors available. * @dms: structure of slave-dma private data. * @phy_regs: physical address of controller's register map * @data_status: Snapshot of SR taken upon completion of the current @@ -186,7 +186,7 @@ struct dw_mci { void *sg_cpu; const struct dw_mci_dma_ops *dma_ops; /* For idmac */ - unsigned int ring_size; + unsigned short desc_num; /* For edmac */ struct dw_mci_dma_slave *dms; -- cgit v1.2.3