From 50227acbf4e5173db0f05ed95414512e7783889f Mon Sep 17 00:00:00 2001 From: Ben Levinsky Date: Thu, 28 May 2026 19:16:33 -0700 Subject: [PATCH 01/64] remoteproc: Add common wc-ioremap carveout callbacks Several remoteproc drivers open-code the same ioremap_wc() and iounmap() callbacks for carveout mappings. Add subsystem-private helpers in remoteproc_internal.h so those drivers can share the same implementation. Keep this change behavior-neutral. The helper now emits a common error message on ioremap_wc() failure, but leaves mem->is_iomem handling to a follow-on patch so that the behavioral change can be justified separately. Signed-off-by: Ben Levinsky Tested-by: Peng Fan #i.MX8MP-EVK Link: https://lore.kernel.org/r/20260529021637.2077602-2-ben.levinsky@amd.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/remoteproc_internal.h | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 0a5e15744b1d..46080c1c030e 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -14,6 +14,7 @@ #include #include +#include struct rproc; @@ -122,6 +123,31 @@ rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...); void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev); void rproc_remove_rvdev(struct rproc_vdev *rvdev); +static inline int rproc_mem_entry_ioremap_wc(struct rproc *rproc, + struct rproc_mem_entry *mem) +{ + void __iomem *va; + + va = ioremap_wc(mem->dma, mem->len); + if (!va) { + dev_err(&rproc->dev, "Unable to map memory region: %pa+%zx\n", + &mem->dma, mem->len); + return -ENOMEM; + } + + mem->va = (__force void *)va; + + return 0; +} + +static inline int rproc_mem_entry_iounmap(struct rproc *rproc, + struct rproc_mem_entry *mem) +{ + iounmap((__force __iomem void *)mem->va); + + return 0; +} + static inline int rproc_prepare_device(struct rproc *rproc) { if (rproc->ops->prepare) From aef86ae680361cf309cf18678a88b1257dcb9a84 Mon Sep 17 00:00:00 2001 From: Ben Levinsky Date: Thu, 28 May 2026 19:16:34 -0700 Subject: [PATCH 02/64] remoteproc: Switch exact-match drivers to wc-ioremap callbacks Replace the exact-match carveout map and unmap callbacks in the existing remoteproc drivers with the common wc-ioremap helpers. This covers xlnx_r5_remoteproc, rcar_rproc, st_remoteproc, stm32_rproc, imx_rproc, and imx_dsp_rproc. Leave the zynqmp R5 TCM callbacks alone because they also clear the mapped memory and are therefore not exact matches for the shared helpers. Signed-off-by: Ben Levinsky Reviewed-by: Geert Uytterhoeven # renesas Tested-by: Peng Fan #i.MX8MP-EVK Link: https://lore.kernel.org/r/20260529021637.2077602-3-ben.levinsky@amd.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 36 ++++--------------- drivers/remoteproc/imx_rproc.c | 32 ++--------------- drivers/remoteproc/rcar_rproc.c | 33 ++--------------- drivers/remoteproc/st_remoteproc.c | 31 ++-------------- drivers/remoteproc/stm32_rproc.c | 33 ++--------------- drivers/remoteproc/xlnx_r5_remoteproc.c | 47 +++---------------------- 6 files changed, 18 insertions(+), 194 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 008741af9f11..2d9f14fbef1d 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -644,32 +644,6 @@ static void imx_dsp_rproc_free_mbox(struct imx_dsp_rproc *priv) mbox_free_channel(priv->rxdb_ch); } -static int imx_dsp_rproc_mem_alloc(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - struct device *dev = rproc->dev.parent; - void *va; - - va = ioremap_wc(mem->dma, mem->len); - if (!va) { - dev_err(dev, "Unable to map memory region: %pa+%zx\n", - &mem->dma, mem->len); - return -ENOMEM; - } - - mem->va = va; - - return 0; -} - -static int imx_dsp_rproc_mem_release(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - iounmap(mem->va); - - return 0; -} - /** * imx_dsp_rproc_add_carveout() - request mailbox channels * @priv: private data pointer @@ -700,8 +674,10 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) /* Register memory region */ mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)att->sa, - att->size, da, imx_dsp_rproc_mem_alloc, - imx_dsp_rproc_mem_release, "dsp_mem"); + att->size, da, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, + "dsp_mem"); if (mem) rproc_coredump_add_segment(rproc, da, att->size); @@ -732,8 +708,8 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) /* Register memory region */ mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)res.start, resource_size(&res), da, - imx_dsp_rproc_mem_alloc, - imx_dsp_rproc_mem_release, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, "%.*s", strchrnul(res.name, '@') - res.name, res.name); if (!mem) return -ENOMEM; diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 7662ebd9d2f4..bb23ebc15d64 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -600,35 +600,6 @@ static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *i return va; } -static int imx_rproc_mem_alloc(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - struct device *dev = rproc->dev.parent; - void *va; - - dev_dbg(dev, "map memory: %p+%zx\n", &mem->dma, mem->len); - va = ioremap_wc(mem->dma, mem->len); - if (IS_ERR_OR_NULL(va)) { - dev_err(dev, "Unable to map memory region: %p+%zx\n", - &mem->dma, mem->len); - return -ENOMEM; - } - - /* Update memory entry va */ - mem->va = va; - - return 0; -} - -static int imx_rproc_mem_release(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma); - iounmap(mem->va); - - return 0; -} - static int imx_rproc_sm_lmm_prepare(struct rproc *rproc) { struct imx_rproc *priv = rproc->priv; @@ -692,7 +663,8 @@ static int imx_rproc_prepare(struct rproc *rproc) /* Register memory region */ mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)res.start, resource_size(&res), da, - imx_rproc_mem_alloc, imx_rproc_mem_release, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, "%.*s", strchrnul(res.name, '@') - res.name, res.name); if (!mem) diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c index 3c25625f966d..e3121fadd292 100644 --- a/drivers/remoteproc/rcar_rproc.c +++ b/drivers/remoteproc/rcar_rproc.c @@ -19,35 +19,6 @@ struct rcar_rproc { struct reset_control *rst; }; -static int rcar_rproc_mem_alloc(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - struct device *dev = &rproc->dev; - void *va; - - dev_dbg(dev, "map memory: %pa+%zx\n", &mem->dma, mem->len); - va = ioremap_wc(mem->dma, mem->len); - if (!va) { - dev_err(dev, "Unable to map memory region: %pa+%zx\n", - &mem->dma, mem->len); - return -ENOMEM; - } - - /* Update memory entry va */ - mem->va = va; - - return 0; -} - -static int rcar_rproc_mem_release(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - dev_dbg(&rproc->dev, "unmap memory: %pa\n", &mem->dma); - iounmap(mem->va); - - return 0; -} - static int rcar_rproc_prepare(struct rproc *rproc) { struct device *dev = rproc->dev.parent; @@ -73,8 +44,8 @@ static int rcar_rproc_prepare(struct rproc *rproc) mem = rproc_mem_entry_init(dev, NULL, res.start, resource_size(&res), da, - rcar_rproc_mem_alloc, - rcar_rproc_mem_release, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, res.name); if (!mem) diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c index a07edf7217d2..486180cdccb4 100644 --- a/drivers/remoteproc/st_remoteproc.c +++ b/drivers/remoteproc/st_remoteproc.c @@ -88,33 +88,6 @@ static void st_rproc_kick(struct rproc *rproc, int vqid) dev_err(dev, "failed to send message via mbox: %d\n", ret); } -static int st_rproc_mem_alloc(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - struct device *dev = rproc->dev.parent; - void *va; - - va = ioremap_wc(mem->dma, mem->len); - if (!va) { - dev_err(dev, "Unable to map memory region: %pa+%zx\n", - &mem->dma, mem->len); - return -ENOMEM; - } - - /* Update memory entry va */ - mem->va = va; - - return 0; -} - -static int st_rproc_mem_release(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - iounmap(mem->va); - - return 0; -} - static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) { struct device *dev = rproc->dev.parent; @@ -138,8 +111,8 @@ static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)res.start, resource_size(&res), res.start, - st_rproc_mem_alloc, - st_rproc_mem_release, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, "%.*s", strchrnul(res.name, '@') - res.name, res.name); diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index 632614013dc6..a6e36a11627d 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -113,35 +113,6 @@ static int stm32_rproc_pa_to_da(struct rproc *rproc, phys_addr_t pa, u64 *da) return -EINVAL; } -static int stm32_rproc_mem_alloc(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - struct device *dev = rproc->dev.parent; - void *va; - - dev_dbg(dev, "map memory: %pad+%zx\n", &mem->dma, mem->len); - va = (__force void *)ioremap_wc(mem->dma, mem->len); - if (IS_ERR_OR_NULL(va)) { - dev_err(dev, "Unable to map memory region: %pad+0x%zx\n", - &mem->dma, mem->len); - return -ENOMEM; - } - - /* Update memory entry va */ - mem->va = va; - - return 0; -} - -static int stm32_rproc_mem_release(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma); - iounmap((__force __iomem void *)mem->va); - - return 0; -} - static int stm32_rproc_of_memory_translations(struct platform_device *pdev, struct stm32_rproc *ddata) { @@ -237,8 +208,8 @@ static int stm32_rproc_prepare(struct rproc *rproc) mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)res.start, resource_size(&res), da, - stm32_rproc_mem_alloc, - stm32_rproc_mem_release, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, "%.*s", strchrnul(res.name, '@') - res.name, res.name); if (mem) diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c index 3349d1877751..59e7b10a6f26 100644 --- a/drivers/remoteproc/xlnx_r5_remoteproc.c +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c @@ -451,45 +451,6 @@ static int zynqmp_r5_rproc_stop(struct rproc *rproc) return ret; } -/* - * zynqmp_r5_mem_region_map() - * @rproc: single R5 core's corresponding rproc instance - * @mem: mem descriptor to map reserved memory-regions - * - * Callback to map va for memory-region's carveout. - * - * return 0 on success, otherwise non-zero value on failure - */ -static int zynqmp_r5_mem_region_map(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - void __iomem *va; - - va = ioremap_wc(mem->dma, mem->len); - if (IS_ERR_OR_NULL(va)) - return -ENOMEM; - - mem->va = (void *)va; - - return 0; -} - -/* - * zynqmp_r5_rproc_mem_unmap - * @rproc: single R5 core's corresponding rproc instance - * @mem: mem entry to unmap - * - * Unmap memory-region carveout - * - * return: always returns 0 - */ -static int zynqmp_r5_mem_region_unmap(struct rproc *rproc, - struct rproc_mem_entry *mem) -{ - iounmap((void __iomem *)mem->va); - return 0; -} - /* * add_mem_regions_carveout() * @rproc: single R5 core's corresponding rproc instance @@ -526,8 +487,8 @@ static int add_mem_regions_carveout(struct rproc *rproc) rproc_mem = rproc_mem_entry_init(&rproc->dev, NULL, (dma_addr_t)res.start, resource_size(&res), res.start, - zynqmp_r5_mem_region_map, - zynqmp_r5_mem_region_unmap, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, "%.*s", strchrnul(res.name, '@') - res.name, res.name); @@ -564,8 +525,8 @@ static int add_sram_carveouts(struct rproc *rproc) rproc_mem = rproc_mem_entry_init(&rproc->dev, NULL, dma_addr, len, da, - zynqmp_r5_mem_region_map, - zynqmp_r5_mem_region_unmap, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, sram->sram_res.name); if (!rproc_mem) { dev_err(&rproc->dev, "failed to add sram %s da=0x%x, size=0x%lx", From 0db071a39c8637262a00763adfc44c2fae89c82c Mon Sep 17 00:00:00 2001 From: Ben Levinsky Date: Thu, 28 May 2026 19:16:35 -0700 Subject: [PATCH 03/64] remoteproc: Mark wc-ioremap carveouts as iomem Carveouts registered through the shared wc-ioremap helper are backed by I/O memory, but rproc_da_to_va() only reports that to its callers when mem->is_iomem is set on the carveout. Without that flag, the remoteproc ELF loader and coredump paths can fall back to normal memcpy()/memset() accessors instead of the I/O helpers used for iomapped memory. Mark shared wc-ioremap carveouts as iomem so the framework uses the proper memcpy_toio(), memset_io(), and memcpy_fromio() accessors for these regions. Signed-off-by: Ben Levinsky Tested-by: Peng Fan #i.MX8MP-EVK Link: https://lore.kernel.org/r/20260529021637.2077602-4-ben.levinsky@amd.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/remoteproc_internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 46080c1c030e..9afda697271d 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -136,6 +136,7 @@ static inline int rproc_mem_entry_ioremap_wc(struct rproc *rproc, } mem->va = (__force void *)va; + mem->is_iomem = true; return 0; } From e6b4e660f08894ef8fa2aaee3ef5c0f86ae4c59d Mon Sep 17 00:00:00 2001 From: Ben Levinsky Date: Thu, 28 May 2026 19:16:36 -0700 Subject: [PATCH 04/64] remoteproc: Add helper for optional ELF resource tables Add a helper macro around rproc_elf_load_rsc_table() for thin parse_fw() wrappers that treat a missing ELF resource table as optional while keeping per-driver logging decisions local to the caller of rproc_elf_load_rsc_table_optional(). Signed-off-by: Ben Levinsky Tested-by: Peng Fan #i.MX8MP-EVK Link: https://lore.kernel.org/r/20260529021637.2077602-5-ben.levinsky@amd.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/remoteproc_internal.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 9afda697271d..02c00475b010 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -149,6 +149,17 @@ static inline int rproc_mem_entry_iounmap(struct rproc *rproc, return 0; } +#define rproc_elf_load_rsc_table_optional(rproc, fw, dev_func, fmt, ...) \ + ({ \ + int ret = rproc_elf_load_rsc_table(rproc, fw); \ + if (ret == -EINVAL) { \ + dev_func(&rproc->dev, fmt, ##__VA_ARGS__); \ + return 0; \ + } else { \ + return ret; \ + } \ + }) + static inline int rproc_prepare_device(struct rproc *rproc) { if (rproc->ops->prepare) From 65bb7dee37f1858d5920e9bfd48f7cd96bf421e4 Mon Sep 17 00:00:00 2001 From: Ben Levinsky Date: Thu, 28 May 2026 19:16:37 -0700 Subject: [PATCH 05/64] remoteproc: Switch drivers to optional resource-table helper Use the shared optional resource-table helper in the remoteproc drivers that already treat a missing resource table as non-fatal: xlnx_r5_remoteproc, rcar_rproc, stm32_rproc, imx_rproc, and imx_dsp_rproc. Keep thin local parse_fw() wrappers in each driver so the helper only centralizes the return-value handling while each platform retains control over whether the missing-table case is logged and at what severity. Signed-off-by: Ben Levinsky Tested-by: Peng Fan #i.MX8MP-EVK Link: https://lore.kernel.org/r/20260529021637.2077602-6-ben.levinsky@amd.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 5 ++--- drivers/remoteproc/imx_rproc.c | 8 ++------ drivers/remoteproc/rcar_rproc.c | 8 ++------ drivers/remoteproc/stm32_rproc.c | 6 ++---- drivers/remoteproc/xlnx_r5_remoteproc.c | 23 +++++++++-------------- 5 files changed, 17 insertions(+), 33 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 2d9f14fbef1d..fd60c67ba8a9 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -956,9 +956,8 @@ static int imx_dsp_rproc_elf_load_segments(struct rproc *rproc, const struct fir static int imx_dsp_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) { - if (rproc_elf_load_rsc_table(rproc, fw)) - dev_warn(&rproc->dev, "no resource table found for this firmware\n"); - + rproc_elf_load_rsc_table_optional(rproc, fw, dev_warn, + "no resource table found for this firmware\n"); return 0; } diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index bb23ebc15d64..745ce52cd822 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -682,12 +682,8 @@ static int imx_rproc_prepare(struct rproc *rproc) static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) { - int ret; - - ret = rproc_elf_load_rsc_table(rproc, fw); - if (ret) - dev_info(&rproc->dev, "No resource table in elf\n"); - + rproc_elf_load_rsc_table_optional(rproc, fw, dev_info, + "No resource table in elf\n"); return 0; } diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c index e3121fadd292..1fe6c01bde40 100644 --- a/drivers/remoteproc/rcar_rproc.c +++ b/drivers/remoteproc/rcar_rproc.c @@ -57,12 +57,8 @@ static int rcar_rproc_prepare(struct rproc *rproc) static int rcar_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) { - int ret; - - ret = rproc_elf_load_rsc_table(rproc, fw); - if (ret) - dev_info(&rproc->dev, "No resource table in elf\n"); - + rproc_elf_load_rsc_table_optional(rproc, fw, dev_info, + "No resource table in elf\n"); return 0; } diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index a6e36a11627d..0e5d64fbe52c 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -234,9 +234,8 @@ static int stm32_rproc_prepare(struct rproc *rproc) static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) { - if (rproc_elf_load_rsc_table(rproc, fw)) - dev_warn(&rproc->dev, "no resource table found for this firmware\n"); - + rproc_elf_load_rsc_table_optional(rproc, fw, dev_warn, + "no resource table found for this firmware\n"); return 0; } @@ -928,4 +927,3 @@ MODULE_DESCRIPTION("STM32 Remote Processor Control Driver"); MODULE_AUTHOR("Ludovic Barre "); MODULE_AUTHOR("Fabien Dessenne "); MODULE_LICENSE("GPL v2"); - diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c index 59e7b10a6f26..7000f08975f0 100644 --- a/drivers/remoteproc/xlnx_r5_remoteproc.c +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c @@ -679,20 +679,15 @@ release_tcm: */ static int zynqmp_r5_parse_fw(struct rproc *rproc, const struct firmware *fw) { - int ret; - - ret = rproc_elf_load_rsc_table(rproc, fw); - if (ret == -EINVAL) { - /* - * resource table only required for IPC. - * if not present, this is not necessarily an error; - * for example, loading r5 hello world application - * so simply inform user and keep going. - */ - dev_info(&rproc->dev, "no resource table found.\n"); - ret = 0; - } - return ret; + /* + * resource table only required for IPC. + * if not present, this is not necessarily an error; + * for example, loading r5 hello world application + * so simply inform user and keep going. + */ + rproc_elf_load_rsc_table_optional(rproc, fw, dev_info, + "no resource table found.\n"); + return 0; } /** From 738a5c60c37460a09dbd5c3c85f4207e5938ca5e Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Fri, 12 Jun 2026 16:49:58 -0500 Subject: [PATCH 06/64] remoteproc: Use presence checks for syscon props The OMAP and Keystone remoteproc drivers only need to know whether "ti,bootreg" and "ti,syscon-dev" are present before parsing them. Reading those properties as booleans misrepresents their DT encoding. Use of_property_present() for the presence tests and keep the existing phandle parsing for the actual property values. Assisted-by: Codex:gpt-5-5 Signed-off-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20260612214959.1884404-1-robh@kernel.org Signed-off-by: Mathieu Poirier --- drivers/remoteproc/keystone_remoteproc.c | 2 +- drivers/remoteproc/omap_remoteproc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c index e7fde5509786..83763d640c4e 100644 --- a/drivers/remoteproc/keystone_remoteproc.c +++ b/drivers/remoteproc/keystone_remoteproc.c @@ -317,7 +317,7 @@ static int keystone_rproc_of_get_dev_syscon(struct platform_device *pdev, struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; - if (!of_property_read_bool(np, "ti,syscon-dev")) { + if (!of_property_present(np, "ti,syscon-dev")) { dev_err(dev, "ti,syscon-dev property is absent\n"); return -EINVAL; } diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index cb01354248af..6ed0f28edac9 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -1140,7 +1140,7 @@ static int omap_rproc_get_boot_data(struct platform_device *pdev, if (!data) return -ENODEV; - if (!of_property_read_bool(np, "ti,bootreg")) + if (!of_property_present(np, "ti,bootreg")) return 0; oproc->boot_data = devm_kzalloc(&pdev->dev, sizeof(*oproc->boot_data), From 70cfc11cfcfb07ca8eeed1f667cc0eec9e82aa71 Mon Sep 17 00:00:00 2001 From: Tanmay Shah Date: Fri, 19 Jun 2026 09:38:54 -0700 Subject: [PATCH 07/64] remoteproc: xlnx: Refactor start & stop ops Current _start and _stop ops are implemented using various APIs from the platform management firmware driver. Instead provide respective RPU start and stop API in the firmware driver and move the logic to interact with the PM firmware in the firmware driver. The remoteproc driver doesn't need to know actual logic, but only the final result i.e. RPU start/stop was success or not. This refactor keeps the remoteproc driver simple and moves firmware interaction logic to the firmware driver. Signed-off-by: Tanmay Shah Acked-by: Michal Simek Link: https://lore.kernel.org/r/20260619163854.410392-1-tanmay.shah@amd.com Signed-off-by: Mathieu Poirier --- drivers/firmware/xilinx/zynqmp.c | 93 +++++++++++++++++++++++++ drivers/remoteproc/xlnx_r5_remoteproc.c | 68 ++---------------- include/linux/firmware/xlnx-zynqmp.h | 12 ++++ 3 files changed, 110 insertions(+), 63 deletions(-) diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index af838b2dc327..f9a3a95b0638 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -1513,6 +1513,99 @@ int zynqmp_pm_request_wake(const u32 node, } EXPORT_SYMBOL_GPL(zynqmp_pm_request_wake); +/** + * zynqmp_pm_start_rpu - Boot Real-time Processing Unit (Cortex-R) on SoC + * + * @node: power-domains id of the core + * @bootaddr: Boot address of elf + * + * Return: status, either success or error+reason + */ +int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr) +{ + enum rpu_boot_mem bootmem; + int ret; + + /* + * The exception vector pointers (EVP) refer to the base-address of + * exception vectors (for reset, IRQ, FIQ, etc). The reset-vector + * starts at the base-address and subsequent vectors are on 4-byte + * boundaries. + * + * Exception vectors can start either from 0x0000_0000 (LOVEC) or + * from 0xFFFF_0000 (HIVEC) which is mapped in the OCM (On-Chip Memory) + * + * Usually firmware will put Exception vectors at LOVEC. + * + * It is not recommend that you change the exception vector. + * Changing the EVP to HIVEC will result in increased interrupt latency + * and jitter. Also, if the OCM is secured and the Cortex-R5F processor + * is non-secured, then the Cortex-R5F processor cannot access the + * HIVEC exception vectors in the OCM. + */ + bootmem = (bootaddr >= 0xFFFC0000) ? + PM_RPU_BOOTMEM_HIVEC : PM_RPU_BOOTMEM_LOVEC; + + pr_debug("RPU boot addr 0x%llx from %s.", bootaddr, + bootmem == PM_RPU_BOOTMEM_HIVEC ? "OCM" : "TCM"); + + /* Request node before starting RPU core if new version of API is supported */ + if (zynqmp_pm_feature(PM_REQUEST_NODE) > PM_API_VERSION_1) { + ret = zynqmp_pm_request_node(node, + ZYNQMP_PM_CAPABILITY_ACCESS, 0, + ZYNQMP_PM_REQUEST_ACK_BLOCKING); + if (ret < 0) { + pr_err("failed to request 0x%x", node); + return ret; + } + } + + ret = zynqmp_pm_request_wake(node, true, + bootmem, ZYNQMP_PM_REQUEST_ACK_NO); + if (ret) + pr_err("failed to start RPU = 0x%x\n", node); + return ret; +} +EXPORT_SYMBOL_GPL(zynqmp_pm_start_rpu); + +/** + * zynqmp_pm_stop_rpu - Stop Real-time Processing Unit (Cortex-R) on SoC + * + * @node: power-domains id of the core + * + * Return: status, either success or error+reason + */ +int zynqmp_pm_stop_rpu(const u32 node) +{ + int ret; + + /* Use release node API to stop core if new version of API is supported */ + if (zynqmp_pm_feature(PM_RELEASE_NODE) > PM_API_VERSION_1) { + ret = zynqmp_pm_release_node(node); + if (ret) + pr_err("failed to stop remoteproc RPU %d\n", ret); + return ret; + } + + /* + * Check expected version of EEMI call before calling it. This avoids + * any error or warning prints from firmware as it is expected that fw + * doesn't support it. + */ + if (zynqmp_pm_feature(PM_FORCE_POWERDOWN) != PM_API_VERSION_1) { + pr_debug("EEMI interface %d ver 1 not supported\n", + PM_FORCE_POWERDOWN); + return -EOPNOTSUPP; + } + + /* maintain force pwr down for backward compatibility */ + ret = zynqmp_pm_force_pwrdwn(node, ZYNQMP_PM_REQUEST_ACK_BLOCKING); + if (ret) + pr_err("core force power down failed\n"); + return ret; +} +EXPORT_SYMBOL_GPL(zynqmp_pm_stop_rpu); + /** * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves * @node: Node ID of the slave diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c index 7000f08975f0..7014d48c1228 100644 --- a/drivers/remoteproc/xlnx_r5_remoteproc.c +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c @@ -364,49 +364,12 @@ static void zynqmp_r5_rproc_kick(struct rproc *rproc, int vqid) static int zynqmp_r5_rproc_start(struct rproc *rproc) { struct zynqmp_r5_core *r5_core = rproc->priv; - enum rpu_boot_mem bootmem; int ret; - /* - * The exception vector pointers (EVP) refer to the base-address of - * exception vectors (for reset, IRQ, FIQ, etc). The reset-vector - * starts at the base-address and subsequent vectors are on 4-byte - * boundaries. - * - * Exception vectors can start either from 0x0000_0000 (LOVEC) or - * from 0xFFFF_0000 (HIVEC) which is mapped in the OCM (On-Chip Memory) - * - * Usually firmware will put Exception vectors at LOVEC. - * - * It is not recommend that you change the exception vector. - * Changing the EVP to HIVEC will result in increased interrupt latency - * and jitter. Also, if the OCM is secured and the Cortex-R5F processor - * is non-secured, then the Cortex-R5F processor cannot access the - * HIVEC exception vectors in the OCM. - */ - bootmem = (rproc->bootaddr >= 0xFFFC0000) ? - PM_RPU_BOOTMEM_HIVEC : PM_RPU_BOOTMEM_LOVEC; - - dev_dbg(r5_core->dev, "RPU boot addr 0x%llx from %s.", rproc->bootaddr, - bootmem == PM_RPU_BOOTMEM_HIVEC ? "OCM" : "TCM"); - - /* Request node before starting RPU core if new version of API is supported */ - if (zynqmp_pm_feature(PM_REQUEST_NODE) > 1) { - ret = zynqmp_pm_request_node(r5_core->pm_domain_id, - ZYNQMP_PM_CAPABILITY_ACCESS, 0, - ZYNQMP_PM_REQUEST_ACK_BLOCKING); - if (ret < 0) { - dev_err(r5_core->dev, "failed to request 0x%x", - r5_core->pm_domain_id); - return ret; - } - } - - ret = zynqmp_pm_request_wake(r5_core->pm_domain_id, 1, - bootmem, ZYNQMP_PM_REQUEST_ACK_NO); + ret = zynqmp_pm_start_rpu(r5_core->pm_domain_id, rproc->bootaddr); if (ret) - dev_err(r5_core->dev, - "failed to start RPU = 0x%x\n", r5_core->pm_domain_id); + dev_err(&rproc->dev, "failed to start RPU\n"); + return ret; } @@ -423,30 +386,9 @@ static int zynqmp_r5_rproc_stop(struct rproc *rproc) struct zynqmp_r5_core *r5_core = rproc->priv; int ret; - /* Use release node API to stop core if new version of API is supported */ - if (zynqmp_pm_feature(PM_RELEASE_NODE) > 1) { - ret = zynqmp_pm_release_node(r5_core->pm_domain_id); - if (ret) - dev_err(r5_core->dev, "failed to stop remoteproc RPU %d\n", ret); - return ret; - } - - /* - * Check expected version of EEMI call before calling it. This avoids - * any error or warning prints from firmware as it is expected that fw - * doesn't support it. - */ - if (zynqmp_pm_feature(PM_FORCE_POWERDOWN) != 1) { - dev_dbg(r5_core->dev, "EEMI interface %d ver 1 not supported\n", - PM_FORCE_POWERDOWN); - return -EOPNOTSUPP; - } - - /* maintain force pwr down for backward compatibility */ - ret = zynqmp_pm_force_pwrdwn(r5_core->pm_domain_id, - ZYNQMP_PM_REQUEST_ACK_BLOCKING); + ret = zynqmp_pm_stop_rpu(r5_core->pm_domain_id); if (ret) - dev_err(r5_core->dev, "core force power down failed\n"); + dev_err(&rproc->dev, "failed to stop RPU\n"); return ret; } diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index 7e27b0f7bf7e..347df66ee176 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -644,6 +644,8 @@ int zynqmp_pm_get_node_status(const u32 node, u32 *const status, u32 *const requirements, u32 *const usage); int zynqmp_pm_get_rpu_node_status(const u32 node, u32 *const status, u32 *const requirements, u32 *const usage); +int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr); +int zynqmp_pm_stop_rpu(const u32 node); int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value); int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config, u32 value); @@ -960,6 +962,16 @@ static inline int zynqmp_pm_get_rpu_node_status(const u32 node, u32 *const statu return -ENODEV; } +static inline int zynqmp_pm_start_rpu(const u32 node, const u64 bootaddr) +{ + return -ENODEV; +} + +static inline int zynqmp_pm_stop_rpu(const u32 node) +{ + return -ENODEV; +} + static inline int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 value) From 52543154836e79e0389489e8578db764bce8c6a8 Mon Sep 17 00:00:00 2001 From: Ben Levinsky Date: Tue, 30 Jun 2026 10:40:56 -0700 Subject: [PATCH 08/64] remoteproc: guard wc-ioremap helpers with HAS_IOMEM The common wc-ioremap carveout callbacks live in remoteproc_internal.h, which is included by the remoteproc core. This means the helper bodies are parsed even for builds that do not enable any platform driver using those callbacks. On s390, CONFIG_HAS_IOMEM and CONFIG_GENERIC_IOREMAP depend on CONFIG_PCI. A randconfig with CONFIG_REMOTEPROC=y and CONFIG_PCI=n therefore has no usable ioremap_wc() or iounmap() declarations, and fails to build the common remoteproc objects with implicit declarations from the helper bodies. Only include linux/io.h and build the real wc-ioremap helpers when CONFIG_HAS_IOMEM is enabled. Provide no-IOMEM stubs so the internal header remains self-contained for randconfig and COMPILE_TEST coverage. Fixes: 50227acbf4e5 ("remoteproc: Add common wc-ioremap carveout callbacks") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202606301559.w8eorNQ2-lkp@intel.com/ Signed-off-by: Ben Levinsky Link: https://lore.kernel.org/r/20260630174056.667646-1-ben.levinsky@amd.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/remoteproc_internal.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 02c00475b010..3a742ef6ef60 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h @@ -14,7 +14,9 @@ #include #include +#ifdef CONFIG_HAS_IOMEM #include +#endif struct rproc; @@ -123,6 +125,7 @@ rproc_find_carveout_by_name(struct rproc *rproc, const char *name, ...); void rproc_add_rvdev(struct rproc *rproc, struct rproc_vdev *rvdev); void rproc_remove_rvdev(struct rproc_vdev *rvdev); +#ifdef CONFIG_HAS_IOMEM static inline int rproc_mem_entry_ioremap_wc(struct rproc *rproc, struct rproc_mem_entry *mem) { @@ -148,6 +151,19 @@ static inline int rproc_mem_entry_iounmap(struct rproc *rproc, return 0; } +#else +static inline int rproc_mem_entry_ioremap_wc(struct rproc *rproc, + struct rproc_mem_entry *mem) +{ + return -EOPNOTSUPP; +} + +static inline int rproc_mem_entry_iounmap(struct rproc *rproc, + struct rproc_mem_entry *mem) +{ + return 0; +} +#endif #define rproc_elf_load_rsc_table_optional(rproc, fw, dev_func, fmt, ...) \ ({ \ From 9698acea9b21937877d7d301883a6c8277a08900 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 23 Jun 2026 03:05:17 -0700 Subject: [PATCH 09/64] dt-bindings: remoteproc: qcom: cleanup qcom,adsp.yaml Items in qcom,adsp.yaml has common clock and interrupt properties, move these out of the allOf section to avoid list the compatible repeatly. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Jingyi Wang Link: https://lore.kernel.org/r/20260623-knp-soccp-v7-1-1ec7bb5c9fec@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../bindings/remoteproc/qcom,adsp.yaml | 64 ++++--------------- 1 file changed, 14 insertions(+), 50 deletions(-) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index 16a245fe2738..a270834605da 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -32,6 +32,14 @@ properties: reg: maxItems: 1 + clocks: + items: + - description: XO clock + + clock-names: + items: + - const: xo + cx-supply: true px-supply: @@ -49,6 +57,12 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + maxItems: 5 + + interrupt-names: + maxItems: 5 + required: - compatible - memory-region @@ -57,56 +71,6 @@ unevaluatedProperties: false allOf: - $ref: /schemas/remoteproc/qcom,pas-common.yaml# - - if: - properties: - compatible: - contains: - enum: - - qcom,msm8226-adsp-pil - - qcom,msm8953-adsp-pil - - qcom,msm8974-adsp-pil - - qcom,msm8996-adsp-pil - - qcom,msm8996-slpi-pil - - qcom,msm8998-adsp-pas - - qcom,msm8998-slpi-pas - - qcom,sdm660-adsp-pas - - qcom,sdm660-cdsp-pas - - qcom,sdm845-adsp-pas - - qcom,sdm845-cdsp-pas - - qcom,sdm845-slpi-pas - then: - properties: - clocks: - items: - - description: XO clock - clock-names: - items: - - const: xo - - - if: - properties: - compatible: - contains: - enum: - - qcom,msm8226-adsp-pil - - qcom,msm8953-adsp-pil - - qcom,msm8974-adsp-pil - - qcom,msm8996-adsp-pil - - qcom,msm8996-slpi-pil - - qcom,msm8998-adsp-pas - - qcom,msm8998-slpi-pas - - qcom,sdm660-adsp-pas - - qcom,sdm660-cdsp-pas - - qcom,sdm845-adsp-pas - - qcom,sdm845-cdsp-pas - - qcom,sdm845-slpi-pas - then: - properties: - interrupts: - maxItems: 5 - interrupt-names: - maxItems: 5 - - if: properties: compatible: From 5eb8427596322c9c51638b906f39acff7c10c963 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 23 Jun 2026 03:05:18 -0700 Subject: [PATCH 10/64] dt-bindings: remoteproc: qcom: move interrupts and interrupt-names list out of pas-common Move interrupts and interrupt-names list out of pas-common since they will be redefined differently for Kaanapali SoCCP. Signed-off-by: Jingyi Wang Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260623-knp-soccp-v7-2-1ec7bb5c9fec@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../bindings/remoteproc/qcom,adsp.yaml | 14 +++++++++++-- .../bindings/remoteproc/qcom,milos-pas.yaml | 18 +++++++++++++---- .../bindings/remoteproc/qcom,pas-common.yaml | 16 ++------------- .../bindings/remoteproc/qcom,qcs404-pas.yaml | 14 +++++++++++-- .../bindings/remoteproc/qcom,sa8775p-pas.yaml | 14 +++++++++++-- .../bindings/remoteproc/qcom,sc7180-pas.yaml | 20 +++++++++++++++++++ .../remoteproc/qcom,sc8280xp-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sdx55-pas.yaml | 16 +++++++++++++-- .../bindings/remoteproc/qcom,shikra-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sm6115-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sm6350-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sm6375-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sm8150-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sm8350-pas.yaml | 20 +++++++++++++++++++ .../bindings/remoteproc/qcom,sm8550-pas.yaml | 20 +++++++++++++++++++ 15 files changed, 246 insertions(+), 26 deletions(-) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index a270834605da..16c35e15ee1b 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -58,10 +58,20 @@ properties: description: Firmware name for the Hexagon core interrupts: - maxItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt interrupt-names: - maxItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack required: - compatible diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml index e5cce0d05fc6..d22d50c1e1ea 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml @@ -34,12 +34,22 @@ properties: - const: xo interrupts: - minItems: 6 - maxItems: 6 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt interrupt-names: - minItems: 6 - maxItems: 6 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack qcom,qmp: $ref: /schemas/types.yaml#/definitions/phandle diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml index 4607b459131b..3847aadfa980 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml @@ -26,23 +26,11 @@ properties: interrupts: minItems: 5 - items: - - description: Watchdog interrupt - - description: Fatal interrupt - - description: Ready interrupt - - description: Handover interrupt - - description: Stop acknowledge interrupt - - description: Shutdown acknowledge interrupt + maxItems: 6 interrupt-names: minItems: 5 - items: - - const: wdog - - const: fatal - - const: ready - - const: handover - - const: stop-ack - - const: shutdown-ack + maxItems: 6 iommus: maxItems: 1 diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml index ad45fd00ae34..5854b3d2041d 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml @@ -32,10 +32,20 @@ properties: - const: xo interrupts: - maxItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt interrupt-names: - maxItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack power-domains: false power-domain-names: false diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml index bcd2bcf96e24..7f287e55896e 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml @@ -59,10 +59,20 @@ properties: - description: Memory region for main Firmware authentication interrupts: - maxItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt interrupt-names: - maxItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack required: - compatible diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml index 66b455d0a8e3..cb0a61fc301d 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml @@ -48,6 +48,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml index 8227527c1d77..fef9d7c39f3c 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml @@ -45,6 +45,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml index 8c4abde74915..2bbd427c6ea4 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml @@ -30,10 +30,22 @@ properties: - const: xo interrupts: - minItems: 6 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt interrupt-names: - minItems: 6 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack power-domains: items: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,shikra-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,shikra-pas.yaml index 253b14eb2b59..34a2f15e9361 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,shikra-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,shikra-pas.yaml @@ -51,6 +51,26 @@ properties: and devices related to the remoteproc core. unevaluatedProperties: false + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + qcom,smem-states: $ref: /schemas/types.yaml#/definitions/phandle-array description: States used by the AP to signal the Hexagon core diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml index eeb6a8aafeb9..987fac433fae 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml @@ -51,6 +51,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml index c1a3cc308bdb..53ffb1ccd199 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml @@ -45,6 +45,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml index 7286b2baa19f..6823a2a8d74e 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml @@ -39,6 +39,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + smd-edge: false required: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml index a8cddf7e2fe1..8a1fae095a3b 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml @@ -61,6 +61,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml index 6d09823153fc..4ea7518db537 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml @@ -55,6 +55,26 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index 9f30a38152a3..4721c04ce09b 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -75,6 +75,26 @@ properties: - description: DSM Memory region 2 - description: Memory region for Qlink Logging + interrupts: + minItems: 5 + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + minItems: 5 + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + required: - compatible - reg From 8b54bacadc0c17e735ea8cb45e78ff360803a302 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 23 Jun 2026 03:05:19 -0700 Subject: [PATCH 11/64] dt-bindings: remoteproc: qcom: Document pas for SoCCP on Kaanapali and Glymur platforms Document the component used to boot SoCCP on Kaanapali SoC and add compatible for Glymur SoCCP which could fallback to Kaanapali. Extend the "qcom,smem-states", "qcom,smem-state-names" in the pas-common and add maxItems constraints for SMEM properties in the documents that reference to pas-common. Signed-off-by: Jingyi Wang Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260623-knp-soccp-v7-3-1ec7bb5c9fec@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../bindings/remoteproc/qcom,adsp.yaml | 8 + .../remoteproc/qcom,kaanapali-soccp-pas.yaml | 154 ++++++++++++++++++ .../bindings/remoteproc/qcom,milos-pas.yaml | 8 + .../bindings/remoteproc/qcom,pas-common.yaml | 12 +- .../bindings/remoteproc/qcom,qcs404-pas.yaml | 8 + .../bindings/remoteproc/qcom,sa8775p-pas.yaml | 8 + .../bindings/remoteproc/qcom,sc7180-pas.yaml | 8 + .../remoteproc/qcom,sc8280xp-pas.yaml | 8 + .../bindings/remoteproc/qcom,sdx55-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm6115-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm6350-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm6375-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm8150-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm8350-pas.yaml | 8 + .../bindings/remoteproc/qcom,sm8550-pas.yaml | 8 + 15 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index 16c35e15ee1b..7e8ecae8e6cb 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -73,6 +73,14 @@ properties: - const: handover - const: stop-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - memory-region diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml new file mode 100644 index 000000000000..ce18460a949f --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/remoteproc/qcom,kaanapali-soccp-pas.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Kaanapali SoCCP Peripheral Authentication Service + +maintainers: + - Jingyi Wang + +description: + The SoC Control Processor (SoCCP) is a small RISC-V MCU that controls USB + Type-C, battery charging and various other functions on Qualcomm SoCs, somewhat + analogous to traditional PC Embedded Controllers. This document describes + the Peripheral Authentication Service that loads and boots firmware for SoCCP. + +properties: + compatible: + oneOf: + - items: + - enum: + - qcom,glymur-soccp-pas + - const: qcom,kaanapali-soccp-pas + - enum: + - qcom,kaanapali-soccp-pas + + reg: + maxItems: 1 + + clocks: + items: + - description: XO clock + + clock-names: + items: + - const: xo + + power-domains: + items: + - description: CX power domain + - description: MX power domain + + power-domain-names: + items: + - const: cx + - const: mx + + firmware-name: + items: + - description: Firmware name of the SoC Control Processor + - description: Firmware name of the SoCCP Devicetree + + memory-region: + items: + - description: Memory region for main Firmware authentication + - description: Memory region for Devicetree Firmware authentication + + interrupts: + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Pong interrupt + + interrupt-names: + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: pong + + qcom,smem-states: + minItems: 2 + description: States used by the AP to signal the SoC Control Processor + + qcom,smem-state-names: + minItems: 2 + description: The names of the state bits used for SMP2P output + +required: + - compatible + - reg + - memory-region + - power-domains + - power-domain-names + +allOf: + - $ref: /schemas/remoteproc/qcom,pas-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #define IPCC_MPROC_SOCCP + + remoteproc@d00000 { + compatible = "qcom,kaanapali-soccp-pas"; + reg = <0x00d00000 0x200000>; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + interrupts-extended = <&intc GIC_SPI 167 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>, + <&soccp_smp2p_in 9 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "pong"; + + memory-region = <&soccp_mem>, + <&soccp_dtb_mem_mem>; + + firmware-name = "qcom/kaanapali/soccp.mbn", + "qcom/kaanapali/soccp_dtb.mbn"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MX>; + power-domain-names = "cx", + "mx"; + + qcom,smem-states = <&soccp_smp2p_out 0>, + <&soccp_smp2p_out 8>; + qcom,smem-state-names = "stop", + "ping"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_MPROC_SOCCP + IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "soccp"; + qcom,remote-pid = <19>; + + /* ... */ + }; + }; diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml index d22d50c1e1ea..99d7337e58ec 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml @@ -69,6 +69,14 @@ properties: - description: Memory region for core Firmware authentication - description: Memory region for Devicetree Firmware authentication + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml index 3847aadfa980..11faf655f530 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,pas-common.yaml @@ -46,8 +46,16 @@ properties: qcom,smem-states: $ref: /schemas/types.yaml#/definitions/phandle-array description: States used by the AP to signal the Hexagon core + minItems: 1 items: - - description: Stop the modem + - description: Stop the remoteproc + items: + - description: Phandle to the Shared Memory Point 2 Point device + handling the communication with a remote processor + - description: Single bit index to toggle in the value sent to + the remote processor + maximum: 32 + - description: Ping the remoteproc items: - description: Phandle to the Shared Memory Point 2 Point device handling the communication with a remote processor @@ -57,8 +65,10 @@ properties: qcom,smem-state-names: description: The names of the state bits used for SMP2P output + minItems: 1 items: - const: stop + - const: ping smd-edge: $ref: /schemas/remoteproc/qcom,smd-edge.yaml# diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml index 5854b3d2041d..bf9bf1af9ff1 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,qcs404-pas.yaml @@ -59,6 +59,14 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml index 7f287e55896e..dda2d144b720 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sa8775p-pas.yaml @@ -74,6 +74,14 @@ properties: - const: handover - const: stop-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml index cb0a61fc301d..b20780e5e26b 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc7180-pas.yaml @@ -68,6 +68,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml index fef9d7c39f3c..4bbe4a986c7c 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml @@ -65,6 +65,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml index 2bbd427c6ea4..8c16b01c53e4 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sdx55-pas.yaml @@ -71,6 +71,14 @@ properties: maxItems: 1 description: Firmware name for the Hexagon core + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml index 987fac433fae..454ba82bd6f1 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6115-pas.yaml @@ -71,6 +71,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml index 53ffb1ccd199..42e02c64347a 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6350-pas.yaml @@ -65,6 +65,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml index 6823a2a8d74e..274f87880e2e 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm6375-pas.yaml @@ -61,6 +61,14 @@ properties: smd-edge: false + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml index 8a1fae095a3b..5a7c5f8c92d1 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8150-pas.yaml @@ -81,6 +81,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml index 4ea7518db537..72d0db5698c5 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8350-pas.yaml @@ -75,6 +75,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index 4721c04ce09b..faf7b2890de8 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -95,6 +95,14 @@ properties: - const: stop-ack - const: shutdown-ack + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + required: - compatible - reg From f45ec01bae29a96374690fa323b42717e62aa575 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Tue, 23 Jun 2026 03:05:20 -0700 Subject: [PATCH 12/64] dt-bindings: remoteproc: qcom: Document pas for SoCCP on Hawi and Maili SoC Document SoCCP remote processor used on Qualcomm Hawi and Maili SoC which is fully compatible with Kaanapali. Co-developed-by: Yijie Yang Signed-off-by: Yijie Yang Signed-off-by: Mukesh Ojha Signed-off-by: Jingyi Wang Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260623-knp-soccp-v7-4-1ec7bb5c9fec@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml index ce18460a949f..8fd6913e414d 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml @@ -21,6 +21,8 @@ properties: - items: - enum: - qcom,glymur-soccp-pas + - qcom,hawi-soccp-pas + - qcom,maili-soccp-pas - const: qcom,kaanapali-soccp-pas - enum: - qcom,kaanapali-soccp-pas From 16472c99f4699cb28f2f5f946400ead02f58a15e Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 23 Jun 2026 03:05:21 -0700 Subject: [PATCH 13/64] remoteproc: qcom: pas: Add late attach support for subsystems Subsystems can be brought out of reset by entities such as bootloaders. As the irq enablement could be later than subsystem bring up, the state of subsystem should be checked by reading SMP2P bits. A new qcom_pas_attach() function is introduced. if crash state is detected for the subsystem, rproc_report_crash() is called. If the ready state is detected meanwhile stop state is not detected, it will be marked as "attached", otherwise it could be the early boot feature is not supported by other entities or it has already been stopped. In above cases, the state will be marked as RPROC_OFFLINE so that the PAS driver can load the firmware and start the remoteproc. Co-developed-by: Gokul Krishna Krishnakumar Signed-off-by: Gokul Krishna Krishnakumar Tested-by: Shawn Guo Signed-off-by: Jingyi Wang Tested-by: Mukesh Ojha Link: https://lore.kernel.org/r/20260623-knp-soccp-v7-5-1ec7bb5c9fec@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_common.h | 6 +++ drivers/remoteproc/qcom_q6v5.c | 3 +- drivers/remoteproc/qcom_q6v5_pas.c | 68 ++++++++++++++++++++++++++++++ drivers/remoteproc/qcom_sysmon.c | 19 +++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/qcom_common.h b/drivers/remoteproc/qcom_common.h index b07fbaa091a0..b0e7e336d363 100644 --- a/drivers/remoteproc/qcom_common.h +++ b/drivers/remoteproc/qcom_common.h @@ -68,6 +68,7 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, int ssctl_instance); void qcom_remove_sysmon_subdev(struct qcom_sysmon *sysmon); bool qcom_sysmon_shutdown_acked(struct qcom_sysmon *sysmon); +bool qcom_sysmon_shutdown_irq_state(struct qcom_sysmon *sysmon); #else static inline struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, const char *name, @@ -84,6 +85,11 @@ static inline bool qcom_sysmon_shutdown_acked(struct qcom_sysmon *sysmon) { return false; } + +static inline bool qcom_sysmon_shutdown_irq_state(struct qcom_sysmon *sysmon) +{ + return false; +} #endif #endif diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index 58d5b85e58cd..a11d8ace554b 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -202,7 +202,8 @@ int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5, struct qcom_sysmon *sysmon) q6v5->running = false; /* Don't perform SMP2P dance if remote isn't running */ - if (q6v5->rproc->state != RPROC_RUNNING || qcom_sysmon_shutdown_acked(sysmon)) + if ((q6v5->rproc->state != RPROC_RUNNING && q6v5->rproc->state != RPROC_ATTACHED) || + qcom_sysmon_shutdown_acked(sysmon)) return 0; qcom_smem_state_update_bits(q6v5->state, diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 808e9609988d..8a0bb4b2e71c 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -60,6 +60,7 @@ struct qcom_pas_data { int region_assign_count; bool region_assign_shared; int region_assign_vmid; + bool early_boot; }; struct qcom_pas { @@ -507,6 +508,67 @@ static unsigned long qcom_pas_panic(struct rproc *rproc) return qcom_q6v5_panic(&pas->q6v5); } +static int qcom_pas_attach(struct rproc *rproc) +{ + struct qcom_pas *pas = rproc->priv; + bool ready_state; + bool crash_state; + bool stop_state; + int ret; + + pas->q6v5.handover_issued = true; + enable_irq(pas->q6v5.handover_irq); + + pas->q6v5.running = true; + ret = irq_get_irqchip_state(pas->q6v5.fatal_irq, + IRQCHIP_STATE_LINE_LEVEL, &crash_state); + if (ret) + goto disable_running; + + if (crash_state) { + dev_err(pas->dev, "Subsystem has crashed before driver probe\n"); + rproc_report_crash(rproc, RPROC_FATAL_ERROR); + ret = -EINVAL; + goto disable_running; + } + + ret = irq_get_irqchip_state(pas->q6v5.stop_irq, + IRQCHIP_STATE_LINE_LEVEL, &stop_state); + if (ret) + goto disable_running; + + if (stop_state || qcom_sysmon_shutdown_irq_state(pas->sysmon)) { + dev_info(pas->dev, "Subsystem found stop state set. Falling back to start.\n"); + goto unroll_attach; + } + + ret = irq_get_irqchip_state(pas->q6v5.ready_irq, + IRQCHIP_STATE_LINE_LEVEL, &ready_state); + if (ret) + goto disable_running; + + if (unlikely(!ready_state)) { + /* + * The bootloader may not support early boot, mark the state as + * RPROC_OFFLINE so that the PAS driver can load the firmware and + * start the remoteproc. + */ + dev_err(pas->dev, "Failed to get subsystem ready interrupt\n"); + goto unroll_attach; + } + + return 0; + +unroll_attach: + pas->rproc->state = RPROC_OFFLINE; + ret = -EINVAL; +disable_running: + disable_irq(pas->q6v5.handover_irq); + pas->q6v5.running = false; + + return ret; +} + static const struct rproc_ops qcom_pas_ops = { .unprepare = qcom_pas_unprepare, .start = qcom_pas_start, @@ -515,6 +577,7 @@ static const struct rproc_ops qcom_pas_ops = { .parse_fw = qcom_pas_parse_firmware, .load = qcom_pas_load, .panic = qcom_pas_panic, + .attach = qcom_pas_attach, }; static const struct rproc_ops qcom_pas_minidump_ops = { @@ -526,6 +589,7 @@ static const struct rproc_ops qcom_pas_minidump_ops = { .load = qcom_pas_load, .panic = qcom_pas_panic, .coredump = qcom_pas_minidump, + .attach = qcom_pas_attach, }; static int qcom_pas_init_clock(struct qcom_pas *pas) @@ -852,6 +916,10 @@ static int qcom_pas_probe(struct platform_device *pdev) pas->pas_ctx->use_tzmem = rproc->has_iommu; pas->dtb_pas_ctx->use_tzmem = rproc->has_iommu; + + if (desc->early_boot) + pas->rproc->state = RPROC_DETACHED; + ret = rproc_add(rproc); if (ret) goto remove_ssr_sysmon; diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c index 913e3b750a86..a0830a48b1f4 100644 --- a/drivers/remoteproc/qcom_sysmon.c +++ b/drivers/remoteproc/qcom_sysmon.c @@ -736,6 +736,25 @@ bool qcom_sysmon_shutdown_acked(struct qcom_sysmon *sysmon) } EXPORT_SYMBOL_GPL(qcom_sysmon_shutdown_acked); +bool qcom_sysmon_shutdown_irq_state(struct qcom_sysmon *sysmon) +{ + bool shutdown_state; + int ret; + + if (!sysmon) + return false; + + ret = irq_get_irqchip_state(sysmon->shutdown_irq, + IRQCHIP_STATE_LINE_LEVEL, &shutdown_state); + if (ret) { + dev_warn(sysmon->dev, "failed to get shutdown_state: %d\n", ret); + return false; + } + + return shutdown_state; +} +EXPORT_SYMBOL_GPL(qcom_sysmon_shutdown_irq_state); + /** * sysmon_probe() - probe sys_mon channel * @rpdev: rpmsg device handle From 1f9ecae2ec6aa473825d713221d43bae72fcdfe9 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 23 Jun 2026 03:05:22 -0700 Subject: [PATCH 14/64] remoteproc: qcom_q6v5_pas: Add SoCCP node on Kaanapali The SoC Control Processor (SoCCP) is small RISC-V MCU that controls USB Type-C, battery charging and various other functions on Qualcomm SoCs. It provides a solution for control-plane processing, reducing per-subsystem microcontroller reinvention. Add support for SoCCP PAS loader on Kaanapali platform. Reviewed-by: Dmitry Baryshkov Reviewed-by: Bartosz Golaszewski Signed-off-by: Jingyi Wang Tested-by: Mukesh Ojha # Hawi SoC Link: https://lore.kernel.org/r/20260623-knp-soccp-v7-6-1ec7bb5c9fec@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 8a0bb4b2e71c..60a4337d9e51 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -1640,8 +1640,26 @@ static const struct qcom_pas_data sm8750_mpss_resource = { .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA, }; +static const struct qcom_pas_data kaanapali_soccp_resource = { + .crash_reason_smem = 656, + .firmware_name = "soccp.mbn", + .dtb_firmware_name = "soccp_dtb.mbn", + .pas_id = 51, + .dtb_pas_id = 0x41, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + NULL + }, + .ssr_name = "soccp", + .sysmon_name = "soccp", + .auto_boot = true, + .early_boot = true, +}; + static const struct of_device_id qcom_pas_of_match[] = { { .compatible = "qcom,eliza-adsp-pas", .data = &sm8550_adsp_resource }, + { .compatible = "qcom,kaanapali-soccp-pas", .data = &kaanapali_soccp_resource }, { .compatible = "qcom,milos-adsp-pas", .data = &sm8550_adsp_resource }, { .compatible = "qcom,milos-cdsp-pas", .data = &milos_cdsp_resource }, { .compatible = "qcom,milos-mpss-pas", .data = &sm8450_mpss_resource }, From d93ffd549fb4df18c934ca7a47d4128a18c718cb Mon Sep 17 00:00:00 2001 From: Tanmay Shah Date: Mon, 29 Jun 2026 17:48:05 -0700 Subject: [PATCH 15/64] remoteproc: core: Full attach detach during recovery Current attach on recovery mechanism loads the clean resource table during recovery, but doesn't re-allocate the resources. RPMsg communication will fail after recovery due to this. Fix this incorrect behavior by doing the full detach and attach of remote processor during the recovery. This will load the clean resource table and re-allocate all the resources, which will set up correct vring information in the resource table. Signed-off-by: Tanmay Shah Link: https://lore.kernel.org/r/20260630004806.3835488-2-tanmay.shah@amd.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/remoteproc_core.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index f003be006b1b..8393468fa1ee 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1776,7 +1776,20 @@ static int rproc_attach_recovery(struct rproc *rproc) if (ret) return ret; - return __rproc_attach(rproc); + /* clean up all acquired resources */ + rproc_resource_cleanup(rproc); + + /* release HW resources if needed */ + rproc_unprepare_device(rproc); + + rproc_disable_iommu(rproc); + + /* Free the copy of the resource table */ + kfree(rproc->cached_table); + rproc->cached_table = NULL; + rproc->table_ptr = NULL; + + return rproc_attach(rproc); } static int rproc_boot_recovery(struct rproc *rproc) From 5ae3dc078874693a0a7fd1cf32660bd473fe544d Mon Sep 17 00:00:00 2001 From: Tanmay Shah Date: Mon, 29 Jun 2026 17:48:06 -0700 Subject: [PATCH 16/64] remoteproc: xlnx: Add crash detection mechanism Remote processor will report the crash reason via the resource table and notify the host via mailbox notification. The host checks this crash reason on every mailbox notification from the remote and report to the rproc core framework. Then the rproc core framework will start the recovery process. Signed-off-by: Tanmay Shah Link: https://lore.kernel.org/r/20260630004806.3835488-3-tanmay.shah@amd.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/xlnx_r5_remoteproc.c | 70 ++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c index 7014d48c1228..c685bb5fa62c 100644 --- a/drivers/remoteproc/xlnx_r5_remoteproc.c +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c @@ -112,6 +112,10 @@ struct rsc_tbl_data { const uintptr_t rsc_tbl; } __packed; +enum xlnx_rproc_fw_rsc { + XLNX_RPROC_FW_CRASH_REPORT = RSC_VENDOR_START, +}; + /* * Hardcoded TCM bank values. This will stay in driver to maintain backward * compatibility with device-tree that does not have TCM information. @@ -131,9 +135,27 @@ static const struct mem_bank_data zynqmp_tcm_banks_lockstep[] = { {0xffe30000UL, 0x30000, 0x10000UL, PD_R5_1_BTCM, "btcm1"}, }; +#define CRASH_REASON_STR_LEN 16 + +/** + * struct xlnx_rproc_crash_report - resource to know crash status and reason + * + * @version: version of this resource + * @crashed: if true, the rproc is notifying crash, time to recover + * @crash_reason: number to describe reason of crash + * @crash_reason_str: short string description of crash reason + */ +struct xlnx_rproc_crash_report { + u8 version; + u8 crashed; + u8 crash_reason; + char crash_reason_str[CRASH_REASON_STR_LEN]; +} __packed; + /** * struct zynqmp_r5_core - remoteproc core's internal data * + * @crash_report: rproc crash state and reason * @rsc_tbl_va: resource table virtual address * @sram: Array of sram memories assigned to this core * @num_sram: number of sram for this core @@ -147,6 +169,7 @@ static const struct mem_bank_data zynqmp_tcm_banks_lockstep[] = { * @ipi: pointer to mailbox information */ struct zynqmp_r5_core { + struct xlnx_rproc_crash_report *crash_report; void __iomem *rsc_tbl_va; struct zynqmp_sram_bank *sram; int num_sram; @@ -204,11 +227,27 @@ static int event_notified_idr_cb(int id, void *ptr, void *data) */ static void handle_event_notified(struct work_struct *work) { + struct xlnx_rproc_crash_report *report; + struct zynqmp_r5_core *r5_core; struct mbox_info *ipi; struct rproc *rproc; ipi = container_of(work, struct mbox_info, mbox_work); rproc = ipi->r5_core->rproc; + r5_core = ipi->r5_core; + report = r5_core->crash_report; + + /* report crash only if expected */ + if (report && report->crashed) { + if (rproc->state == RPROC_ATTACHED || rproc->state == RPROC_RUNNING) { + report->crash_reason_str[CRASH_REASON_STR_LEN - 1] = '\0'; + dev_warn(&rproc->dev, "crash reason id: %d %s\n", + report->crash_reason, report->crash_reason_str); + rproc_report_crash(rproc, RPROC_FATAL_ERROR); + report->crashed = false; + return; + } + } /* * We only use IPI for interrupt. The RPU firmware side may or may @@ -390,6 +429,13 @@ static int zynqmp_r5_rproc_stop(struct rproc *rproc) if (ret) dev_err(&rproc->dev, "failed to stop RPU\n"); + /* + * Clear attach on recovery flag during stop operation. The next state + * of the remote processor is expected to be in "Running" state. In this + * state, boot recovery method must take place over attach on recovery. + */ + test_and_clear_bit(RPROC_FEAT_ATTACH_ON_RECOVERY, rproc->features); + return ret; } @@ -784,6 +830,24 @@ static int zynqmp_r5_detach(struct rproc *rproc) return 0; } +static int zynqmp_r5_handle_rsc(struct rproc *rproc, u32 rsc_type, void *rsc, + int offset, int avail) +{ + struct zynqmp_r5_core *r5_core = rproc->priv; + void *rsc_offset = (r5_core->rsc_tbl_va + offset); + + if (rsc_type != XLNX_RPROC_FW_CRASH_REPORT) + return RSC_IGNORED; + + r5_core->crash_report = rsc_offset; + /* reset all values */ + r5_core->crash_report->crashed = false; + r5_core->crash_report->crash_reason = 0; + r5_core->crash_report->crash_reason_str[0] = '\0'; + + return RSC_HANDLED; +} + static const struct rproc_ops zynqmp_r5_rproc_ops = { .prepare = zynqmp_r5_rproc_prepare, .unprepare = zynqmp_r5_rproc_unprepare, @@ -798,6 +862,7 @@ static const struct rproc_ops zynqmp_r5_rproc_ops = { .get_loaded_rsc_table = zynqmp_r5_get_loaded_rsc_table, .attach = zynqmp_r5_attach, .detach = zynqmp_r5_detach, + .handle_rsc = zynqmp_r5_handle_rsc, }; /** @@ -837,7 +902,7 @@ static struct zynqmp_r5_core *zynqmp_r5_alloc_rproc_core(struct device *cdev) rproc_coredump_set_elf_info(r5_rproc, ELFCLASS32, EM_ARM); - r5_rproc->recovery_disabled = true; + r5_rproc->recovery_disabled = false; r5_rproc->has_iommu = false; r5_rproc->auto_boot = false; @@ -1186,6 +1251,9 @@ static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster, if (zynqmp_r5_get_rsc_table_va(r5_core)) dev_dbg(r5_core->dev, "rsc tbl not found\n"); r5_core->rproc->state = RPROC_DETACHED; + /* Enable attach on recovery method. Clear it during rproc stop. */ + rproc_set_feature(r5_core->rproc, + RPROC_FEAT_ATTACH_ON_RECOVERY); r5_core->rproc->auto_boot = true; } } From f4bb5a75bba373fb62864476b79f360a2b901c04 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 5 Jul 2026 19:23:54 +0200 Subject: [PATCH 17/64] remoteproc: ti_k3_r5: Drop redundant NULL check on reset control get devm_reset_control_get_exclusive() does not return NULL (only valid clock or ERR pointer in case for non-optional get), so simplify the code to drop redundant IS_ERR_OR_NULL(). Signed-off-by: Krzysztof Kozlowski Reviewed-by: Philipp Zabel Link: https://lore.kernel.org/r/20260705172353.119031-2-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/ti_k3_r5_remoteproc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c index 04f23295ffc1..b1d04d082e44 100644 --- a/drivers/remoteproc/ti_k3_r5_remoteproc.c +++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c @@ -1074,11 +1074,9 @@ static int k3_r5_cluster_rproc_init(struct platform_device *pdev) } kproc->reset = devm_reset_control_get_exclusive(cdev, NULL); - if (IS_ERR_OR_NULL(kproc->reset)) { - ret = PTR_ERR_OR_ZERO(kproc->reset); - if (!ret) - ret = -ENODEV; - dev_err_probe(cdev, ret, "failed to get reset handle\n"); + if (IS_ERR(kproc->reset)) { + ret = dev_err_probe(cdev, PTR_ERR(kproc->reset), + "failed to get reset handle\n"); goto out; } From 22f9efb3ae07f966a1901d929d16df1388cce65c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Jul 2026 08:56:14 +0200 Subject: [PATCH 18/64] remoteproc: scp: Fix device reference leak on failed lookup Make sure to drop the reference taken to the SCP device when attempting to look up its driver data before the driver has been bound. Note that holding a reference to a device does not prevent its driver data from going away. Fixes: 63c13d61eafe ("remoteproc/mediatek: add SCP support for mt8183") Cc: stable@vger.kernel.org # 5.6 Cc: Erin Lo Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20260706065614.389412-1-johan@kernel.org Signed-off-by: Mathieu Poirier --- drivers/remoteproc/mtk_scp.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c index 85a74c9ec521..436656bdfa8b 100644 --- a/drivers/remoteproc/mtk_scp.c +++ b/drivers/remoteproc/mtk_scp.c @@ -36,6 +36,7 @@ struct mtk_scp *scp_get(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *scp_node; struct platform_device *scp_pdev; + struct mtk_scp *scp; scp_node = of_parse_phandle(dev->of_node, "mediatek,scp", 0); if (!scp_node) { @@ -51,7 +52,13 @@ struct mtk_scp *scp_get(struct platform_device *pdev) return NULL; } - return platform_get_drvdata(scp_pdev); + scp = platform_get_drvdata(scp_pdev); + if (!scp) { + put_device(&scp_pdev->dev); + return NULL; + } + + return scp; } EXPORT_SYMBOL_GPL(scp_get); From 254030af0d81b12b7624d9ce85c6bdd3171629c6 Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Thu, 2 Jul 2026 17:28:20 +0530 Subject: [PATCH 19/64] remoteproc: qcom_q6v5_pas: Switch over to generic PAS TZ APIs Switch qcom_q6v5_pas client driver over to generic PAS TZ APIs. Generic PAS TZ service allows to support multiple TZ implementation backends like QTEE based SCM PAS service, OP-TEE based PAS service and any further future TZ backend service. Since qcom_q6v5_pas depends on MDT loader for PAS firmware loading, it has to be switched over to generic PAS APIs in this commit to avoid any build issues. Reviewed-by: Mukesh Ojha Tested-by: Mukesh Ojha # Lemans Tested-by: Vignesh Viswanathan # IPQ9650 Reviewed-by: Konrad Dybcio Signed-off-by: Sumit Garg Link: https://lore.kernel.org/r/20260702115835.167602-5-sumit.garg@kernel.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 51 +++++++++++++++-------------- drivers/soc/qcom/mdt_loader.c | 12 +++---- include/linux/soc/qcom/mdt_loader.h | 6 ++-- 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 60a4337d9e51..4862c679cbe5 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -116,8 +117,8 @@ struct qcom_pas { struct qcom_rproc_ssr ssr_subdev; struct qcom_sysmon *sysmon; - struct qcom_scm_pas_context *pas_ctx; - struct qcom_scm_pas_context *dtb_pas_ctx; + struct qcom_pas_context *pas_ctx; + struct qcom_pas_context *dtb_pas_ctx; }; static void qcom_pas_segment_dump(struct rproc *rproc, @@ -194,7 +195,7 @@ static int qcom_pas_shutdown_poll_decrypt(struct qcom_pas *pas) do { msleep(QCOM_PAS_DECRYPT_SHUTDOWN_DELAY_MS); - ret = qcom_scm_pas_shutdown(pas->pas_id); + ret = qcom_pas_shutdown(pas->pas_id); } while (ret == -EINVAL && --retry_num); return ret; @@ -210,9 +211,9 @@ static int qcom_pas_unprepare(struct rproc *rproc) * auth_and_reset() was successful, but in other cases clean it up * here. */ - qcom_scm_pas_metadata_release(pas->pas_ctx); + qcom_pas_metadata_release(pas->pas_ctx); if (pas->dtb_pas_id) - qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); + qcom_pas_metadata_release(pas->dtb_pas_ctx); return 0; } @@ -226,9 +227,9 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw) pas->firmware = fw; if (pas->lite_pas_id) - qcom_scm_pas_shutdown(pas->lite_pas_id); + qcom_pas_shutdown(pas->lite_pas_id); if (pas->lite_dtb_pas_id) - qcom_scm_pas_shutdown(pas->lite_dtb_pas_id); + qcom_pas_shutdown(pas->lite_dtb_pas_id); if (pas->dtb_pas_id) { ret = request_firmware(&pas->dtb_firmware, pas->dtb_firmware_name, pas->dev); @@ -248,7 +249,7 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw) return 0; release_dtb_metadata: - qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); + qcom_pas_metadata_release(pas->dtb_pas_ctx); release_firmware(pas->dtb_firmware); return ret; @@ -308,7 +309,7 @@ static int qcom_pas_start(struct rproc *rproc) if (ret) goto disable_px_supply; - ret = qcom_scm_pas_prepare_and_auth_reset(pas->dtb_pas_ctx); + ret = qcom_pas_prepare_and_auth_reset(pas->dtb_pas_ctx); if (ret) { dev_err(pas->dev, "failed to authenticate dtb image and release reset\n"); @@ -327,7 +328,7 @@ static int qcom_pas_start(struct rproc *rproc) if (ret) goto release_pas_metadata; - ret = qcom_scm_pas_prepare_and_auth_reset(pas->pas_ctx); + ret = qcom_pas_prepare_and_auth_reset(pas->pas_ctx); if (ret) { dev_err(pas->dev, "failed to authenticate image and release reset\n"); @@ -337,13 +338,13 @@ static int qcom_pas_start(struct rproc *rproc) ret = qcom_q6v5_wait_for_start(&pas->q6v5, msecs_to_jiffies(5000)); if (ret == -ETIMEDOUT) { dev_err(pas->dev, "start timed out\n"); - qcom_scm_pas_shutdown(pas->pas_id); + qcom_pas_shutdown(pas->pas_id); goto unmap_carveout; } - qcom_scm_pas_metadata_release(pas->pas_ctx); + qcom_pas_metadata_release(pas->pas_ctx); if (pas->dtb_pas_id) - qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); + qcom_pas_metadata_release(pas->dtb_pas_ctx); /* firmware is used to pass reference from qcom_pas_start(), drop it now */ pas->firmware = NULL; @@ -353,9 +354,9 @@ static int qcom_pas_start(struct rproc *rproc) unmap_carveout: qcom_pas_unmap_carveout(rproc, pas->mem_phys, pas->mem_size); release_pas_metadata: - qcom_scm_pas_metadata_release(pas->pas_ctx); + qcom_pas_metadata_release(pas->pas_ctx); if (pas->dtb_pas_id) - qcom_scm_pas_metadata_release(pas->dtb_pas_ctx); + qcom_pas_metadata_release(pas->dtb_pas_ctx); unmap_dtb_carveout: if (pas->dtb_pas_id) @@ -404,7 +405,7 @@ static int qcom_pas_stop(struct rproc *rproc) if (ret == -ETIMEDOUT) dev_err(pas->dev, "timed out on wait\n"); - ret = qcom_scm_pas_shutdown(pas->pas_id); + ret = qcom_pas_shutdown(pas->pas_id); if (ret && pas->decrypt_shutdown) ret = qcom_pas_shutdown_poll_decrypt(pas); @@ -412,7 +413,7 @@ static int qcom_pas_stop(struct rproc *rproc) dev_err(pas->dev, "failed to shutdown: %d\n", ret); if (pas->dtb_pas_id) { - ret = qcom_scm_pas_shutdown(pas->dtb_pas_id); + ret = qcom_pas_shutdown(pas->dtb_pas_id); if (ret) dev_err(pas->dev, "failed to shutdown dtb: %d\n", ret); @@ -482,11 +483,11 @@ static int qcom_pas_parse_firmware(struct rproc *rproc, const struct firmware *f * * Here, we call rproc_elf_load_rsc_table() to check firmware binary has resources * or not and if it is not having then we pass NULL and zero as input resource - * table pointer and size respectively to the argument of qcom_scm_pas_get_rsc_table() + * table pointer and size respectively to the argument of qcom_pas_get_rsc_table() * and this is even true for Qualcomm remote processor who does follow remoteproc * framework. */ - output_rt = qcom_scm_pas_get_rsc_table(pas->pas_ctx, table, table_sz, &output_rt_size); + output_rt = qcom_pas_get_rsc_table(pas->pas_ctx, table, table_sz, &output_rt_size); ret = IS_ERR(output_rt) ? PTR_ERR(output_rt) : 0; if (ret) { dev_err(pas->dev, "Error in getting resource table: %d\n", ret); @@ -807,7 +808,7 @@ static int qcom_pas_probe(struct platform_device *pdev) if (!desc) return -EINVAL; - if (!qcom_scm_is_available()) + if (!qcom_pas_is_available()) return -EPROBE_DEFER; fw_name = desc->firmware_name; @@ -899,16 +900,16 @@ static int qcom_pas_probe(struct platform_device *pdev) qcom_add_ssr_subdev(rproc, &pas->ssr_subdev, desc->ssr_name); - pas->pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->pas_id, - pas->mem_phys, pas->mem_size); + pas->pas_ctx = devm_qcom_pas_context_alloc(pas->dev, pas->pas_id, + pas->mem_phys, pas->mem_size); if (IS_ERR(pas->pas_ctx)) { ret = PTR_ERR(pas->pas_ctx); goto remove_ssr_sysmon; } - pas->dtb_pas_ctx = devm_qcom_scm_pas_context_alloc(pas->dev, pas->dtb_pas_id, - pas->dtb_mem_phys, - pas->dtb_mem_size); + pas->dtb_pas_ctx = devm_qcom_pas_context_alloc(pas->dev, pas->dtb_pas_id, + pas->dtb_mem_phys, + pas->dtb_mem_size); if (IS_ERR(pas->dtb_pas_ctx)) { ret = PTR_ERR(pas->dtb_pas_ctx); goto remove_ssr_sysmon; diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index c004d444d698..137992456b71 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -229,7 +229,7 @@ EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata); static int __qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, const char *fw_name, int pas_id, phys_addr_t mem_phys, - struct qcom_scm_pas_context *ctx) + struct qcom_pas_context *ctx) { const struct elf32_phdr *phdrs; const struct elf32_phdr *phdr; @@ -271,7 +271,7 @@ static int __qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, goto out; } - ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len, ctx); + ret = qcom_pas_init_image(pas_id, metadata, metadata_len, ctx); kfree(metadata); if (ret) { /* Invalid firmware metadata */ @@ -280,7 +280,7 @@ static int __qcom_mdt_pas_init(struct device *dev, const struct firmware *fw, } if (relocate) { - ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); + ret = qcom_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr); if (ret) { /* Unable to set up relocation */ dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name); @@ -472,7 +472,7 @@ EXPORT_SYMBOL_GPL(qcom_mdt_load); * firmware segments (e.g., .bXX files). Authentication of the segments done * by a separate call. * - * The PAS context must be initialized using qcom_scm_pas_context_init() + * The PAS context must be initialized using devm_qcom_pas_context_alloc() * prior to invoking this function. * * @ctx: Pointer to the PAS (Peripheral Authentication Service) context @@ -483,7 +483,7 @@ EXPORT_SYMBOL_GPL(qcom_mdt_load); * * Return: 0 on success or a negative error code on failure. */ -int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw, +int qcom_mdt_pas_load(struct qcom_pas_context *ctx, const struct firmware *fw, const char *firmware, void *mem_region, phys_addr_t *reloc_base) { int ret; diff --git a/include/linux/soc/qcom/mdt_loader.h b/include/linux/soc/qcom/mdt_loader.h index 82372e0db0a1..142409555425 100644 --- a/include/linux/soc/qcom/mdt_loader.h +++ b/include/linux/soc/qcom/mdt_loader.h @@ -10,7 +10,7 @@ struct device; struct firmware; -struct qcom_scm_pas_context; +struct qcom_pas_context; #if IS_ENABLED(CONFIG_QCOM_MDT_LOADER) @@ -20,7 +20,7 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw, phys_addr_t mem_phys, size_t mem_size, phys_addr_t *reloc_base); -int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, const struct firmware *fw, +int qcom_mdt_pas_load(struct qcom_pas_context *ctx, const struct firmware *fw, const char *firmware, void *mem_region, phys_addr_t *reloc_base); int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw, @@ -45,7 +45,7 @@ static inline int qcom_mdt_load(struct device *dev, const struct firmware *fw, return -ENODEV; } -static inline int qcom_mdt_pas_load(struct qcom_scm_pas_context *ctx, +static inline int qcom_mdt_pas_load(struct qcom_pas_context *ctx, const struct firmware *fw, const char *firmware, void *mem_region, phys_addr_t *reloc_base) { From f3b1357673ddb37ae8b9a8fe44df73cbd2a519c5 Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Thu, 2 Jul 2026 17:28:21 +0530 Subject: [PATCH 20/64] remoteproc: qcom_q6v5_mss: Switch to generic PAS TZ APIs Switch qcom_q6v5_mss client driver over to generic PAS TZ APIs. Generic PAS TZ service allows to support multiple TZ implementation backends like QTEE based SCM PAS service, OP-TEE based PAS service and any further future TZ backend service. Reviewed-by: Mukesh Ojha Tested-by: Mukesh Ojha # Lemans Reviewed-by: Konrad Dybcio Signed-off-by: Sumit Garg Link: https://lore.kernel.org/r/20260702115835.167602-6-sumit.garg@kernel.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_mss.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index ae78f5c7c1b6..96888007faa8 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -34,6 +34,7 @@ #include "qcom_pil_info.h" #include "qcom_q6v5.h" +#include #include #define MPSS_CRASH_REASON_SMEM 421 @@ -1480,7 +1481,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc) } if (qproc->need_pas_mem_setup) { - ret = qcom_scm_pas_mem_setup(MPSS_PAS_ID, qproc->mpss_phys, qproc->mpss_size); + ret = qcom_pas_mem_setup(MPSS_PAS_ID, qproc->mpss_phys, qproc->mpss_size); if (ret) { dev_err(qproc->dev, "setting up mpss memory failed: %d\n", ret); @@ -2077,7 +2078,7 @@ static int q6v5_probe(struct platform_device *pdev) if (!desc) return -EINVAL; - if (desc->need_mem_protection && !qcom_scm_is_available()) + if (desc->need_mem_protection && !qcom_pas_is_available()) return -EPROBE_DEFER; mba_image = desc->hexagon_mba_image; From ea3b5245f5deba916320b32a8e6510a74c034c17 Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Thu, 2 Jul 2026 17:28:22 +0530 Subject: [PATCH 21/64] remoteproc: qcom_wcnss: Switch to generic PAS TZ APIs Switch qcom_wcnss client driver over to generic PAS TZ APIs. Generic PAS TZ service allows to support multiple TZ implementation backends like QTEE based SCM PAS service, OP-TEE based PAS service and any further future TZ backend service. Reviewed-by: Mukesh Ojha Tested-by: Mukesh Ojha # Lemans Reviewed-by: Konrad Dybcio Signed-off-by: Sumit Garg Link: https://lore.kernel.org/r/20260702115835.167602-7-sumit.garg@kernel.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_wcnss.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 4add9037dbd5..0dbdd18ab3dd 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -257,7 +257,7 @@ static int wcnss_start(struct rproc *rproc) wcnss_indicate_nv_download(wcnss); wcnss_configure_iris(wcnss); - ret = qcom_scm_pas_auth_and_reset(WCNSS_PAS_ID); + ret = qcom_pas_auth_and_reset(WCNSS_PAS_ID); if (ret) { dev_err(wcnss->dev, "failed to authenticate image and release reset\n"); @@ -269,7 +269,7 @@ static int wcnss_start(struct rproc *rproc) if (wcnss->ready_irq > 0 && ret == 0) { /* We have a ready_irq, but it didn't fire in time. */ dev_err(wcnss->dev, "start timed out\n"); - qcom_scm_pas_shutdown(WCNSS_PAS_ID); + qcom_pas_shutdown(WCNSS_PAS_ID); ret = -ETIMEDOUT; goto disable_iris; } @@ -311,7 +311,7 @@ static int wcnss_stop(struct rproc *rproc) 0); } - ret = qcom_scm_pas_shutdown(WCNSS_PAS_ID); + ret = qcom_pas_shutdown(WCNSS_PAS_ID); if (ret) dev_err(wcnss->dev, "failed to shutdown: %d\n", ret); @@ -557,10 +557,10 @@ static int wcnss_probe(struct platform_device *pdev) data = of_device_get_match_data(&pdev->dev); - if (!qcom_scm_is_available()) + if (!qcom_pas_is_available()) return -EPROBE_DEFER; - if (!qcom_scm_pas_supported(WCNSS_PAS_ID)) { + if (!qcom_pas_supported(WCNSS_PAS_ID)) { dev_err(&pdev->dev, "PAS is not available for WCNSS\n"); return -ENXIO; } From c4383254ac7a529736577e304176a10371c2ee0b Mon Sep 17 00:00:00 2001 From: Sumit Garg Date: Thu, 2 Jul 2026 17:28:23 +0530 Subject: [PATCH 22/64] remoteproc: qcom: Select QCOM_PAS generic service Select PAS generic service driver to enable support for multiple PAS backends like OP-TEE in addition to SCM. Tested-by: Mukesh Ojha # Lemans Tested-by: Vignesh Viswanathan # IPQ9650 Signed-off-by: Sumit Garg Link: https://lore.kernel.org/r/20260702115835.167602-8-sumit.garg@kernel.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index c521c744e7db..65befdbfa5f7 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -210,6 +210,7 @@ config QCOM_Q6V5_MSS select QCOM_Q6V5_COMMON select QCOM_RPROC_COMMON select QCOM_SCM + select QCOM_PAS help Say y here to support the Qualcomm self-authenticating modem subsystem based on Hexagon V5. The TrustZone based system is @@ -230,6 +231,7 @@ config QCOM_Q6V5_PAS select QCOM_Q6V5_COMMON select QCOM_RPROC_COMMON select QCOM_SCM + select QCOM_PAS help Say y here to support the TrustZone based Peripheral Image Loader for the Qualcomm remote processors. This is commonly used to control @@ -282,7 +284,7 @@ config QCOM_WCNSS_PIL select QCOM_MDT_LOADER select QCOM_PIL_INFO select QCOM_RPROC_COMMON - select QCOM_SCM + select QCOM_PAS help Say y here to support the Peripheral Image Loader for loading WCNSS firmware and boot the core on e.g. MSM8974, MSM8916. The firmware is From 8c952807c2cebd5e9e9b37146c9383229794c129 Mon Sep 17 00:00:00 2001 From: Felix Gu Date: Fri, 16 Jan 2026 20:11:03 +0800 Subject: [PATCH 23/64] remoteproc: qcom_q6v5_adsp: Fix reference leak for device node When calling of_parse_phandle_with_args(), the caller is responsible to call of_node_put() to release the reference of device node. In adsp_map_carveout, it does not release the reference. Fixes: f22eedff28af ("remoteproc: qcom: Add support for memory sandbox") Signed-off-by: Felix Gu Link: https://lore.kernel.org/r/tencent_EDC2253D3B1C22217E1259E07765D269100A@qq.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_adsp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c index b5c8d6d38c9c..c81e6c33c747 100644 --- a/drivers/remoteproc/qcom_q6v5_adsp.c +++ b/drivers/remoteproc/qcom_q6v5_adsp.c @@ -355,6 +355,7 @@ static int adsp_map_carveout(struct rproc *rproc) return ret; sid = args.args[0] & SID_MASK_DEFAULT; + of_node_put(args.np); /* Add SID configuration for ADSP Firmware to SMMU */ iova = adsp->mem_phys | (sid << 32); From ef22e806ae3b6728df20b5a6c07aa5a01db38e7b Mon Sep 17 00:00:00 2001 From: Zhongqiu Han Date: Wed, 17 Dec 2025 14:51:08 +0800 Subject: [PATCH 24/64] rpmsg: Replace sprintf() with sysfs_emit() in sysfs show Use sysfs_emit() instead of sprintf() in sysfs attribute show functions. sysfs_emit() is the recommended API for sysfs output as it provides buffer overflow protection and proper formatting. No functional changes. Signed-off-by: Zhongqiu Han Reviewed-by: Chris Lew Link: https://lore.kernel.org/r/20251217065112.18392-2-zhongqiu.han@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_smd.c | 2 +- drivers/rpmsg/rpmsg_char.c | 6 +++--- drivers/rpmsg/rpmsg_core.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c index 3ac863f400ec..7dbe1c6efe41 100644 --- a/drivers/rpmsg/qcom_smd.c +++ b/drivers/rpmsg/qcom_smd.c @@ -1460,7 +1460,7 @@ static ssize_t rpmsg_name_show(struct device *dev, { struct qcom_smd_edge *edge = to_smd_edge(dev); - return sprintf(buf, "%s\n", edge->name); + return sysfs_emit(buf, "%s\n", edge->name); } static DEVICE_ATTR_RO(rpmsg_name); diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index bff5aefee212..68a0e5e93744 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -371,7 +371,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr, { struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", eptdev->chinfo.name); + return sysfs_emit(buf, "%s\n", eptdev->chinfo.name); } static DEVICE_ATTR_RO(name); @@ -380,7 +380,7 @@ static ssize_t src_show(struct device *dev, struct device_attribute *attr, { struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", eptdev->chinfo.src); + return sysfs_emit(buf, "%d\n", eptdev->chinfo.src); } static DEVICE_ATTR_RO(src); @@ -389,7 +389,7 @@ static ssize_t dst_show(struct device *dev, struct device_attribute *attr, { struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", eptdev->chinfo.dst); + return sysfs_emit(buf, "%d\n", eptdev->chinfo.dst); } static DEVICE_ATTR_RO(dst); diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index c56f69c22e42..cfe7d04381ee 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -348,7 +348,7 @@ field##_show(struct device *dev, \ { \ struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ \ - return sprintf(buf, format_string, rpdev->path); \ + return sysfs_emit(buf, format_string, rpdev->path); \ } \ static DEVICE_ATTR_RO(field); @@ -368,7 +368,7 @@ static ssize_t modalias_show(struct device *dev, if (len != -ENODEV) return len; - return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name); + return sysfs_emit(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name); } static DEVICE_ATTR_RO(modalias); From 31a42429e043cde8a94da8872e002781a7068827 Mon Sep 17 00:00:00 2001 From: Zhongqiu Han Date: Wed, 17 Dec 2025 14:51:09 +0800 Subject: [PATCH 25/64] rpmsg: core: Fix incorrect return value documentation The unregister_rpmsg_driver() function has a void return type but the documentation incorrectly described a return value. Remove the incorrect return value documentation to match the actual function signature. Fixes: bcabbccabffe ("rpmsg: add virtio-based remote processor messaging bus") Signed-off-by: Zhongqiu Han Reviewed-by: Chris Lew Link: https://lore.kernel.org/r/20251217065112.18392-3-zhongqiu.han@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- Documentation/staging/rpmsg.rst | 1 - drivers/rpmsg/rpmsg_core.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/Documentation/staging/rpmsg.rst b/Documentation/staging/rpmsg.rst index 42bac1149d9d..63612b7ee120 100644 --- a/Documentation/staging/rpmsg.rst +++ b/Documentation/staging/rpmsg.rst @@ -212,7 +212,6 @@ be probed with. unregisters an rpmsg driver from the rpmsg bus. user should provide a pointer to a previously-registered rpmsg_driver struct. -Returns 0 on success, and an appropriate error value on failure. Typical usage diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index cfe7d04381ee..04bfcc75f05b 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -598,8 +598,6 @@ EXPORT_SYMBOL(__register_rpmsg_driver); /** * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus * @rpdrv: pointer to a struct rpmsg_driver - * - * Return: 0 on success, and an appropriate error value on failure. */ void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv) { From ad6d7795388dbfc8a4c8980b49ad43648b1d6efe Mon Sep 17 00:00:00 2001 From: Sudeepgoud Patil Date: Thu, 11 Dec 2025 14:18:34 +0530 Subject: [PATCH 26/64] rpmsg: glink: Replace strcpy() with strscpy() Replace strcpy() with the safer strscpy() to address unsafe API usage warnings[1] from static analysis tools, as strcpy() performs no bounds checking on the destination buffer. [1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strcpy Signed-off-by: Sudeepgoud Patil Signed-off-by: Vishnu Santhosh Reviewed-by: Chris Lew Link: https://lore.kernel.org/r/20251211-rpmsg-glink-strcpy-replace-v1-1-be06308e5724@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_native.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index d9d4468e4cbd..022b4bcb40d6 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -501,7 +501,7 @@ static int qcom_glink_send_open_req(struct qcom_glink *glink, req->cmd = cpu_to_le16(GLINK_CMD_OPEN); req->param1 = cpu_to_le16(channel->lcid); req->param2 = cpu_to_le32(name_len); - strcpy(req->data, channel->name); + strscpy(req->data, channel->name, GLINK_NAME_SIZE); trace_qcom_glink_cmd_open_tx(glink->label, channel->name, channel->lcid, channel->rcid); From 3dbc90b9c22ea96e37bf55f6011e63b5123ec668 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Sun, 1 Feb 2026 17:55:03 -0300 Subject: [PATCH 27/64] remoteproc: qcom_wcnss: Fix handling the lack of PD regulators in v3 The changes introduced to handle single power domain platforms have swapped the info pointer increment from num_pd_vregs to num_pds, which would shift the info pointer past the end of the array for pronto-v3, which does not list power domain regulators in vregs. This showed up as a difference between GCC- and LLVM-compiled kernels on SDM632 devices, where only with LLVM one would get the "regulator request with no identifier" error, because the out-of-bounds memory ended up being zeroed. Fix by skipping the increment when there are more power domains than regulators. Signed-off-by: Val Packett Fixes: 65991ea8a6d1 ("remoteproc: qcom_wcnss: Handle platforms with only single power domain") Reviewed-by: Konrad Dybcio Fixes: 65991ea8a6d1 ("remoteproc: qcom_wcnss: Handle platforms with only single power domain") Link: https://lore.kernel.org/r/20260201210230.911220-1-val@packett.cool Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_wcnss.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 0dbdd18ab3dd..3392c9380202 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -441,25 +441,31 @@ static void wcnss_release_pds(struct qcom_wcnss *wcnss) } static int wcnss_init_regulators(struct qcom_wcnss *wcnss, - const struct wcnss_vreg_info *info, - int num_vregs, int num_pd_vregs) + const struct wcnss_data *data) { + const struct wcnss_vreg_info *info = data->vregs; struct regulator_bulk_data *bulk; + size_t i, possible_pds = 0, num_vregs = data->num_vregs; int ret; - int i; + + for (i = 0; i < WCNSS_MAX_PDS; i++) + if (data->pd_names[i]) + possible_pds++; /* * If attaching the power domains suceeded we can skip requesting * the regulators for the power domains. For old device trees we need to * reserve extra space to manage them through the regulator interface. */ - if (wcnss->num_pds) { + if (possible_pds >= num_vregs) { + /* Do nothing if vregs do not include PD regulators (pronto-v3) */ + } else if (wcnss->num_pds) { info += wcnss->num_pds; /* Handle single power domain case */ - if (wcnss->num_pds < num_pd_vregs) - num_vregs += num_pd_vregs - wcnss->num_pds; + if (wcnss->num_pds < data->num_pd_vregs) + num_vregs += data->num_pd_vregs - wcnss->num_pds; } else { - num_vregs += num_pd_vregs; + num_vregs += data->num_pd_vregs; } bulk = devm_kcalloc(wcnss->dev, @@ -607,8 +613,7 @@ static int wcnss_probe(struct platform_device *pdev) if (ret && (ret != -ENODATA || !data->num_pd_vregs)) return ret; - ret = wcnss_init_regulators(wcnss, data->vregs, data->num_vregs, - data->num_pd_vregs); + ret = wcnss_init_regulators(wcnss, data); if (ret) goto detach_pds; From 014be5698ed0645f1d5263b354c27fc3ba77b281 Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sat, 14 Mar 2026 18:01:51 +0100 Subject: [PATCH 28/64] MAINTAINERS: Update remoteproc repo url for hwspinlock Since 2021, the remoteproc repo is not hosted anymore in Bjorn's personal namespace, but commit cc73f503f7ec ("MAINTAINERS: Update remoteproc repo url") only updated the url for remoteproc and rpmsg in MAINTAINERS file. The old repository is still accessible, but it's not updated since 2021 and is not anymore listed in https://git.kernel.org/ . Update the url for hwspinlock too. Signed-off-by: Antonio Borneo Link: https://lore.kernel.org/r/20260314170151.18319-1-antonio.borneo@foss.st.com Signed-off-by: Bjorn Andersson --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 15011f5752a9..477be16693db 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11430,7 +11430,7 @@ M: Bjorn Andersson R: Baolin Wang L: linux-remoteproc@vger.kernel.org S: Maintained -T: git git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc.git hwspinlock-next +T: git https://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux.git hwspinlock-next F: Documentation/devicetree/bindings/hwlock/ F: Documentation/locking/hwspinlock.rst F: drivers/hwspinlock/ From 1f9c2897afb0fe86c1fdf4f5e23c5fb8f7442f6d Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Mon, 6 Apr 2026 09:59:50 +0530 Subject: [PATCH 29/64] rpmsg: char: Check for ongoing chrdev destroy A null pointer panic is observed when stopping a remoteproc and closing a character device using the RPMSG_DESTROY_EPT_IOCTL. There is a race where each context calls rpmsg_chrdev_eptdev_destroy(). The thread that runs second will call cdev_device_del() for a second time, which fails because the first call already removed the device from sysfs. Add a check at the beginning of destroy and exit early if the destroy call has already been done. [ 26.654130] Call trace [ 26.656658] kernfs_find_and_get_ns+0x28/0x8 [ 26.661140] sysfs_unmerge_group+0x2c/0x7 [ 26.665357] dpm_sysfs_remove+0x38/0x8 [ 26.669305] device_del+0xa4/0x3e [ 26.672811] cdev_device_del+0x28/0x7 [ 26.676675] rpmsg_chrdev_eptdev_destroy+0x68/0x98 [ 26.682765] rpmsg_eptdev_ioctl+0x130/0x11c8 [ 26.688318] __arm64_sys_ioctl+0xb4/0x10 [ 26.692448] invoke_syscall+0x50/0x12 [ 26.696312] el0_svc_common.constprop.0+0xc8/0xf [ 26.701151] do_el0_svc+0x24/0x3 [ 26.704570] el0_svc+0x40/0x17 [ 26.707810] el0t_64_sync_handler+0x120/0x13 [ 26.712288] el0t_64_sync+0x1a0/0x1a Signed-off-by: Chris Lew Signed-off-by: Vishnu Santhosh Link: https://lore.kernel.org/r/20260406-rpmsg-char-fix-chrdev-destroy-race-v1-1-7317434fa246@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/rpmsg_char.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c index 68a0e5e93744..550fda217da4 100644 --- a/drivers/rpmsg/rpmsg_char.c +++ b/drivers/rpmsg/rpmsg_char.c @@ -79,6 +79,11 @@ int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data) struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev); mutex_lock(&eptdev->ept_lock); + if (!eptdev->rpdev) { + mutex_unlock(&eptdev->ept_lock); + return 0; + } + eptdev->rpdev = NULL; if (eptdev->ept) { /* The default endpoint is released by the rpmsg core */ From e088ffa9a00eaaaf90da74763e774ca160969c26 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 12 May 2026 10:48:23 +0200 Subject: [PATCH 30/64] hwspinlock: propagate errno when registering single lock hwspin_lock_register_single() always returns 0 despite checking the result from radix_tree_insert(). Propagate the errno to make sanity checks in callers of this function actually meaningful. Fixes: 300bab9770e2 ("hwspinlock/core: register a bank of hwspinlocks in a single API call") Link: https://sashiko.dev/#/patchset/20260319105947.6237-1-wsa%2Brenesas%40sang-engineering.com # review of patch 14 Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20260512084856.30497-2-wsa+renesas@sang-engineering.com Signed-off-by: Bjorn Andersson --- drivers/hwspinlock/hwspinlock_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c index cc8e952a6772..a509b73da190 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c @@ -472,7 +472,7 @@ static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id) out: mutex_unlock(&hwspinlock_tree_lock); - return 0; + return ret; } static struct hwspinlock *hwspin_lock_unregister_single(unsigned int id) From 5a5a48e788e02fd8a8eb7188ce440572d6c12418 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Thu, 4 Jun 2026 14:12:53 +0530 Subject: [PATCH 31/64] rpmsg: glink: fix deadlock in endpoint destroy during driver detach MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During driver detach, the device core holds the device mutex throughout the driver's remove callback chain. When the rpmsg endpoint is destroyed as part of that teardown, the GLINK endpoint destroy implementation attempts to unregister the underlying rpmsg device. That unregistration calls device_del(), which tries to re-acquire the same device mutex already held higher up the stack, causing rmmod to hang indefinitely. The deadlock manifests with the following call chain: [<0>] device_del+0x44/0x414  <- tries to acquire same mutex [<0>] device_unregister+0x18/0x34 [<0>] rpmsg_unregister_device+0x28/0x4c [<0>] qcom_glink_remove_rpmsg_device+0x70/0xc0 [<0>] qcom_glink_destroy_ept+0x58/0xbc [<0>] rpmsg_dev_remove+0x50/0x60 [<0>] device_remove+0x4c/0x80 [<0>] device_release_driver_internal+0x1cc/0x228 <- acquires device mutex [<0>] driver_detach+0x4c/0x98 [<0>] bus_remove_driver+0x6c/0xbc [<0>] driver_unregister+0x30/0x60 [<0>] unregister_rpmsg_driver+0x10/0x1c [<0>] fastrpc_exit+0x28/0x38 [fastrpc] [<0>] __arm64_sys_delete_module+0x1b8/0x294 [<0>] invoke_syscall+0x48/0x10c [<0>] el0_svc_common.constprop.0+0xc0/0xe0 [<0>] do_el0_svc+0x1c/0x28 [<0>] el0_svc+0x34/0x108 [<0>] el0t_64_sync_handler+0xa0/0xe4 [<0>] el0t_64_sync+0x198/0x19c The rpmsg device unregistration inside endpoint destroy is redundant. In both contexts where endpoint destruction is triggered: - Driver detach path: the driver core already tears down the rpmsg device. - Channel close path: the rpmsg device is already unregistered before endpoint destruction is reached. Remove the redundant unregistration to fix the deadlock. Co-developed-by: Deepak Kumar Singh Signed-off-by: Deepak Kumar Singh Signed-off-by: Vishnu Santhosh Tested-by: Bjorn Andersson Fixes: a53e356df548 ("rpmsg: glink: fix rpmsg device leak") Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20260604-rpmsg-glink-fix-deadlock-destroy-ept-v1-1-b8a54ad1e4fd@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_native.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 022b4bcb40d6..55793fc18293 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1418,9 +1418,6 @@ static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept) channel->ept.cb = NULL; spin_unlock_irqrestore(&channel->recv_lock, flags); - /* Decouple the potential rpdev from the channel */ - qcom_glink_remove_rpmsg_device(glink, channel); - qcom_glink_send_close_req(glink, channel); } From 786439ad58763e04b91bc2ec5f590e463939f197 Mon Sep 17 00:00:00 2001 From: Chunkai Deng Date: Thu, 18 Jun 2026 00:16:39 -0700 Subject: [PATCH 32/64] rpmsg: glink: smem: order FIFO read after availability check glink_smem_rx_peek() reads the RX FIFO payload after the caller has determined data is available via glink_smem_rx_avail(), which reads the remote-updated head index. A control dependency between the head read and the subsequent payload read does not order the two loads, so the CPU may speculatively read the FIFO before observing the head update and consume stale data the remote has not yet published. Add rmb() in glink_smem_rx_peek() before the memcpy_fromio() so the availability (head) read is ordered ahead of the FIFO payload read, matching the consumer pattern in Documentation/core-api/circular-buffers.rst. Fixes: caf989c350e8 ("rpmsg: glink: Introduce glink smem based transport") Cc: stable@vger.kernel.org Signed-off-by: Chunkai Deng Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260618-rpmsg-glink-smem-mb-v1-1-68a026453a69@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_smem.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index 62adc4db2317..35bb03e67ae8 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -103,6 +103,13 @@ static void glink_smem_rx_peek(struct qcom_glink_pipe *np, if (tail >= pipe->native.length) tail -= pipe->native.length; + /* + * Order the availability (head) read in glink_smem_rx_avail() + * against the FIFO payload read below, so APPS never consumes + * stale data the remote has not yet published. + */ + rmb(); + len = min_t(size_t, count, pipe->native.length - tail); if (len) memcpy_fromio(data, pipe->fifo + tail, len); From c2200063763645d3c23a9428d3f636ed67b2df7a Mon Sep 17 00:00:00 2001 From: Ananthu C V Date: Tue, 7 Jul 2026 03:12:44 -0700 Subject: [PATCH 33/64] remoteproc: qcom: pas: add needs_tzmem flag to trigger shmbridge creation SHM bridge creation is required to enable memory protection for both remoteproc metadata and its memory region on Qualcomm SoCs running non-Gunyah based Hypervisors. We currently rely on the iommu property being present in the remoteproc nodes to detect this. However, this doesn't cover for cases where the remoteproc does a late attach, like SoCCP, and for remoteprocs like OOBM SS (Out of Band Management Sub-system) that doesn't have an iommu in front of it. In the former case, any attempt to create new mappings would fail with EEXIST as they are already setup by the bootloader when the SoCCP is brought out of reset, and unmapping them to create fresh mappings leads to faults since SoCCP could have active transactions on the bus. In the latter case, absence of iommu will be caught by the has_iommu flag, and SHM bridge creation will be skipped. Fix this by introducing a needs_tzmem flag which would cover for the above edge cases by serving as an alternate trigger to the PAS helpers to ensure that SHM bridge is established. Signed-off-by: Ananthu C V Reviewed-by: Mukesh Ojha Link: https://lore.kernel.org/r/20260707-glymur-soccp-v5-1-053993f0c6fe@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 4862c679cbe5..f0f87ad3007f 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -62,6 +62,7 @@ struct qcom_pas_data { bool region_assign_shared; int region_assign_vmid; bool early_boot; + bool needs_tzmem; }; struct qcom_pas { @@ -915,8 +916,8 @@ static int qcom_pas_probe(struct platform_device *pdev) goto remove_ssr_sysmon; } - pas->pas_ctx->use_tzmem = rproc->has_iommu; - pas->dtb_pas_ctx->use_tzmem = rproc->has_iommu; + pas->pas_ctx->use_tzmem = desc->needs_tzmem || rproc->has_iommu; + pas->dtb_pas_ctx->use_tzmem = desc->needs_tzmem || rproc->has_iommu; if (desc->early_boot) pas->rproc->state = RPROC_DETACHED; @@ -1658,8 +1659,27 @@ static const struct qcom_pas_data kaanapali_soccp_resource = { .early_boot = true, }; +static const struct qcom_pas_data glymur_soccp_resource = { + .crash_reason_smem = 656, + .firmware_name = "soccp.mbn", + .dtb_firmware_name = "soccp_dtb.mbn", + .pas_id = 51, + .dtb_pas_id = 0x41, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + NULL + }, + .ssr_name = "soccp", + .sysmon_name = "soccp", + .auto_boot = true, + .early_boot = true, + .needs_tzmem = true, +}; + static const struct of_device_id qcom_pas_of_match[] = { { .compatible = "qcom,eliza-adsp-pas", .data = &sm8550_adsp_resource }, + { .compatible = "qcom,glymur-soccp-pas", .data = &glymur_soccp_resource }, { .compatible = "qcom,kaanapali-soccp-pas", .data = &kaanapali_soccp_resource }, { .compatible = "qcom,milos-adsp-pas", .data = &sm8550_adsp_resource }, { .compatible = "qcom,milos-cdsp-pas", .data = &milos_cdsp_resource }, From 6aa64a4c89faec9daff36828df38f8f69498a870 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 6 Jul 2026 17:37:16 +0200 Subject: [PATCH 34/64] remoteproc: qcom_q6v5_mss: Make ssctl_id configurable per platform Currently, qcom_q6v5_mss hardcodes 0x12 as the instance ID for the subsystem control (ssctl) QMI service. However, some platforms (e.g. MDM9607) provide the service with a different instance ID (0x22). Make it possible to override the ssctl_id per platform by adding it to the platform-specific rproc_hexagon_res struct. The same pattern also exists already inside qcom_q6v5_pas. Signed-off-by: Stephan Gerhold Reviewed-by: Dmitry Baryshkov Reviewed-by: Mukesh Ojha Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260706-qcom-q6v5-mss-mdm9607-ssctl-id-v1-1-f59e728af621@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_mss.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index 96888007faa8..3a3d98cc89ff 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -163,6 +163,7 @@ struct rproc_hexagon_res { char **active_clk_names; char **proxy_pd_names; int version; + int ssctl_id; bool need_mem_protection; bool need_pas_mem_setup; bool has_alt_reset; @@ -2192,7 +2193,7 @@ static int q6v5_probe(struct platform_device *pdev) qcom_add_smd_subdev(rproc, &qproc->smd_subdev); qcom_add_pdm_subdev(rproc, &qproc->pdm_subdev); qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss"); - qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12); + qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", desc->ssctl_id); if (IS_ERR(qproc->sysmon)) { ret = PTR_ERR(qproc->sysmon); goto remove_subdevs; @@ -2272,6 +2273,7 @@ static const struct rproc_hexagon_res sc7180_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_SC7180, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res sc7280_mss = { @@ -2302,6 +2304,7 @@ static const struct rproc_hexagon_res sc7280_mss = { .has_ext_cntl_regs = true, .has_vq6 = true, .version = MSS_SC7280, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res sdm660_mss = { @@ -2335,6 +2338,7 @@ static const struct rproc_hexagon_res sdm660_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_SDM660, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res sdm845_mss = { @@ -2372,6 +2376,7 @@ static const struct rproc_hexagon_res sdm845_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_SDM845, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res msm8998_mss = { @@ -2405,6 +2410,7 @@ static const struct rproc_hexagon_res msm8998_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8998, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res msm8996_mss = { @@ -2445,6 +2451,7 @@ static const struct rproc_hexagon_res msm8996_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8996, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res mdm9607_mss = { @@ -2480,6 +2487,7 @@ static const struct rproc_hexagon_res mdm9607_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MDM9607, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res msm8909_mss = { @@ -2516,6 +2524,7 @@ static const struct rproc_hexagon_res msm8909_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8909, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res msm8916_mss = { @@ -2563,6 +2572,7 @@ static const struct rproc_hexagon_res msm8916_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8916, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res msm8917_mss = { @@ -2607,6 +2617,7 @@ static const struct rproc_hexagon_res msm8917_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8917, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res msm8937_mss = { @@ -2651,6 +2662,7 @@ static const struct rproc_hexagon_res msm8937_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8937, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res msm8940_mss = { @@ -2695,6 +2707,7 @@ static const struct rproc_hexagon_res msm8940_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8940, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res msm8953_mss = { @@ -2732,6 +2745,7 @@ static const struct rproc_hexagon_res msm8953_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8953, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res msm8974_mss = { @@ -2786,6 +2800,7 @@ static const struct rproc_hexagon_res msm8974_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8974, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res msm8226_mss = { @@ -2825,6 +2840,7 @@ static const struct rproc_hexagon_res msm8226_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8226, + .ssctl_id = 0x12, }; static const struct rproc_hexagon_res msm8926_mss = { @@ -2872,6 +2888,7 @@ static const struct rproc_hexagon_res msm8926_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MSM8926, + .ssctl_id = 0x12, }; static const struct of_device_id q6v5_of_match[] = { From 846baa5ab461e24d31f942dcdff1932e8516dd00 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Mon, 6 Jul 2026 17:37:17 +0200 Subject: [PATCH 35/64] remoteproc: qcom_q6v5_mss: Fix MDM9607 subsystem control instance ID On MDM9607, the modem firmware exposes the QMI subsystem control service with instance ID 0x22 (34), as visible e.g. with qrtr-lookup: $ qrtr-lookup Service Version Instance Node Port 43 2 34 3 1 Subsystem control service Currently, qcom_q6v5_mss uses ssctl_id 0x12 for all platforms. The QMI service never shows up with this ID, leading to the following error when trying to shutdown the modem: qcom-q6v5-mss 4080000.remoteproc: timeout waiting for ssctl service Set the correct ssctl_id to allow clean shutdown of the modem firmware with the subsystem control service. ssctl_id 0x22 is also used by other modem-only Qualcomm platforms in qcom_q6v5_pas, such as SDX55. Fixes: 4fe236a1d024 ("remoteproc: qcom_q6v5_mss: Add MDM9607") Signed-off-by: Stephan Gerhold Reviewed-by: Mukesh Ojha Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260706-qcom-q6v5-mss-mdm9607-ssctl-id-v1-2-f59e728af621@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_mss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index 3a3d98cc89ff..bef198b9ee63 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -2487,7 +2487,7 @@ static const struct rproc_hexagon_res mdm9607_mss = { .has_ext_cntl_regs = false, .has_vq6 = false, .version = MSS_MDM9607, - .ssctl_id = 0x12, + .ssctl_id = 0x22, }; static const struct rproc_hexagon_res msm8909_mss = { From 44f4911ab8e6f4d69afad5f2571bbd2da421c918 Mon Sep 17 00:00:00 2001 From: Uday Khare Date: Thu, 18 Jun 2026 18:50:54 +0530 Subject: [PATCH 36/64] remoteproc: qcom: Fix glink->node reference leak in qcom_add_glink_subdev In qcom_add_glink_subdev(), the device node reference acquired via of_get_child_by_name() is stored in glink->node. If the subsequent kstrdup_const() allocation for glink->ssr_name fails, the function returns early without calling of_node_put() on glink->node, leaking the reference count. Fix this by adding of_node_put(glink->node) on the error path before returning. Fixes: cd9fc8f1b35b ("remoteproc: qcom: Pass ssr_name to glink subdevice") Signed-off-by: Uday Khare Link: https://lore.kernel.org/r/20260618132054.11010-1-udaykhare77@gmail.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/qcom_common.c b/drivers/remoteproc/qcom_common.c index e1a955476c9b..5294e327f158 100644 --- a/drivers/remoteproc/qcom_common.c +++ b/drivers/remoteproc/qcom_common.c @@ -253,8 +253,10 @@ void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink, return; glink->ssr_name = kstrdup_const(ssr_name, GFP_KERNEL); - if (!glink->ssr_name) + if (!glink->ssr_name) { + of_node_put(glink->node); return; + } glink->dev = dev; glink->subdev.start = glink_subdev_start; From bb7c5d6f5b41d192fa81ce404e463f5d3ce70cb3 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Fri, 12 Jun 2026 14:09:08 +0300 Subject: [PATCH 37/64] remoteproc: qcom: q6v5: Make handover IRQ one-shot The handover interrupt is expected to be consumed once during each prepare cycle. If the remote processor keeps signalling handover after the first event, qcom_q6v5 currently logs the duplicate interrupt repeatedly while leaving the IRQ enabled. Track the handover IRQ enable state explicitly and route all handover IRQ enable/disable operations through idempotent helpers. Request the handover IRQ with IRQF_NO_AUTOEN so it is only enabled through the helper during prepare. The handover handler disables it after marking handover as issued, while unprepare disables and synchronizes it before checking whether handover was issued. Signed-off-by: Abel Vesa Link: https://lore.kernel.org/r/20260612-rproc-q6v5-handover-irq-one-shot-v1-1-bb688f4446b3@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5.c | 54 +++++++++++++++++++++++++++------- drivers/remoteproc/qcom_q6v5.h | 4 +++ 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index a11d8ace554b..0206a4a19254 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -36,6 +36,40 @@ static int q6v5_load_state_toggle(struct qcom_q6v5 *q6v5, bool enable) return ret; } +static void q6v5_handover_irq_enable(struct qcom_q6v5 *q6v5) +{ + unsigned long flags; + bool enable = false; + + spin_lock_irqsave(&q6v5->handover_lock, flags); + if (!q6v5->handover_irq_enabled) { + q6v5->handover_irq_enabled = true; + enable = true; + } + spin_unlock_irqrestore(&q6v5->handover_lock, flags); + + if (enable) + enable_irq(q6v5->handover_irq); +} + +static void q6v5_handover_irq_disable(struct qcom_q6v5 *q6v5, bool sync) +{ + unsigned long flags; + bool disable = false; + + spin_lock_irqsave(&q6v5->handover_lock, flags); + if (q6v5->handover_irq_enabled) { + q6v5->handover_irq_enabled = false; + disable = true; + } + spin_unlock_irqrestore(&q6v5->handover_lock, flags); + + if (disable) + disable_irq_nosync(q6v5->handover_irq); + if (sync) + synchronize_irq(q6v5->handover_irq); +} + /** * qcom_q6v5_prepare() - reinitialize the qcom_q6v5 context before start * @q6v5: reference to qcom_q6v5 context to be reinitialized @@ -64,7 +98,7 @@ int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5) q6v5->running = true; q6v5->handover_issued = false; - enable_irq(q6v5->handover_irq); + q6v5_handover_irq_enable(q6v5); return 0; } @@ -78,7 +112,8 @@ EXPORT_SYMBOL_GPL(qcom_q6v5_prepare); */ int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5) { - disable_irq(q6v5->handover_irq); + q6v5_handover_irq_disable(q6v5, true); + q6v5_load_state_toggle(q6v5, false); /* Disable interconnect vote, in case handover never happened */ @@ -164,18 +199,15 @@ static irqreturn_t q6v5_handover_interrupt(int irq, void *data) { struct qcom_q6v5 *q6v5 = data; - if (q6v5->handover_issued) { - dev_err(q6v5->dev, "Handover signaled, but it already happened\n"); - return IRQ_HANDLED; - } + q6v5->handover_issued = true; + + q6v5_handover_irq_disable(q6v5, false); if (q6v5->handover) q6v5->handover(q6v5); icc_set_bw(q6v5->path, 0, 0); - q6v5->handover_issued = true; - return IRQ_HANDLED; } @@ -257,6 +289,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, q6v5->crash_reason = crash_reason; q6v5->handover = handover; + spin_lock_init(&q6v5->handover_lock); + init_completion(&q6v5->start_done); init_completion(&q6v5->stop_done); @@ -305,13 +339,13 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, ret = devm_request_threaded_irq(&pdev->dev, q6v5->handover_irq, NULL, q6v5_handover_interrupt, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, + IRQF_TRIGGER_RISING | IRQF_ONESHOT | + IRQF_NO_AUTOEN, "q6v5 handover", q6v5); if (ret) { dev_err(&pdev->dev, "failed to acquire handover IRQ\n"); return ret; } - disable_irq(q6v5->handover_irq); q6v5->stop_irq = platform_get_irq_byname(pdev, "stop-ack"); if (q6v5->stop_irq < 0) diff --git a/drivers/remoteproc/qcom_q6v5.h b/drivers/remoteproc/qcom_q6v5.h index 5a859c41896e..8991ff090579 100644 --- a/drivers/remoteproc/qcom_q6v5.h +++ b/drivers/remoteproc/qcom_q6v5.h @@ -5,6 +5,7 @@ #include #include +#include #include struct icc_path; @@ -29,6 +30,9 @@ struct qcom_q6v5 { int handover_irq; int stop_irq; + /* Protects handover_irq_enabled against stop/handover races. */ + spinlock_t handover_lock; + bool handover_irq_enabled; bool handover_issued; struct completion start_done; From 3d88927742c6073d5eb772886a98aed014d50180 Mon Sep 17 00:00:00 2001 From: Yijie Yang Date: Mon, 15 Jun 2026 16:30:21 +0800 Subject: [PATCH 38/64] dt-bindings: remoteproc: qcom,sm8550-pas: Add Qualcomm Maili ADSP and CDSP Document compatible strings for the ADSP and CDSP Peripheral Authentication Services on the Qualcomm Maili SoC. Both are compatible with the Qualcomm SM8550 PAS and can fallback to SM8550 except for one additional interrupt ("shutdown-ack"). For CDSP, similar to Kaanapali, "global_sync_mem" is not managed by the kernel. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Yijie Yang Acked-by: Rob Herring (Arm) Acked-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260615-remoteproc-v1-1-67721b4b052a@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index faf7b2890de8..2a4c527552e6 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -32,6 +32,7 @@ properties: - qcom,glymur-adsp-pas - qcom,hawi-adsp-pas - qcom,kaanapali-adsp-pas + - qcom,maili-adsp-pas - qcom,sm8750-adsp-pas - const: qcom,sm8550-adsp-pas - items: @@ -39,6 +40,7 @@ properties: - qcom,glymur-cdsp-pas - qcom,hawi-cdsp-pas - qcom,kaanapali-cdsp-pas + - qcom,maili-cdsp-pas - const: qcom,sm8550-cdsp-pas - items: - const: qcom,sm8750-cdsp-pas @@ -138,6 +140,8 @@ allOf: - qcom,hawi-cdsp-pas - qcom,kaanapali-adsp-pas - qcom,kaanapali-cdsp-pas + - qcom,maili-adsp-pas + - qcom,maili-cdsp-pas - qcom,sm8750-adsp-pas then: properties: From 026a3fada43261e403c6c4d9bda9501547e3f108 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 23 Jun 2026 02:05:34 -0700 Subject: [PATCH 39/64] remoteproc: core: Attach rproc asynchronously in rproc_add() path via schedule_work() Unlike the remoteproc firmware load path where rproc_add() call rproc_auto_boot_callback() asynchronously and ignores the return value of rproc_boot(), the attach path calls rproc_boot() synchronously and propagates its return value back to rproc_add(). This means a failure during rproc_attach() causes rproc_add() to fail and triggers resource release, removing the remoteproc from sysfs and making it unavailable for recovery or further boot attempts. Align the remoteproc attach path with the firmware load path by introducing attach_work and scheduling rproc_boot() asynchronously via schedule_work(). This keeps the remoteproc registered and available in sysfs even if the initial attach attempt fails, and avoids blocking rproc_add() on the attach result. Signed-off-by: Jingyi Wang Link: https://lore.kernel.org/r/20260623-rproc-attach-issue-v3-1-8e24310707ce@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 20 ++++++++++++-------- include/linux/remoteproc.h | 2 ++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 8393468fa1ee..d21669976ccf 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1668,18 +1668,21 @@ static void rproc_auto_boot_callback(const struct firmware *fw, void *context) release_firmware(fw); } +static void rproc_attach_work(struct work_struct *work) +{ + struct rproc *rproc = container_of(work, struct rproc, attach_work); + + rproc_boot(rproc); +} + static int rproc_trigger_auto_boot(struct rproc *rproc) { int ret; - /* - * Since the remote processor is in a detached state, it has already - * been booted by another entity. As such there is no point in waiting - * for a firmware image to be loaded, we can simply initiate the process - * of attaching to it immediately. - */ - if (rproc->state == RPROC_DETACHED) - return rproc_boot(rproc); + if (rproc->state == RPROC_DETACHED) { + schedule_work(&rproc->attach_work); + return 0; + } /* * We're initiating an asynchronous firmware loading, so we can @@ -2520,6 +2523,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, INIT_LIST_HEAD(&rproc->dump_segments); INIT_WORK(&rproc->crash_handler, rproc_crash_handler_work); + INIT_WORK(&rproc->attach_work, rproc_attach_work); rproc->state = RPROC_OFFLINE; diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index 7c1546d48008..f1d14d075bf3 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -259,6 +259,7 @@ enum rproc_features { * @subdevs: list of subdevices, to following the running state * @notifyids: idr for dynamically assigning rproc-wide unique notify ids * @index: index of this rproc device + * @attach_work: workqueue for attaching rproc * @crash_handler: workqueue for handling a crash * @crash_cnt: crash counter * @recovery_disabled: flag that state if recovery was disabled @@ -301,6 +302,7 @@ struct rproc { struct list_head subdevs; struct idr notifyids; int index; + struct work_struct attach_work; struct work_struct crash_handler; unsigned int crash_cnt; bool recovery_disabled; From f44ae8ce156a387b07d40e2d6a0ef979a2748aa1 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 23 Jun 2026 02:05:35 -0700 Subject: [PATCH 40/64] remoteproc: qcom: Check subdev start status in rproc_stop() For rproc that doing attach, rproc_start_subdevices() is called only when attach successfully. If rproc_report_crash() is called in the attach function, rproc_boot_recovery()->rproc_stop()->rproc_stop_subdevices()-> glink_subdev_stop() could be called and cause NULL pointer dereference: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000300 Mem abort info: ... pc : qcom_glink_smem_unregister+0x14/0x48 [qcom_glink_smem] lr : glink_subdev_stop+0x1c/0x30 [qcom_common] ... Call trace: qcom_glink_smem_unregister+0x14/0x48 [qcom_glink_smem] (P) glink_subdev_stop+0x1c/0x30 [qcom_common] rproc_stop+0x58/0x17c rproc_trigger_recovery+0xb0/0x150 rproc_crash_handler_work+0xa4/0xc4 process_scheduled_works+0x18c/0x2d8 worker_thread+0x144/0x280 kthread+0x124/0x138 ret_from_fork+0x10/0x20 Code: a9be7bfd 910003fd a90153f3 aa0003f3 (b9430000) ---[ end trace 0000000000000000 ]--- Introduce "subdevs_started" flag to indicate rproc_start_subdevices() has been called successfully. Ensure subdevices are only stopped if they have been started. Signed-off-by: Jingyi Wang Link: https://lore.kernel.org/r/20260623-rproc-attach-issue-v3-2-8e24310707ce@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 7 +++++++ include/linux/remoteproc.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index d21669976ccf..28ad42c31f0f 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1099,6 +1099,8 @@ static int rproc_start_subdevices(struct rproc *rproc) } } + rproc->subdevs_started = true; + return 0; unroll_registration: @@ -1114,10 +1116,15 @@ static void rproc_stop_subdevices(struct rproc *rproc, bool crashed) { struct rproc_subdev *subdev; + if (!rproc->subdevs_started) + return; + list_for_each_entry_reverse(subdev, &rproc->subdevs, node) { if (subdev->stop) subdev->stop(subdev, crashed); } + + rproc->subdevs_started = false; } static void rproc_unprepare_subdevices(struct rproc *rproc) diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index f1d14d075bf3..17ed75a11e15 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -272,6 +272,7 @@ enum rproc_features { * @has_iommu: flag to indicate if remote processor is behind an MMU * @auto_boot: flag to indicate if remote processor should be auto-started * @sysfs_read_only: flag to make remoteproc sysfs files read only + * @subdevs_started: flag to indicate if subdevs have started * @dump_segments: list of segments in the firmware * @nb_vdev: number of vdev currently handled by rproc * @elf_class: firmware ELF class @@ -314,6 +315,7 @@ struct rproc { bool has_iommu; bool auto_boot; bool sysfs_read_only; + bool subdevs_started; struct list_head dump_segments; int nb_vdev; u8 elf_class; From 0ec167625b4fea30b26da33c188e853ff25d5583 Mon Sep 17 00:00:00 2001 From: Jingyi Wang Date: Tue, 23 Jun 2026 02:05:36 -0700 Subject: [PATCH 41/64] remoteproc: core: cancel crash_handler work in rproc_add() error path Ensure crash_handler work is cancelled before tearing down rproc resources to avoid accessing freed memory. Signed-off-by: Jingyi Wang Link: https://lore.kernel.org/r/20260623-rproc-attach-issue-v3-3-8e24310707ce@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 28ad42c31f0f..0583d3a56212 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -2340,6 +2340,7 @@ int rproc_add(struct rproc *rproc) return 0; rproc_remove_dev: + cancel_work_sync(&rproc->crash_handler); rproc_delete_debug_dir(rproc); device_del(dev); rproc_remove_cdev: From e1de7da25434994c3d270cbed0d2311d9620da09 Mon Sep 17 00:00:00 2001 From: Vishnu Santhosh Date: Sat, 11 Jul 2026 09:34:18 +0530 Subject: [PATCH 42/64] remoteproc: qcom_q6v5_pas: Create platform device for BAM-DMUX Some Qualcomm SoCs using the generic PAS remoteproc driver (e.g. Shikra) implement the BAM-DMUX protocol on the modem remoteproc to expose network data channels. The hardware/firmware resources required by the BAM-DMUX driver are described in an extra device tree node below the modem remoteproc, with the compatible "qcom,bam-dmux". qcom_q6v5_mss.c already creates a platform device for this node (commit 59983c74fc42 ("remoteproc: qcom_q6v5_mss: Create platform device for BAM-DMUX")), but qcom_q6v5_pas.c has no equivalent logic, so the bam-dmux node never probes on SoCs handled by this driver. Mirror the qcom_q6v5_mss.c approach: create a platform device specifically for the "qcom,bam-dmux" child node on probe, and destroy it on remove. of_get_compatible_child() returns NULL when the node is absent, and of_platform_device_create()/of_node_put() are NULL-safe, so this is a no-op for the many PAS-based SoCs that have no bam-dmux child. Signed-off-by: Vishnu Santhosh Link: https://lore.kernel.org/r/20260711-qcom-q6v5-pas-bam-dmux-v1-1-1e9231143b79@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index f0f87ad3007f..25599d728208 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -117,6 +118,7 @@ struct qcom_pas { struct qcom_rproc_pdm pdm_subdev; struct qcom_rproc_ssr ssr_subdev; struct qcom_sysmon *sysmon; + struct platform_device *bam_dmux; struct qcom_pas_context *pas_ctx; struct qcom_pas_context *dtb_pas_ctx; @@ -801,6 +803,7 @@ static int qcom_pas_probe(struct platform_device *pdev) const struct qcom_pas_data *desc; struct qcom_pas *pas; struct rproc *rproc; + struct device_node *node; const char *fw_name, *dtb_fw_name = NULL; const struct rproc_ops *ops = &qcom_pas_ops; int ret; @@ -926,6 +929,10 @@ static int qcom_pas_probe(struct platform_device *pdev) if (ret) goto remove_ssr_sysmon; + node = of_get_compatible_child(pdev->dev.of_node, "qcom,bam-dmux"); + pas->bam_dmux = of_platform_device_create(node, NULL, &pdev->dev); + of_node_put(node); + return 0; remove_ssr_sysmon: @@ -950,6 +957,9 @@ static void qcom_pas_remove(struct platform_device *pdev) { struct qcom_pas *pas = platform_get_drvdata(pdev); + if (pas->bam_dmux) + of_platform_device_destroy(&pas->bam_dmux->dev, NULL); + rproc_del(pas->rproc); qcom_q6v5_deinit(&pas->q6v5); From a83689d50ef62f518a28311013b97a2da9b42ff1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 12 Jul 2026 16:57:19 +0200 Subject: [PATCH 43/64] dt-bindings: remoteproc: Drop redundant $ref of firmware-name property The DT schema core defines the type ($ref) of 'firmware-name' property as string-array, so individual schemas do not need to. They also should not redefine it to a single string, but instead just set number of expected firmware names. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260712145718.126492-2-krzysztof.kozlowski@oss.qualcomm.com Signed-off-by: Mathieu Poirier Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml | 2 +- .../devicetree/bindings/remoteproc/ti,pru-consumer.yaml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml b/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml index 3f710433e937..4cd5121b9a4e 100644 --- a/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml +++ b/Documentation/devicetree/bindings/remoteproc/amlogic,meson-mx-ao-arc.yaml @@ -25,7 +25,7 @@ properties: - const: amlogic,meson-mx-ao-arc firmware-name: - $ref: /schemas/types.yaml#/definitions/string + maxItems: 1 description: The name of the firmware which should be loaded for this remote processor. diff --git a/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml b/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml index 2811334515d1..591471e5f93a 100644 --- a/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml +++ b/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml @@ -30,7 +30,6 @@ properties: maxItems: 1 firmware-name: - $ref: /schemas/types.yaml#/definitions/string-array minItems: 1 maxItems: 6 description: | From 40acbf6097c5930e9a3ff907d02ce69023b449c4 Mon Sep 17 00:00:00 2001 From: Ananthu C V Date: Thu, 9 Jul 2026 23:39:42 -0700 Subject: [PATCH 44/64] dt-bindings: remoteproc: qcom: move glymur SoCCP pas to standalone SHM bridge creation is required to enable memory protection for both remoteproc metadata and its memory region on Qualcomm SoCs like Glymur running non-Gunyah based Hypervisors, unlike Kaanapali. Having Glymur fall back to the Kaanapali binding is therefore incorrect and breaks subsystem restart on Glymur. Fix this by decoupling Glymur SoCCP PAS from Kaanapali and registering it as its own binding. Fixes: 8b54bacadc0c ("dt-bindings: remoteproc: qcom: Document pas for SoCCP on Kaanapali and Glymur platforms") Signed-off-by: Ananthu C V Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260709-glymur-soccp-v6-1-16f70227547d@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml index 8fd6913e414d..e6c78d621d17 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,kaanapali-soccp-pas.yaml @@ -20,11 +20,11 @@ properties: oneOf: - items: - enum: - - qcom,glymur-soccp-pas - qcom,hawi-soccp-pas - qcom,maili-soccp-pas - const: qcom,kaanapali-soccp-pas - enum: + - qcom,glymur-soccp-pas - qcom,kaanapali-soccp-pas reg: From 8527ebd21a5691d10922ab8c8ab7cb02de6b4f8b Mon Sep 17 00:00:00 2001 From: Ben Levinsky Date: Tue, 14 Jul 2026 13:24:40 -0700 Subject: [PATCH 45/64] dt-bindings: remoteproc: Document AMD MicroBlaze/V BRAM-based rproc Describe an AMD MicroBlaze/V BRAM-based remote processor controlled through the remoteproc framework. The binding models a soft-core processor subsystem instantiated in AMD programmable logic and using dual-port BRAM for firmware storage and execution. The remoteproc device is represented as a child node whose reg property describes the firmware memory window in the processor-local address space. The parent bus node provides standard devicetree address translation through ranges so Linux can access the same BRAM through the system physical address space. A clock input feeds the soft-core processor subsystem, and an active-low reset GPIO holds the processor in reset until firmware loading completes. The firmware-name property is optional. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Ben Levinsky Link: https://lore.kernel.org/r/20260714202441.554065-2-ben.levinsky@amd.com Signed-off-by: Mathieu Poirier --- .../bindings/remoteproc/amd,bram-rproc.yaml | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 Documentation/devicetree/bindings/remoteproc/amd,bram-rproc.yaml diff --git a/Documentation/devicetree/bindings/remoteproc/amd,bram-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/amd,bram-rproc.yaml new file mode 100644 index 000000000000..c0359f447ea8 --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/amd,bram-rproc.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/remoteproc/amd,bram-rproc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AMD MicroBlaze/V BRAM-based Remote Processor + +maintainers: + - Ben Levinsky + +description: | + Soft-core processor subsystem instantiated in AMD programmable logic and + using dual-port BRAM for firmware storage and execution. + + Hardware Architecture: + + Host (PS) Programmable Logic (PL) + ========= ====================== + + AXI Interface -----------------> AXI BRAM Controller (Host Port) + | + | Port A + v + +-----------------+ + | Dual-Port BRAM | + | (shared memory) | + +-----------------+ + ^ + | Port B + | + AXI BRAM Controller (Soft-core Port) + ^ + | LMB + | + Soft-core CPU (MicroBlaze/V) + + GPIO --------------------------> Proc Sys Reset ----> CPU Reset Signal + + Clock -------------------------> Clock Distribution -> CPU Clock + + Memory Architecture: + + The dual-port BRAM allows simultaneous access from both processors: + - Port A: Connected to the host AXI BRAM controller for firmware loading + - Port B: Connected to the soft-core local memory bus for execution + + The reg property describes the executable BRAM window in the processor-local + address space. The parent bus node translates that window to the system + physical address space by using standard devicetree address translation + through ranges. A clock input and a reset GPIO control the subsystem. + +properties: + compatible: + oneOf: + - const: xlnx,zynqmp-bram-rproc + - items: + - enum: + - amd,versal2-bram-rproc + - xlnx,versal-bram-rproc + - xlnx,versal-net-bram-rproc + - const: xlnx,zynqmp-bram-rproc + + reg: + maxItems: 1 + description: + Processor-local address and size of the BRAM firmware memory window, + as seen by the soft-core processor (typically 0x0 for reset vector). + The parent bus ranges property must translate this window to the + corresponding system physical address. + + clocks: + maxItems: 1 + description: + Clock input for the soft-core processor subsystem. + + firmware-name: + maxItems: 1 + description: + Name of the firmware ELF file to load. + + reset-gpios: + maxItems: 1 + description: + GPIO specifier controlling the soft-core reset input. + +required: + - compatible + - reg + - clocks + - reset-gpios + +additionalProperties: false + +examples: + - | + #include + remoteproc@0 { + compatible = "xlnx,zynqmp-bram-rproc"; + reg = <0x0 0x40000>; + clocks = <&pl_clk>; + firmware-name = "firmware.elf"; + reset-gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; + }; +... From f87b4998994ebe7743eb0981257c4e789d3fa290 Mon Sep 17 00:00:00 2001 From: Ben Levinsky Date: Tue, 14 Jul 2026 13:24:41 -0700 Subject: [PATCH 46/64] remoteproc: Add AMD MicroBlaze/V BRAM-based remote processor driver Add a remoteproc driver for AMD MicroBlaze/V soft-core processor subsystems instantiated in programmable logic and using dual-port BRAM for firmware storage and execution. The driver parses the firmware memory window from the remoteproc device node's reg property, interprets that address and size in the processor-local address space, and then uses standard devicetree address translation through the parent bus ranges property to obtain the corresponding Linux-visible system physical address. The resulting translated region is registered as the executable remoteproc carveout and coredump segment. The processor is controlled through an active-low reset GPIO and a subsystem clock. The clock is enabled before reset is released, and the processor is kept in reset until firmware loading completes. The firmware-name property is optional, allowing firmware to be assigned later through the remoteproc framework. Firmware images without a resource table are also accepted. Signed-off-by: Ben Levinsky Link: https://lore.kernel.org/r/20260714202441.554065-3-ben.levinsky@amd.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/Kconfig | 9 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/amd_mbv_bram_rproc.c | 213 ++++++++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 drivers/remoteproc/amd_mbv_bram_rproc.c diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 65befdbfa5f7..5b56b2dcc725 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -23,6 +23,15 @@ config REMOTEPROC_CDEV It's safe to say N if you don't want to use this interface. +config AMD_MBV_BRAM_REMOTEPROC + tristate "AMD MicroBlaze/V BRAM-based remoteproc support" + depends on OF && COMMON_CLK && (GPIOLIB || COMPILE_TEST) + help + Say y or m here to support a MicroBlaze/V BRAM-based remote + processor managed through the remoteproc framework. + + If unsure, say N. + config IMX_REMOTEPROC tristate "i.MX remoteproc support" depends on ARCH_MXC diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 1c7598b8475d..689686de0d41 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -11,6 +11,7 @@ remoteproc-y += remoteproc_sysfs.o remoteproc-y += remoteproc_virtio.o remoteproc-y += remoteproc_elf_loader.o obj-$(CONFIG_REMOTEPROC_CDEV) += remoteproc_cdev.o +obj-$(CONFIG_AMD_MBV_BRAM_REMOTEPROC) += amd_mbv_bram_rproc.o obj-$(CONFIG_IMX_REMOTEPROC) += imx_rproc.o obj-$(CONFIG_IMX_DSP_REMOTEPROC) += imx_dsp_rproc.o obj-$(CONFIG_INGENIC_VPU_RPROC) += ingenic_rproc.o diff --git a/drivers/remoteproc/amd_mbv_bram_rproc.c b/drivers/remoteproc/amd_mbv_bram_rproc.c new file mode 100644 index 000000000000..e4a103cf8455 --- /dev/null +++ b/drivers/remoteproc/amd_mbv_bram_rproc.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AMD MicroBlaze/V BRAM-based Remote Processor driver + * + * Copyright (C) 2026 Advanced Micro Devices, Inc. + * + * This driver supports soft-core processors (MicroBlaze, MicroBlaze-V, or + * similar) instantiated in AMD programmable logic, using dual-port BRAM + * for firmware storage and execution. + * + * The firmware memory (BRAM) is described in the processor-local address + * space and translated to the Linux-visible system physical address with + * standard devicetree address translation. + * + * Reset is controlled via GPIO connected to Processor System Reset IP. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "remoteproc_internal.h" + +/** + * struct amd_bram_rproc - AMD MicroBlaze/V BRAM-based remoteproc private data + * @dev: device pointer + * @reset: GPIO descriptor for reset control (active-low) + * @clk: processor clock + */ +struct amd_bram_rproc { + struct device *dev; + struct gpio_desc *reset; + struct clk *clk; +}; + +static int amd_bram_rproc_prepare(struct rproc *rproc) +{ + struct amd_bram_rproc *priv = rproc->priv; + struct rproc_mem_entry *mem; + struct resource res; + u64 da, size; + int ret; + + ret = of_property_read_reg(priv->dev->of_node, 0, &da, &size); + if (ret) { + dev_err(priv->dev, "failed to parse executable memory reg\n"); + return ret; + } + + if (!size || size > U32_MAX) { + dev_err(priv->dev, "invalid executable memory size\n"); + return -EINVAL; + } + + if (da > U32_MAX) { + dev_err(priv->dev, "invalid executable memory address\n"); + return -EINVAL; + } + + ret = of_address_to_resource(priv->dev->of_node, 0, &res); + if (ret) { + dev_err(priv->dev, "failed to translate executable memory reg\n"); + return ret; + } + + mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)res.start, + resource_size(&res), da, + rproc_mem_entry_ioremap_wc, + rproc_mem_entry_iounmap, + dev_name(priv->dev)); + if (!mem) + return -ENOMEM; + + rproc_add_carveout(rproc, mem); + rproc_coredump_add_segment(rproc, da, resource_size(&res)); + + return 0; +} + +static int amd_bram_rproc_start(struct rproc *rproc) +{ + struct amd_bram_rproc *priv = rproc->priv; + int ret; + + /* Enable clock before releasing reset */ + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(priv->dev, "failed to enable clock: %d\n", ret); + return ret; + } + + /* Deassert reset and let the processor run. */ + ret = gpiod_set_value_cansleep(priv->reset, 0); + if (ret) { + dev_err(priv->dev, "failed to deassert reset: %d\n", ret); + clk_disable_unprepare(priv->clk); + return ret; + } + + return 0; +} + +static int amd_bram_rproc_stop(struct rproc *rproc) +{ + struct amd_bram_rproc *priv = rproc->priv; + int ret; + + /* Assert reset before disabling the processor clock. */ + ret = gpiod_set_value_cansleep(priv->reset, 1); + if (ret) { + dev_err(priv->dev, "failed to assert reset: %d\n", ret); + return ret; + } + + /* Disable clock after asserting reset */ + clk_disable_unprepare(priv->clk); + + return 0; +} + +static int amd_bram_rproc_parse_fw(struct rproc *rproc, + const struct firmware *fw) +{ + rproc_elf_load_rsc_table_optional(rproc, fw, dev_dbg, + "no resource table found\n"); + return 0; +} + +static const struct rproc_ops amd_bram_rproc_ops = { + .prepare = amd_bram_rproc_prepare, + .start = amd_bram_rproc_start, + .stop = amd_bram_rproc_stop, + .load = rproc_elf_load_segments, + .sanity_check = rproc_elf_sanity_check, + .get_boot_addr = rproc_elf_get_boot_addr, + .parse_fw = amd_bram_rproc_parse_fw, +}; + +static int amd_bram_rproc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct amd_bram_rproc *priv; + const char *fw_name = NULL; + struct rproc *rproc; + int ret; + + ret = rproc_of_parse_firmware(dev, 0, &fw_name); + if (ret < 0 && ret != -EINVAL) + return dev_err_probe(dev, ret, + "failed to parse firmware-name property\n"); + + rproc = devm_rproc_alloc(dev, dev_name(dev), &amd_bram_rproc_ops, + fw_name, sizeof(*priv)); + if (!rproc) + return -ENOMEM; + + priv = rproc->priv; + priv->dev = dev; + + /* Get the processor clock */ + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) + return dev_err_probe(dev, PTR_ERR(priv->clk), + "failed to get clock\n"); + + /* + * Keep the processor in reset until remoteproc has finished loading + * firmware into the executable memory window described by reg and + * translated through the parent bus ranges property. + */ + priv->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(priv->reset)) + return dev_err_probe(dev, PTR_ERR(priv->reset), + "failed to get reset gpio\n"); + + rproc->auto_boot = false; + + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + if (ret) + return dev_err_probe(dev, ret, "failed to set DMA mask\n"); + + platform_set_drvdata(pdev, rproc); + + ret = devm_rproc_add(dev, rproc); + if (ret) + return dev_err_probe(dev, ret, "failed to register rproc\n"); + + return 0; +} + +static const struct of_device_id amd_bram_rproc_of_match[] = { + { .compatible = "xlnx,zynqmp-bram-rproc" }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, amd_bram_rproc_of_match); + +static struct platform_driver amd_bram_rproc_driver = { + .probe = amd_bram_rproc_probe, + .driver = { + .name = "amd-bram-rproc", + .of_match_table = amd_bram_rproc_of_match, + }, +}; +module_platform_driver(amd_bram_rproc_driver); + +MODULE_DESCRIPTION("AMD MicroBlaze/V BRAM-based Remote Processor driver"); +MODULE_AUTHOR("Ben Levinsky "); +MODULE_LICENSE("GPL"); From 46841a37948dc9b476744750d44082afd582347e Mon Sep 17 00:00:00 2001 From: Pan Chuang Date: Fri, 17 Jul 2026 14:52:23 +0800 Subject: [PATCH 47/64] remoteproc: Remove redundant dev_err()/dev_err_probe() Since commit 55b48e23f5c4 ("genirq/devres: Add error handling in devm_request_*_irq()"), devm_request_irq() and devm_request_threaded_irq() automatically log detailed error messages on failure. Remove the now-redundant driver-specific dev_err() and dev_err_probe() calls. Signed-off-by: Pan Chuang Acked-by: Paul Cercueil # Ingenic Link: https://lore.kernel.org/r/20260717065224.600593-1-panchuang@vivo.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/da8xx_remoteproc.c | 2 +- drivers/remoteproc/ingenic_rproc.c | 4 +--- drivers/remoteproc/keystone_remoteproc.c | 4 ++-- drivers/remoteproc/mtk_scp.c | 4 +--- drivers/remoteproc/qcom_q6v5.c | 20 +++++--------------- drivers/remoteproc/qcom_sysmon.c | 2 -- drivers/remoteproc/qcom_wcnss.c | 4 +--- drivers/remoteproc/stm32_rproc.c | 3 +-- 8 files changed, 12 insertions(+), 31 deletions(-) diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c index 23fca7176539..006fa7b56727 100644 --- a/drivers/remoteproc/da8xx_remoteproc.c +++ b/drivers/remoteproc/da8xx_remoteproc.c @@ -298,7 +298,7 @@ static int da8xx_rproc_probe(struct platform_device *pdev) handle_event, 0, "da8xx-remoteproc", rproc); if (ret) - return dev_err_probe(dev, ret, "devm_request_threaded_irq error\n"); + return ret; /* * rproc_add() can end up enabling the DSP's clk with the DSP diff --git a/drivers/remoteproc/ingenic_rproc.c b/drivers/remoteproc/ingenic_rproc.c index 1b78d8ddeacf..252519f48964 100644 --- a/drivers/remoteproc/ingenic_rproc.c +++ b/drivers/remoteproc/ingenic_rproc.c @@ -219,10 +219,8 @@ static int ingenic_rproc_probe(struct platform_device *pdev) ret = devm_request_irq(dev, vpu->irq, vpu_interrupt, IRQF_NO_AUTOEN, "VPU", rproc); - if (ret < 0) { - dev_err(dev, "Failed to request IRQ\n"); + if (ret < 0) return ret; - } ret = devm_rproc_add(dev, rproc); if (ret) { diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c index 83763d640c4e..407d6034f748 100644 --- a/drivers/remoteproc/keystone_remoteproc.c +++ b/drivers/remoteproc/keystone_remoteproc.c @@ -411,7 +411,7 @@ static int keystone_rproc_probe(struct platform_device *pdev) ret = devm_request_irq(dev, ksproc->irq_ring, keystone_rproc_vring_interrupt, IRQF_NO_AUTOEN, dev_name(dev), ksproc); if (ret) - return dev_err_probe(dev, ret, "failed to request vring interrupt\n"); + return ret; ksproc->irq_fault = platform_get_irq_byname(pdev, "exception"); if (ksproc->irq_fault < 0) @@ -419,7 +419,7 @@ static int keystone_rproc_probe(struct platform_device *pdev) ret = devm_request_irq(dev, ksproc->irq_fault, keystone_rproc_exception_interrupt, IRQF_NO_AUTOEN, dev_name(dev), ksproc); if (ret) - return dev_err_probe(dev, ret, "failed to enable exception interrupt\n"); + return ret; ksproc->kick_gpio = devm_gpiod_get(dev, "kick", GPIOD_ASIS); ret = PTR_ERR_OR_ZERO(ksproc->kick_gpio); diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c index 436656bdfa8b..9751acc2bf83 100644 --- a/drivers/remoteproc/mtk_scp.c +++ b/drivers/remoteproc/mtk_scp.c @@ -1246,10 +1246,8 @@ static struct mtk_scp *scp_rproc_init(struct platform_device *pdev, scp_irq_handler, IRQF_ONESHOT, pdev->name, scp); - if (ret) { - dev_err(dev, "failed to request irq\n"); + if (ret) goto remove_subdev; - } return scp; diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index 0206a4a19254..1075ef4027b7 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -302,10 +302,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, NULL, q6v5_wdog_interrupt, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "q6v5 wdog", q6v5); - if (ret) { - dev_err(&pdev->dev, "failed to acquire wdog IRQ\n"); + if (ret) return ret; - } q6v5->fatal_irq = platform_get_irq_byname(pdev, "fatal"); if (q6v5->fatal_irq < 0) @@ -315,10 +313,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, NULL, q6v5_fatal_interrupt, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "q6v5 fatal", q6v5); - if (ret) { - dev_err(&pdev->dev, "failed to acquire fatal IRQ\n"); + if (ret) return ret; - } q6v5->ready_irq = platform_get_irq_byname(pdev, "ready"); if (q6v5->ready_irq < 0) @@ -328,10 +324,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, NULL, q6v5_ready_interrupt, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "q6v5 ready", q6v5); - if (ret) { - dev_err(&pdev->dev, "failed to acquire ready IRQ\n"); + if (ret) return ret; - } q6v5->handover_irq = platform_get_irq_byname(pdev, "handover"); if (q6v5->handover_irq < 0) @@ -342,10 +336,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, IRQF_TRIGGER_RISING | IRQF_ONESHOT | IRQF_NO_AUTOEN, "q6v5 handover", q6v5); - if (ret) { - dev_err(&pdev->dev, "failed to acquire handover IRQ\n"); + if (ret) return ret; - } q6v5->stop_irq = platform_get_irq_byname(pdev, "stop-ack"); if (q6v5->stop_irq < 0) @@ -355,10 +347,8 @@ int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, NULL, q6v5_stop_interrupt, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "q6v5 stop", q6v5); - if (ret) { - dev_err(&pdev->dev, "failed to acquire stop-ack IRQ\n"); + if (ret) return ret; - } q6v5->state = devm_qcom_smem_state_get(&pdev->dev, "stop", &q6v5->stop_bit); if (IS_ERR(q6v5->state)) { diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c index a0830a48b1f4..61e1038328e8 100644 --- a/drivers/remoteproc/qcom_sysmon.c +++ b/drivers/remoteproc/qcom_sysmon.c @@ -662,8 +662,6 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "q6v5 shutdown-ack", sysmon); if (ret) { - dev_err(sysmon->dev, - "failed to acquire shutdown-ack IRQ\n"); kfree(sysmon); return ERR_PTR(ret); } diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 3392c9380202..e9a00efe97f6 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -521,10 +521,8 @@ static int wcnss_request_irq(struct qcom_wcnss *wcnss, NULL, thread_fn, IRQF_TRIGGER_RISING | IRQF_ONESHOT, "wcnss", wcnss); - if (ret) { - dev_err(&pdev->dev, "request %s IRQ failed\n", name); + if (ret) return ret; - } /* Return the IRQ number if the IRQ was successfully acquired */ return irq_number; diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index 0e5d64fbe52c..1fe4cdc0a13a 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -682,8 +682,7 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev, err = devm_request_irq(dev, irq, stm32_rproc_wdg, 0, dev_name(dev), pdev); if (err) - return dev_err_probe(dev, err, - "failed to request wdg irq\n"); + return err; ddata->wdg_irq = irq; From 3db03f63ab8961d42e1bc443a1a42354ed81ea81 Mon Sep 17 00:00:00 2001 From: Bhargav Joshi Date: Sun, 19 Jul 2026 23:36:41 +0530 Subject: [PATCH 48/64] dt-bindings: remoteproc: ti,wkup-m3: Convert to DT schema Convert Texas Instruments Wakeup M3 Remote Processor from text to Dt schema. Add optional resets and reset-names property which was missing from legacy binding. make ti,hwmods deprecated as it no longer needed, it is kept to support older board files without ti,sysc. Signed-off-by: Bhargav Joshi Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20260719-ti-wkup_m3-v1-1-848a95b401a5@gmail.com Signed-off-by: Mathieu Poirier --- .../remoteproc/ti,am3352-wkup-m3.yaml | 89 +++++++++++++++++++ .../bindings/remoteproc/wkup_m3_rproc.txt | 52 ----------- 2 files changed, 89 insertions(+), 52 deletions(-) create mode 100644 Documentation/devicetree/bindings/remoteproc/ti,am3352-wkup-m3.yaml delete mode 100644 Documentation/devicetree/bindings/remoteproc/wkup_m3_rproc.txt diff --git a/Documentation/devicetree/bindings/remoteproc/ti,am3352-wkup-m3.yaml b/Documentation/devicetree/bindings/remoteproc/ti,am3352-wkup-m3.yaml new file mode 100644 index 000000000000..9e8a03acdec4 --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/ti,am3352-wkup-m3.yaml @@ -0,0 +1,89 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/remoteproc/ti,am3352-wkup-m3.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: TI AM33xx/AM43xx Wakeup M3 Remote Processor + +maintainers: + - Suman Anna + - Bhargav Joshi + +description: + The TI AM33xx and AM43xx family of devices use a small Cortex M3 co-processor + (commonly referred to as Wakeup M3 or CM3) to help with various low power + tasks that cannot be controlled from the MPU. This CM3 processor requires a + firmware binary to accomplish this. A wkup_m3 device node is used to + represent the Wakeup M3 processor instance within the SoC. It is added as a + child node of the parent interconnect bus (l4_wkup) through which it is + accessible to the MPU. + +properties: + compatible: + enum: + - ti,am3352-wkup-m3 + - ti,am4372-wkup-m3 + + reg: + items: + - description: Address range for UMEM + - description: Address range for DMEM + + reg-names: + items: + - const: umem + - const: dmem + + ti,pm-firmware: + $ref: /schemas/types.yaml#/definitions/string + description: + Name of firmware file to be used for loading and booting the wkup_m3 + remote processor. + + resets: + maxItems: 1 + + reset-names: + items: + - const: rstctrl + + ti,hwmods: + $ref: /schemas/types.yaml#/definitions/string + deprecated: true + description: + Name of the hwmod associated with the wkupm3 device. + +required: + - compatible + - reg + - reg-names + - ti,pm-firmware + +dependencies: + resets: [reset-names] + reset-names: [resets] + +additionalProperties: false + +examples: + - | + target-module@0 { + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x0 0x4>; + reg-names = "rev"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00000000 0x00000000 0x4000>, + <0x00080000 0x00080000 0x2000>; + + cpu@0 { + compatible = "ti,am3352-wkup-m3"; + reg = <0x00000000 0x4000>, + <0x00080000 0x2000>; + reg-names = "umem", "dmem"; + resets = <&prm_wkup 3>; + reset-names = "rstctrl"; + ti,pm-firmware = "am335x-pm-firmware.elf"; + }; + }; diff --git a/Documentation/devicetree/bindings/remoteproc/wkup_m3_rproc.txt b/Documentation/devicetree/bindings/remoteproc/wkup_m3_rproc.txt deleted file mode 100644 index 3a70073797eb..000000000000 --- a/Documentation/devicetree/bindings/remoteproc/wkup_m3_rproc.txt +++ /dev/null @@ -1,52 +0,0 @@ -TI Wakeup M3 Remoteproc Driver -============================== - -The TI AM33xx and AM43xx family of devices use a small Cortex M3 co-processor -(commonly referred to as Wakeup M3 or CM3) to help with various low power tasks -that cannot be controlled from the MPU. This CM3 processor requires a firmware -binary to accomplish this. The wkup_m3 remoteproc driver handles the loading of -the firmware and booting of the CM3. - -Wkup M3 Device Node: -==================== -A wkup_m3 device node is used to represent the Wakeup M3 processor instance -within the SoC. It is added as a child node of the parent interconnect bus -(l4_wkup) through which it is accessible to the MPU. - -Required properties: --------------------- -- compatible: Should be one of, - "ti,am3352-wkup-m3" for AM33xx SoCs - "ti,am4372-wkup-m3" for AM43xx SoCs -- reg: Should contain the address ranges for the two internal - memory regions, UMEM and DMEM. The parent node should - provide an appropriate ranges property for properly - translating these into bus addresses. -- reg-names: Contains the corresponding names for the two memory - regions. These should be named "umem" & "dmem". -- ti,hwmods: Name of the hwmod associated with the wkupm3 device. -- ti,pm-firmware: Name of firmware file to be used for loading and - booting the wkup_m3 remote processor. - -Example: --------- -/* AM33xx */ -ocp { - l4_wkup: l4_wkup@44c00000 { - compatible = "am335-l4-wkup", "simple-bus"; - ranges = <0 0x44c00000 0x400000>; - #address-cells = <1>; - #size-cells = <1>; - - wkup_m3: wkup_m3@100000 { - compatible = "ti,am3352-wkup-m3"; - reg = <0x100000 0x4000>, - <0x180000 0x2000>; - reg-names = "umem", "dmem"; - ti,hwmods = "wkup_m3"; - ti,pm-firmware = "am335x-pm-firmware.elf"; - }; - }; - - ... -}; From 2482ca875ef5993df8daee563033d70e2523a25f Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 23 Jul 2026 03:52:27 +0000 Subject: [PATCH 49/64] remoteproc: Allow shutdown of crashed processors rproc_shutdown() rejects a remoteproc in RPROC_CRASHED state, and rproc_del() ignores that error. The result of these two decisions is that a user cannot stop a remoteproc that with recovery disabled that has entered a crash state, and removal of an associated remoteproc driver will release resources without first stopping the remoteproc. Allow rproc_shutdown() to stop crashed processors. Propagate the crash state to subdevice teardown, to allow subdevices to dismantle things appropriately. Assisted-by: OpenCode:GPT-5.5 Fixes: 5e6a0e05270e ("remoteproc: core: Move state checking to remoteproc_core") Signed-off-by: Bjorn Andersson Reviewed-by: Mukesh Ojha Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260723-rproc-rmmod-not-crashing-v1-1-546dfd5de0e6@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 0583d3a56212..3cd4570513c2 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -2002,6 +2002,7 @@ EXPORT_SYMBOL(rproc_boot); int rproc_shutdown(struct rproc *rproc) { struct device *dev = &rproc->dev; + bool crashed; int ret; ret = mutex_lock_interruptible(&rproc->lock); @@ -2011,16 +2012,18 @@ int rproc_shutdown(struct rproc *rproc) } if (rproc->state != RPROC_RUNNING && - rproc->state != RPROC_ATTACHED) { + rproc->state != RPROC_ATTACHED && + rproc->state != RPROC_CRASHED) { ret = -EINVAL; goto out; } + crashed = rproc->state == RPROC_CRASHED; /* if the remote proc is still needed, bail out */ if (!atomic_dec_and_test(&rproc->power)) goto out; - ret = rproc_stop(rproc, false); + ret = rproc_stop(rproc, crashed); if (ret) { atomic_inc(&rproc->power); goto out; From 74ee3b2f5767447c57959994341e5b95f1079977 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 23 Jul 2026 03:52:28 +0000 Subject: [PATCH 50/64] remoteproc: Prevent crash handling to race with rproc_del() There's no synchronization between rproc_crash_handler_work() and rproc_del(), as such it's possible for a driver to be removed while crash-handler work is scheduled, or even executing - resulting in use-after-free issues. To avoid this the scheduled work need to be cancelled and synchronized against before the removal proceeds. In order to ensure that this doesn't race with the reporting, and thereby scheduling new work, a "deleting" flag is introduced. This is similar to the RPROC_DELETE state that was introduced to ensure that "start" didn't race with rproc_del(), but the existing mechanism can not be used as it's valid to call rproc_report_crash() in atomic context - and the "state" is protected by a mutex. In the event that work is cancelled the pm_stay_awake() is left unbalanced and need to be unrolled. The blocking and cancelling of crash-handler work prior to the actual rproc_shutdown() call does have the explicit side-effect that crashes resulting from the shutdown process will not enter the crash-handling path, and as such will not generate devcoredumps etc. Due to the existing mutual exclusion between these code paths there's no concrete reduction in functionality, but further work would be needed to handle this case. Assisted-by: OpenCode:GPT-5.5 Fixes: 8afd519c3470 ("remoteproc: add rproc_report_crash function to notify rproc crashes") Signed-off-by: Bjorn Andersson Reviewed-by: Pradnya Dahiwale Link: https://lore.kernel.org/r/20260723-rproc-rmmod-not-crashing-v1-2-546dfd5de0e6@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 42 +++++++++++++++++++++------ drivers/remoteproc/remoteproc_sysfs.c | 1 - include/linux/remoteproc.h | 13 +++++---- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 3cd4570513c2..899d2058bc45 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1851,6 +1851,11 @@ int rproc_trigger_recovery(struct rproc *rproc) if (ret) return ret; + if (READ_ONCE(rproc->deleting)) { + ret = -ENODEV; + goto unlock_mutex; + } + /* State could have changed before we got the mutex */ if (rproc->state != RPROC_CRASHED) goto unlock_mutex; @@ -1883,6 +1888,11 @@ static void rproc_crash_handler_work(struct work_struct *work) mutex_lock(&rproc->lock); + if (READ_ONCE(rproc->deleting)) { + mutex_unlock(&rproc->lock); + goto out; + } + if (rproc->state == RPROC_CRASHED) { /* handle only the first crash detected */ mutex_unlock(&rproc->lock); @@ -1938,9 +1948,9 @@ int rproc_boot(struct rproc *rproc) return ret; } - if (rproc->state == RPROC_DELETED) { + if (READ_ONCE(rproc->deleting)) { ret = -ENODEV; - dev_err(dev, "can't boot deleted rproc %s\n", rproc->name); + dev_err(dev, "can't boot deleting rproc %s\n", rproc->name); goto unlock_mutex; } @@ -2533,8 +2543,9 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, INIT_LIST_HEAD(&rproc->subdevs); INIT_LIST_HEAD(&rproc->dump_segments); - INIT_WORK(&rproc->crash_handler, rproc_crash_handler_work); INIT_WORK(&rproc->attach_work, rproc_attach_work); + INIT_WORK(&rproc->crash_handler, rproc_crash_handler_work); + spin_lock_init(&rproc->crash_handler_lock); rproc->state = RPROC_OFFLINE; @@ -2598,16 +2609,21 @@ EXPORT_SYMBOL(rproc_put); */ int rproc_del(struct rproc *rproc) { + unsigned long flags; + if (!rproc) return -EINVAL; + spin_lock_irqsave(&rproc->crash_handler_lock, flags); + WRITE_ONCE(rproc->deleting, true); + spin_unlock_irqrestore(&rproc->crash_handler_lock, flags); + + if (cancel_work_sync(&rproc->crash_handler)) + pm_relax(rproc->dev.parent); + /* TODO: make sure this works with rproc->power > 1 */ rproc_shutdown(rproc); - mutex_lock(&rproc->lock); - rproc->state = RPROC_DELETED; - mutex_unlock(&rproc->lock); - rproc_delete_debug_dir(rproc); /* the rproc is downref'ed as soon as it's removed from the klist */ @@ -2719,18 +2735,26 @@ EXPORT_SYMBOL(rproc_get_by_child); */ void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type) { + unsigned long flags; + if (!rproc) { pr_err("NULL rproc pointer\n"); return; } + spin_lock_irqsave(&rproc->crash_handler_lock, flags); + if (READ_ONCE(rproc->deleting)) { + spin_unlock_irqrestore(&rproc->crash_handler_lock, flags); + return; + } + /* Prevent suspend while the remoteproc is being recovered */ pm_stay_awake(rproc->dev.parent); + queue_work(rproc_recovery_wq, &rproc->crash_handler); + spin_unlock_irqrestore(&rproc->crash_handler_lock, flags); dev_err(&rproc->dev, "crash detected in %s: type %s\n", rproc->name, rproc_crash_to_string(type)); - - queue_work(rproc_recovery_wq, &rproc->crash_handler); } EXPORT_SYMBOL(rproc_report_crash); diff --git a/drivers/remoteproc/remoteproc_sysfs.c b/drivers/remoteproc/remoteproc_sysfs.c index 138e752c5e4e..925b0cdbe577 100644 --- a/drivers/remoteproc/remoteproc_sysfs.c +++ b/drivers/remoteproc/remoteproc_sysfs.c @@ -168,7 +168,6 @@ static const char * const rproc_state_string[] = { [RPROC_SUSPENDED] = "suspended", [RPROC_RUNNING] = "running", [RPROC_CRASHED] = "crashed", - [RPROC_DELETED] = "deleted", [RPROC_ATTACHED] = "attached", [RPROC_DETACHED] = "detached", [RPROC_LAST] = "invalid", diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index 17ed75a11e15..ef711a5b1a7f 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -145,7 +146,6 @@ struct rproc_ops { * a message. * @RPROC_RUNNING: device is up and running * @RPROC_CRASHED: device has crashed; need to start recovery - * @RPROC_DELETED: device is deleted * @RPROC_ATTACHED: device has been booted by another entity and the core * has attached to it * @RPROC_DETACHED: device has been booted by another entity and waiting @@ -163,10 +163,9 @@ enum rproc_state { RPROC_SUSPENDED = 1, RPROC_RUNNING = 2, RPROC_CRASHED = 3, - RPROC_DELETED = 4, - RPROC_ATTACHED = 5, - RPROC_DETACHED = 6, - RPROC_LAST = 7, + RPROC_ATTACHED = 4, + RPROC_DETACHED = 5, + RPROC_LAST = 6, }; /** @@ -261,6 +260,8 @@ enum rproc_features { * @index: index of this rproc device * @attach_work: workqueue for attaching rproc * @crash_handler: workqueue for handling a crash + * @crash_handler_lock: serializes crash handler queueing and deletion + * @deleting: remoteproc deletion has begun * @crash_cnt: crash counter * @recovery_disabled: flag that state if recovery was disabled * @max_notifyid: largest allocated notify id. @@ -305,6 +306,8 @@ struct rproc { int index; struct work_struct attach_work; struct work_struct crash_handler; + spinlock_t crash_handler_lock; + bool deleting; unsigned int crash_cnt; bool recovery_disabled; int max_notifyid; From 4059c64d78b5d543dabae332922e763b4c95c79e Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 23 Jul 2026 03:52:29 +0000 Subject: [PATCH 51/64] remoteproc: Force shutdown during device removal rproc_del() is subjected to the reference counted shutdown path, as such a remoteproc with more than one reference will be left running as its resources are released underneath it. Refactor the shutdown path such that the reference count value is ignored when called from rproc_del(). Assisted-by: OpenCode:GPT-5.5 Signed-off-by: Bjorn Andersson Reviewed-by: Pradnya Dahiwale Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20260723-rproc-rmmod-not-crashing-v1-3-546dfd5de0e6@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_core.c | 95 +++++++++++++++------------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 899d2058bc45..1ed406714849 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1988,6 +1988,54 @@ unlock_mutex: } EXPORT_SYMBOL(rproc_boot); +static int __rproc_shutdown(struct rproc *rproc, bool force) +{ + struct device *dev = &rproc->dev; + bool crashed; + int ret; + + ret = mutex_lock_interruptible(&rproc->lock); + if (ret) { + dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, ret); + return ret; + } + + if (rproc->state != RPROC_RUNNING && + rproc->state != RPROC_ATTACHED && + rproc->state != RPROC_CRASHED) { + ret = -EINVAL; + goto out; + } + crashed = rproc->state == RPROC_CRASHED; + + if (!atomic_dec_and_test(&rproc->power) && !force) { + /* The remote processor is still needed by another user. */ + goto out; + } + + ret = rproc_stop(rproc, crashed); + if (ret) { + atomic_inc(&rproc->power); + goto out; + } + + /* clean up all acquired resources */ + rproc_resource_cleanup(rproc); + + /* release HW resources if needed */ + rproc_unprepare_device(rproc); + + rproc_disable_iommu(rproc); + + /* Free the copy of the resource table */ + kfree(rproc->cached_table); + rproc->cached_table = NULL; + rproc->table_ptr = NULL; +out: + mutex_unlock(&rproc->lock); + return ret; +} + /** * rproc_shutdown() - power off the remote processor * @rproc: the remote processor @@ -2011,49 +2059,7 @@ EXPORT_SYMBOL(rproc_boot); */ int rproc_shutdown(struct rproc *rproc) { - struct device *dev = &rproc->dev; - bool crashed; - int ret; - - ret = mutex_lock_interruptible(&rproc->lock); - if (ret) { - dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, ret); - return ret; - } - - if (rproc->state != RPROC_RUNNING && - rproc->state != RPROC_ATTACHED && - rproc->state != RPROC_CRASHED) { - ret = -EINVAL; - goto out; - } - crashed = rproc->state == RPROC_CRASHED; - - /* if the remote proc is still needed, bail out */ - if (!atomic_dec_and_test(&rproc->power)) - goto out; - - ret = rproc_stop(rproc, crashed); - if (ret) { - atomic_inc(&rproc->power); - goto out; - } - - /* clean up all acquired resources */ - rproc_resource_cleanup(rproc); - - /* release HW resources if needed */ - rproc_unprepare_device(rproc); - - rproc_disable_iommu(rproc); - - /* Free the copy of the resource table */ - kfree(rproc->cached_table); - rproc->cached_table = NULL; - rproc->table_ptr = NULL; -out: - mutex_unlock(&rproc->lock); - return ret; + return __rproc_shutdown(rproc, false); } EXPORT_SYMBOL(rproc_shutdown); @@ -2621,8 +2627,7 @@ int rproc_del(struct rproc *rproc) if (cancel_work_sync(&rproc->crash_handler)) pm_relax(rproc->dev.parent); - /* TODO: make sure this works with rproc->power > 1 */ - rproc_shutdown(rproc); + __rproc_shutdown(rproc, true); rproc_delete_debug_dir(rproc); From 0ea50486978f109e6d4c32267fab01ed654a2160 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 23 Jul 2026 03:00:41 +0000 Subject: [PATCH 52/64] remoteproc: qcom: q6v5: Request shutdown if crash is triggered host-side rpmsg client drivers are allowed to invoke rproc_report_crash() on their grandparent when they determine that the otherwise seemingly healthy remoteproc has entered a functionally broken state. In the crash handling path qcom_q6v5_request_stop() is invoked, which is based on the current rproc state whether to request a graceful shutdown. But the current rproc `state` will be RPROC_CRASHED regardless of where the crash handler was initiated from, and empirical data shows that unless the firmware is taking part of the shutdown the system state is often left such that it's not possible to start the subsystem again. Use the `running` state in the q6v5 driver to make the decision instead, as this does represent the actual state of the firmware. This makes it possible to reliably trigger a restart from client drivers. Fixes: 3cc889eb83f5 ("remoteproc: qcom: q6v5: Avoid setting smem bit in case of crash shutdown") Signed-off-by: Bjorn Andersson Reviewed-by: Konrad Dybcio Reviewed-by: Mukesh Ojha Link: https://lore.kernel.org/r/20260723-q6v5-host-side-crash-v1-1-23bd53db90a7@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c index 1075ef4027b7..fe148b4b3775 100644 --- a/drivers/remoteproc/qcom_q6v5.c +++ b/drivers/remoteproc/qcom_q6v5.c @@ -229,13 +229,13 @@ static irqreturn_t q6v5_stop_interrupt(int irq, void *data) */ int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5, struct qcom_sysmon *sysmon) { + bool was_running = q6v5->running; int ret; q6v5->running = false; - /* Don't perform SMP2P dance if remote isn't running */ - if ((q6v5->rproc->state != RPROC_RUNNING && q6v5->rproc->state != RPROC_ATTACHED) || - qcom_sysmon_shutdown_acked(sysmon)) + /* A watchdog/fatal IRQ clears running; logical crashes still need a stop. */ + if (!was_running || qcom_sysmon_shutdown_acked(sysmon)) return 0; qcom_smem_state_update_bits(q6v5->state, From ac9e9980375bbec70cc4886842f98b2f471ccc65 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 22 Jul 2026 13:56:48 +0300 Subject: [PATCH 53/64] dt-bindings: remoteproc: qcom,sm8550-pas: Add Eliza CDSP compatible Document compatible string for the CDSP Peripheral Authentication Service on the Eliza SoC. It is not compatible with any other. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Abel Vesa Link: https://lore.kernel.org/r/20260722-remoteproc-eliza-cdsp-v4-1-04c6eee70cb1@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../bindings/remoteproc/qcom,sm8550-pas.yaml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index 2a4c527552e6..9d94eff330ac 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -17,6 +17,7 @@ properties: compatible: oneOf: - enum: + - qcom,eliza-cdsp-pas - qcom,sdx75-mpss-pas - qcom,sm8550-adsp-pas - qcom,sm8550-cdsp-pas @@ -171,6 +172,7 @@ allOf: compatible: contains: enum: + - qcom,eliza-cdsp-pas - qcom,sm8750-cdsp-pas then: properties: @@ -285,6 +287,25 @@ allOf: - const: mxc - const: nsp + - if: + properties: + compatible: + contains: + enum: + - qcom,eliza-cdsp-pas + then: + properties: + power-domains: + items: + - description: CX power domain + - description: MX power domain + - description: NSP power domain + power-domain-names: + items: + - const: cx + - const: mx + - const: nsp + unevaluatedProperties: false examples: From 844d8f49e9d7f0621c10aeea059d59fd957bbd1e Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 22 Jul 2026 13:56:49 +0300 Subject: [PATCH 54/64] remoteproc: qcom: pas: Add Eliza CDSP support Add dedicated driver data for the Eliza CDSP remote processor. It looks almost the same as for Milos, except Eliza needs region assign. Tie the new driver data to the Eliza specific compatible. Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Abel Vesa Link: https://lore.kernel.org/r/20260722-remoteproc-eliza-cdsp-v4-2-04c6eee70cb1@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 25599d728208..c8313c61da94 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -1687,8 +1687,34 @@ static const struct qcom_pas_data glymur_soccp_resource = { .needs_tzmem = true, }; +static const struct qcom_pas_data eliza_cdsp_resource = { + .crash_reason_smem = 601, + .firmware_name = "cdsp.mbn", + .dtb_firmware_name = "cdsp_dtb.mbn", + .pas_id = 18, + .dtb_pas_id = 0x25, + .minidump_id = 7, + .auto_boot = true, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + "nsp", + NULL + }, + .load_state = "cdsp", + .ssr_name = "cdsp", + .sysmon_name = "cdsp", + .ssctl_id = 0x17, + .smem_host_id = 5, + .region_assign_idx = 2, + .region_assign_count = 1, + .region_assign_shared = true, + .region_assign_vmid = QCOM_SCM_VMID_CDSP, +}; + static const struct of_device_id qcom_pas_of_match[] = { { .compatible = "qcom,eliza-adsp-pas", .data = &sm8550_adsp_resource }, + { .compatible = "qcom,eliza-cdsp-pas", .data = &eliza_cdsp_resource }, { .compatible = "qcom,glymur-soccp-pas", .data = &glymur_soccp_resource }, { .compatible = "qcom,kaanapali-soccp-pas", .data = &kaanapali_soccp_resource }, { .compatible = "qcom,milos-adsp-pas", .data = &sm8550_adsp_resource }, From 78fb78cb94d389c1696b439623cebe75775f1d4a Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 22 Jul 2026 12:40:52 +0300 Subject: [PATCH 55/64] dt-bindings: remoteproc: qcom,milos-pas: Move Eliza ADSP to SM8550 schema The ADSP PAS found on Eliza SoC looks fully compatible with SM8750, which can fallback to SM8550 except for the extra interrupt ("shutdown-ack"). So document its bindings in the SM8550 schema instead. Fixes: 7cf2f07f949c ("dt-bindings: remoteproc: qcom,milos-pas: Document Eliza ADSP") Signed-off-by: Abel Vesa Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20260722-dts-qcom-eliza-fix-adsp-binding-v2-1-e1e98ae15533@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/remoteproc/qcom,milos-pas.yaml | 3 --- .../devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml index 99d7337e58ec..b24e6f6eaf37 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,milos-pas.yaml @@ -16,7 +16,6 @@ description: properties: compatible: enum: - - qcom,eliza-adsp-pas - qcom,milos-adsp-pas - qcom,milos-cdsp-pas - qcom,milos-mpss-pas @@ -88,7 +87,6 @@ allOf: properties: compatible: enum: - - qcom,eliza-adsp-pas - qcom,milos-adsp-pas - qcom,milos-cdsp-pas then: @@ -109,7 +107,6 @@ allOf: compatible: contains: enum: - - qcom,eliza-adsp-pas - qcom,milos-adsp-pas then: properties: diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index 9d94eff330ac..c58e8a6c7fe1 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -30,6 +30,7 @@ properties: - qcom,x1e80100-cdsp-pas - items: - enum: + - qcom,eliza-adsp-pas - qcom,glymur-adsp-pas - qcom,hawi-adsp-pas - qcom,kaanapali-adsp-pas @@ -135,6 +136,7 @@ allOf: compatible: contains: enum: + - qcom,eliza-adsp-pas - qcom,glymur-adsp-pas - qcom,glymur-cdsp-pas - qcom,hawi-adsp-pas From b589944ecd95fe4a51bc2aab13ce83b298b7bcc8 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 22 Jul 2026 12:40:53 +0300 Subject: [PATCH 56/64] arm64: dts: qcom: eliza: Add fallback compatible for ADSP remoteproc The ADSP found on Eliza SoC is actually fully compatible with the ones from SM8750 class. So add the SM8550 compatible as fallback, just like the rest from the SM8750 class SoCs. Fixes: 88ddafb01ec0 ("arm64: dts: qcom: eliza: Describe the ADSP and USB related nodes") Reviewed-by: Krzysztof Kozlowski Reviewed-by: Dmitry Baryshkov Signed-off-by: Abel Vesa Link: https://lore.kernel.org/r/20260722-dts-qcom-eliza-fix-adsp-binding-v2-2-e1e98ae15533@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- arch/arm64/boot/dts/qcom/eliza.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/qcom/eliza.dtsi b/arch/arm64/boot/dts/qcom/eliza.dtsi index 977de44b816e..b1b364f69f5f 100644 --- a/arch/arm64/boot/dts/qcom/eliza.dtsi +++ b/arch/arm64/boot/dts/qcom/eliza.dtsi @@ -1969,7 +1969,7 @@ }; remoteproc_adsp: remoteproc@3000000 { - compatible = "qcom,eliza-adsp-pas"; + compatible = "qcom,eliza-adsp-pas", "qcom,sm8550-adsp-pas"; reg = <0x0 0x03000000 0x0 0x10000>; interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>, From 142044ea7bbb83c180319368a8ba088452ceb7f5 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 24 Jul 2026 23:58:53 +0530 Subject: [PATCH 57/64] remoteproc: qcom: annotate mem_region fields with __iomem The firmware memory regions in qcom_adsp, qcom_pas and qcom_wcnss are mapped using devm_ioremap_wc() / devm_ioremap_resource_wc(), which return void __iomem *. However, the mem_region (and dtb_mem_region) fields in the respective driver structs were declared as plain void *, causing sparse to flag address space mismatches: qcom_q6v5_adsp.c:639:26: warning: incorrect type in assignment (different address spaces) qcom_q6v5_adsp.c:639:26: expected void *mem_region qcom_q6v5_adsp.c:639:26: got void [noderef] __iomem * qcom_q6v5_pas.c:141:45: warning: incorrect type in argument 2 (different address spaces) qcom_q6v5_pas.c:141:45: expected void const volatile [noderef] __iomem *src qcom_q6v5_pas.c:141:45: got void * qcom_q6v5_pas.c:637:25: warning: incorrect type in assignment (different address spaces) qcom_q6v5_pas.c:637:25: expected void *mem_region qcom_q6v5_pas.c:637:25: got void [noderef] __iomem * qcom_q6v5_pas.c:654:29: warning: incorrect type in assignment (different address spaces) qcom_q6v5_pas.c:654:29: expected void *dtb_mem_region qcom_q6v5_pas.c:654:29: got void [noderef] __iomem * qcom_wcnss.c:540:27: warning: incorrect type in assignment (different address spaces) qcom_wcnss.c:540:27: expected void *mem_region qcom_wcnss.c:540:27: got void [noderef] __iomem * Fix this by annotating the struct fields with __iomem to correctly reflect the address space of the underlying mapping. These regions are subsequently passed to qcom_mdt_load(), qcom_mdt_load_no_init() and qcom_mdt_pas_load(), all of which take void * and use plain memcpy()/memset() internally to write firmware segments into the region. This is intentional and safe: the mappings are write-combining (WC), which on arm64 permits bulk CPU stores without requiring the memcpy_toio()/memset_io() accessors. Changing the MDT loader API to accept void __iomem * would be a more invasive change and would affect callers. Signed-off-by: Mukesh Ojha Link: https://lore.kernel.org/r/20260724182858.1868271-2-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_adsp.c | 6 +++--- drivers/remoteproc/qcom_q6v5_pas.c | 10 +++++----- drivers/remoteproc/qcom_wcnss.c | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c index c81e6c33c747..39654206781d 100644 --- a/drivers/remoteproc/qcom_q6v5_adsp.c +++ b/drivers/remoteproc/qcom_q6v5_adsp.c @@ -105,7 +105,7 @@ struct qcom_adsp { phys_addr_t mem_phys; phys_addr_t mem_reloc; - void *mem_region; + void __iomem *mem_region; size_t mem_size; bool has_iommu; @@ -318,7 +318,7 @@ static int adsp_load(struct rproc *rproc, const struct firmware *fw) int ret; ret = qcom_mdt_load_no_init(adsp->dev, fw, rproc->firmware, - adsp->mem_region, adsp->mem_phys, + (__force void *)adsp->mem_region, adsp->mem_phys, adsp->mem_size, &adsp->mem_reloc); if (ret) return ret; @@ -492,7 +492,7 @@ static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iom if (offset < 0 || offset + len > adsp->mem_size) return NULL; - return adsp->mem_region + offset; + return (__force void *)adsp->mem_region + offset; } static int adsp_parse_firmware(struct rproc *rproc, const struct firmware *fw) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index c8313c61da94..fb633c2b823d 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -101,8 +101,8 @@ struct qcom_pas { phys_addr_t mem_reloc; phys_addr_t dtb_mem_reloc; phys_addr_t region_assign_phys[MAX_ASSIGN_COUNT]; - void *mem_region; - void *dtb_mem_region; + void __iomem *mem_region; + void __iomem *dtb_mem_region; size_t mem_size; size_t dtb_mem_size; size_t region_assign_size[MAX_ASSIGN_COUNT]; @@ -243,7 +243,7 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw) } ret = qcom_mdt_pas_load(pas->dtb_pas_ctx, pas->dtb_firmware, - pas->dtb_firmware_name, pas->dtb_mem_region, + pas->dtb_firmware_name, (__force void *)pas->dtb_mem_region, &pas->dtb_mem_reloc); if (ret) goto release_dtb_metadata; @@ -321,7 +321,7 @@ static int qcom_pas_start(struct rproc *rproc) } ret = qcom_mdt_pas_load(pas->pas_ctx, pas->firmware, rproc->firmware, - pas->mem_region, &pas->mem_reloc); + (__force void *)pas->mem_region, &pas->mem_reloc); if (ret) goto release_pas_metadata; @@ -447,7 +447,7 @@ static void *qcom_pas_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is if (is_iomem) *is_iomem = true; - return pas->mem_region + offset; + return (__force void *)pas->mem_region + offset; } static int qcom_pas_parse_firmware(struct rproc *rproc, const struct firmware *fw) diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index e9a00efe97f6..c856a92af43c 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -94,7 +94,7 @@ struct qcom_wcnss { phys_addr_t mem_phys; phys_addr_t mem_reloc; - void *mem_region; + void __iomem *mem_region; size_t mem_size; struct qcom_rproc_subdev smd_subdev; @@ -158,7 +158,7 @@ static int wcnss_load(struct rproc *rproc, const struct firmware *fw) int ret; ret = qcom_mdt_load(wcnss->dev, fw, rproc->firmware, WCNSS_PAS_ID, - wcnss->mem_region, wcnss->mem_phys, + (__force void *)wcnss->mem_region, wcnss->mem_phys, wcnss->mem_size, &wcnss->mem_reloc); if (ret) return ret; @@ -327,7 +327,7 @@ static void *wcnss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_io if (offset < 0 || offset + len > wcnss->mem_size) return NULL; - return wcnss->mem_region + offset; + return (__force void *)wcnss->mem_region + offset; } static const struct rproc_ops wcnss_ops = { From c06c5ab4945392d2c2aded6d832ab6b58cabe351 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 24 Jul 2026 23:58:54 +0530 Subject: [PATCH 58/64] remoteproc: qcom: pas: Guard dtb metadata release with dtb_pas_id check All other call sites of qcom_scm_pas_metadata_release() for the DTB context are guarded by a check on pas->dtb_pas_id, but the call inside qcom_pas_load() was not. Fix this by moving the call to the guarded block. Reviewed-by: Konrad Dybcio Fixes: 29814986b82e ("remoteproc: qcom_q6v5_pas: add support for dtb co-firmware loading") Cc: stable@vger.kernel.org Reviewed-by: Dmitry Baryshkov Signed-off-by: Mukesh Ojha Link: https://lore.kernel.org/r/20260724182858.1868271-3-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index fb633c2b823d..507c7008663f 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -245,17 +245,14 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw) ret = qcom_mdt_pas_load(pas->dtb_pas_ctx, pas->dtb_firmware, pas->dtb_firmware_name, (__force void *)pas->dtb_mem_region, &pas->dtb_mem_reloc); - if (ret) - goto release_dtb_metadata; + if (ret) { + qcom_pas_metadata_release(pas->dtb_pas_ctx); + release_firmware(pas->dtb_firmware); + return ret; + } } return 0; - -release_dtb_metadata: - qcom_pas_metadata_release(pas->dtb_pas_ctx); - release_firmware(pas->dtb_firmware); - - return ret; } static void qcom_pas_unmap_carveout(struct rproc *rproc, phys_addr_t mem_phys, size_t size) From a5464fa3173c83da28b46e3c12be6d4a27bf5728 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 24 Jul 2026 23:58:55 +0530 Subject: [PATCH 59/64] remoteproc: qcom: pas: Fix the PAS context creation placement DTB PAS context creation should be done only for subsystems that support a DTB firmware binary; otherwise, memory is wasted. Move the context creation to the appropriate location. Reviewed-by: Konrad Dybcio Reviewed-by: Dmitry Baryshkov Signed-off-by: Mukesh Ojha Link: https://lore.kernel.org/r/20260724182858.1868271-4-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 507c7008663f..b0a3083424fb 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -702,6 +702,11 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) return PTR_ERR(pas->mem_region); } + pas->pas_ctx = devm_qcom_pas_context_alloc(pas->dev, pas->pas_id, + pas->mem_phys, pas->mem_size); + if (IS_ERR(pas->pas_ctx)) + return PTR_ERR(pas->pas_ctx); + if (!pas->dtb_pas_id) return 0; @@ -719,6 +724,12 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) return PTR_ERR(pas->dtb_mem_region); } + pas->dtb_pas_ctx = devm_qcom_pas_context_alloc(pas->dev, pas->dtb_pas_id, + pas->dtb_mem_phys, + pas->dtb_mem_size); + if (IS_ERR(pas->dtb_pas_ctx)) + return PTR_ERR(pas->dtb_pas_ctx); + return 0; } @@ -901,23 +912,9 @@ static int qcom_pas_probe(struct platform_device *pdev) qcom_add_ssr_subdev(rproc, &pas->ssr_subdev, desc->ssr_name); - pas->pas_ctx = devm_qcom_pas_context_alloc(pas->dev, pas->pas_id, - pas->mem_phys, pas->mem_size); - if (IS_ERR(pas->pas_ctx)) { - ret = PTR_ERR(pas->pas_ctx); - goto remove_ssr_sysmon; - } - - pas->dtb_pas_ctx = devm_qcom_pas_context_alloc(pas->dev, pas->dtb_pas_id, - pas->dtb_mem_phys, - pas->dtb_mem_size); - if (IS_ERR(pas->dtb_pas_ctx)) { - ret = PTR_ERR(pas->dtb_pas_ctx); - goto remove_ssr_sysmon; - } - pas->pas_ctx->use_tzmem = desc->needs_tzmem || rproc->has_iommu; - pas->dtb_pas_ctx->use_tzmem = desc->needs_tzmem || rproc->has_iommu; + if (pas->dtb_pas_id) + pas->dtb_pas_ctx->use_tzmem = desc->needs_tzmem || rproc->has_iommu; if (desc->early_boot) pas->rproc->state = RPROC_DETACHED; From 0b0379fcf9ce395bb51cadb6552ec3b1380436bb Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 24 Jul 2026 23:58:56 +0530 Subject: [PATCH 60/64] remoteproc: qcom: pas: Map/unmap subsystem region before auth_and_reset Qualcomm remoteproc drivers such as qcom_q6v5_mss, which do not use the Peripheral Authentication Service (PAS), always map the MBA region before use and unmap it once the usage is complete. This behavior was introduced to avoid issues seen in the past where speculative accesses from the application processor to the MBA region after it was assigned to the remote Q6 led to an XPU violation. The issue was mitigated by unmapping the region before handing control to the remote Q6. Currently, most Qualcomm SoCs using the PAS driver run either with a standalone QHEE or the Gunyah hypervisor. In these environments, the hypervisor unmaps the Q6 memory from HLOS Stage-2 and remaps it into the Q6 Stage-2 page table. As a result, speculative accesses from HLOS cannot reach the region even if it remains mapped in HLOS Stage-1; therefore, XPU violations cannot occur. However, when the same SoC runs Linux at EL2, Linux itself must perform the unmapping to avoid such issues. It is still correct to apply this mapping/ unmapping sequence even for SoCs that run under Gunyah, so this behavior should not be conditional. Introduce qcom_pas_ctx_map() in qcom_pas.h to centralise the ioremap_wc pattern used by both qcom_q6v5_pas and qcom_mdt_pas_load, and use it in both places. Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Mukesh Ojha Link: https://lore.kernel.org/r/20260724182858.1868271-5-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 35 ++++++++++++++++---------- drivers/soc/qcom/mdt_loader.c | 15 ++++++++--- include/linux/firmware/qcom/qcom_pas.h | 12 +++++++++ include/linux/soc/qcom/mdt_loader.h | 4 +-- 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index b0a3083424fb..a91b80cdae33 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -150,7 +150,13 @@ static void qcom_pas_minidump(struct rproc *rproc) if (rproc->dump_conf == RPROC_COREDUMP_DISABLED) return; + pas->mem_region = qcom_pas_ctx_map(pas->pas_ctx); + if (!pas->mem_region) + return; + qcom_minidump(rproc, pas->minidump_id, qcom_pas_segment_dump); + iounmap(pas->mem_region); + pas->mem_region = NULL; } static int qcom_pas_pds_enable(struct qcom_pas *pas, struct device **pds, @@ -243,8 +249,7 @@ static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw) } ret = qcom_mdt_pas_load(pas->dtb_pas_ctx, pas->dtb_firmware, - pas->dtb_firmware_name, (__force void *)pas->dtb_mem_region, - &pas->dtb_mem_reloc); + pas->dtb_firmware_name, &pas->dtb_mem_reloc); if (ret) { qcom_pas_metadata_release(pas->dtb_pas_ctx); release_firmware(pas->dtb_firmware); @@ -318,7 +323,7 @@ static int qcom_pas_start(struct rproc *rproc) } ret = qcom_mdt_pas_load(pas->pas_ctx, pas->firmware, rproc->firmware, - (__force void *)pas->mem_region, &pas->mem_reloc); + &pas->mem_reloc); if (ret) goto release_pas_metadata; @@ -570,6 +575,19 @@ disable_running: return ret; } +static void qcom_pas_coredump(struct rproc *rproc) +{ + struct qcom_pas *pas = rproc->priv; + + pas->mem_region = qcom_pas_ctx_map(pas->pas_ctx); + if (!pas->mem_region) + return; + + rproc_coredump(rproc); + iounmap(pas->mem_region); + pas->mem_region = NULL; +} + static const struct rproc_ops qcom_pas_ops = { .unprepare = qcom_pas_unprepare, .start = qcom_pas_start, @@ -579,6 +597,7 @@ static const struct rproc_ops qcom_pas_ops = { .load = qcom_pas_load, .panic = qcom_pas_panic, .attach = qcom_pas_attach, + .coredump = qcom_pas_coredump, }; static const struct rproc_ops qcom_pas_minidump_ops = { @@ -696,11 +715,6 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) pas->mem_phys = pas->mem_reloc = res.start; pas->mem_size = resource_size(&res); - pas->mem_region = devm_ioremap_resource_wc(pas->dev, &res); - if (IS_ERR(pas->mem_region)) { - dev_err(pas->dev, "unable to map memory region: %pR\n", &res); - return PTR_ERR(pas->mem_region); - } pas->pas_ctx = devm_qcom_pas_context_alloc(pas->dev, pas->pas_id, pas->mem_phys, pas->mem_size); @@ -718,11 +732,6 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) pas->dtb_mem_phys = pas->dtb_mem_reloc = res.start; pas->dtb_mem_size = resource_size(&res); - pas->dtb_mem_region = devm_ioremap_resource_wc(pas->dev, &res); - if (IS_ERR(pas->dtb_mem_region)) { - dev_err(pas->dev, "unable to map dtb memory region: %pR\n", &res); - return PTR_ERR(pas->dtb_mem_region); - } pas->dtb_pas_ctx = devm_qcom_pas_context_alloc(pas->dev, pas->dtb_pas_id, pas->dtb_mem_phys, diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c index 137992456b71..002100fe2d32 100644 --- a/drivers/soc/qcom/mdt_loader.c +++ b/drivers/soc/qcom/mdt_loader.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -478,22 +479,28 @@ EXPORT_SYMBOL_GPL(qcom_mdt_load); * @ctx: Pointer to the PAS (Peripheral Authentication Service) context * @fw: Firmware object representing the .mdt file * @firmware: Name of the firmware used to construct segment file names - * @mem_region: Memory region allocated for loading the firmware * @reloc_base: Physical address adjusted after relocation * * Return: 0 on success or a negative error code on failure. */ int qcom_mdt_pas_load(struct qcom_pas_context *ctx, const struct firmware *fw, - const char *firmware, void *mem_region, phys_addr_t *reloc_base) + const char *firmware, phys_addr_t *reloc_base) { + void __iomem *mem_region; int ret; ret = __qcom_mdt_pas_init(ctx->dev, fw, firmware, ctx->pas_id, ctx->mem_phys, ctx); if (ret) return ret; - return qcom_mdt_load_no_init(ctx->dev, fw, firmware, mem_region, ctx->mem_phys, - ctx->mem_size, reloc_base); + mem_region = qcom_pas_ctx_map(ctx); + if (!mem_region) + return -ENOMEM; + + ret = qcom_mdt_load_no_init(ctx->dev, fw, firmware, (__force void *)mem_region, + ctx->mem_phys, ctx->mem_size, reloc_base); + iounmap(mem_region); + return ret; } EXPORT_SYMBOL_GPL(qcom_mdt_pas_load); diff --git a/include/linux/firmware/qcom/qcom_pas.h b/include/linux/firmware/qcom/qcom_pas.h index 65b1c9564458..fb2ec3be6a16 100644 --- a/include/linux/firmware/qcom/qcom_pas.h +++ b/include/linux/firmware/qcom/qcom_pas.h @@ -8,7 +8,9 @@ #ifndef __QCOM_PAS_H #define __QCOM_PAS_H +#include #include +#include #include struct qcom_pas_context { @@ -22,6 +24,16 @@ struct qcom_pas_context { bool use_tzmem; }; +static inline void __iomem *qcom_pas_ctx_map(struct qcom_pas_context *ctx) +{ + void __iomem *ptr = ioremap_wc(ctx->mem_phys, ctx->mem_size); + + if (!ptr) + dev_err(ctx->dev, "unable to map memory region: %pa+%zx\n", + &ctx->mem_phys, ctx->mem_size); + return ptr; +} + bool qcom_pas_is_available(void); struct qcom_pas_context *devm_qcom_pas_context_alloc(struct device *dev, u32 pas_id, diff --git a/include/linux/soc/qcom/mdt_loader.h b/include/linux/soc/qcom/mdt_loader.h index 142409555425..74886f772d46 100644 --- a/include/linux/soc/qcom/mdt_loader.h +++ b/include/linux/soc/qcom/mdt_loader.h @@ -21,7 +21,7 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw, phys_addr_t *reloc_base); int qcom_mdt_pas_load(struct qcom_pas_context *ctx, const struct firmware *fw, - const char *firmware, void *mem_region, phys_addr_t *reloc_base); + const char *firmware, phys_addr_t *reloc_base); int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw, const char *fw_name, void *mem_region, @@ -47,7 +47,7 @@ static inline int qcom_mdt_load(struct device *dev, const struct firmware *fw, static inline int qcom_mdt_pas_load(struct qcom_pas_context *ctx, const struct firmware *fw, const char *firmware, - void *mem_region, phys_addr_t *reloc_base) + phys_addr_t *reloc_base) { return -ENODEV; } From d402a23bf4337a5050306847ea19e1bdd8e05736 Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Fri, 24 Jul 2026 23:58:57 +0530 Subject: [PATCH 61/64] remoteproc: qcom: pas: Drop unused dtb_mem_region field dtb_mem_region is no longer referenced after the ioremap was moved to respective places where mapping is required. Remove it from struct qcom_pas. Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Mukesh Ojha Link: https://lore.kernel.org/r/20260724182858.1868271-6-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index a91b80cdae33..428942d8c066 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -101,8 +101,9 @@ struct qcom_pas { phys_addr_t mem_reloc; phys_addr_t dtb_mem_reloc; phys_addr_t region_assign_phys[MAX_ASSIGN_COUNT]; + void __iomem *mem_region; - void __iomem *dtb_mem_region; + size_t mem_size; size_t dtb_mem_size; size_t region_assign_size[MAX_ASSIGN_COUNT]; From 77a6aafb404dda8ed6c2689dd78e10377ccebb4d Mon Sep 17 00:00:00 2001 From: Mukesh Ojha Date: Mon, 13 Jul 2026 15:02:37 +0530 Subject: [PATCH 62/64] dt-bindings: remoteproc: qcom,sm8550-pas: Add Hawi and Maili MPSS compatible Document compatible string for the MPSS Peripheral Authentication Service on the Hawi and Maili SoCs. The Hawi and Maili MPSS is compatible with the SM8650 MPSS (six interrupts, CX and MSS power domains, memory region). Signed-off-by: Mukesh Ojha Reviewed-by: Krzysztof Kozlowski Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20260713093237.691117-1-mukesh.ojha@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml index c58e8a6c7fe1..a062188861ff 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sm8550-pas.yaml @@ -18,6 +18,8 @@ properties: oneOf: - enum: - qcom,eliza-cdsp-pas + - qcom,hawi-mpss-pas + - qcom,maili-mpss-pas - qcom,sdx75-mpss-pas - qcom,sm8550-adsp-pas - qcom,sm8550-cdsp-pas @@ -204,6 +206,8 @@ allOf: properties: compatible: enum: + - qcom,hawi-mpss-pas + - qcom,maili-mpss-pas - qcom,sdx75-mpss-pas - qcom,sm8650-mpss-pas then: @@ -254,6 +258,8 @@ allOf: properties: compatible: enum: + - qcom,hawi-mpss-pas + - qcom,maili-mpss-pas - qcom,sdx75-mpss-pas - qcom,sm8550-mpss-pas - qcom,sm8650-mpss-pas From f0b6c2b40f78db917e72a5d273b031e99ab2c0e7 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 29 Jul 2026 10:35:07 +0800 Subject: [PATCH 63/64] dt-bindings: remoteproc: qcom,nord-pas: Document Nord PAS Add a dedicated binding for the Qualcomm Nord SoC PAS devices: ADSP and CDSPs. Nord ADSP uses CX and MX power domains while the CDSPs add an NSP domain on top of that. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Shawn Guo Link: https://lore.kernel.org/r/20260729023508.879752-3-shengchao.guo@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../bindings/remoteproc/qcom,nord-pas.yaml | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 Documentation/devicetree/bindings/remoteproc/qcom,nord-pas.yaml diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,nord-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,nord-pas.yaml new file mode 100644 index 000000000000..e90d2953ba69 --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/qcom,nord-pas.yaml @@ -0,0 +1,173 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/remoteproc/qcom,nord-pas.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Nord SoC Peripheral Authentication Service + +maintainers: + - Shawn Guo + +description: + Qualcomm Nord SoC Peripheral Authentication Service loads and boots firmware + on the Qualcomm DSP Hexagon cores. + +properties: + compatible: + enum: + - qcom,nord-adsp-pas + - qcom,nord-cdsp0-pas + - qcom,nord-cdsp1-pas + - qcom,nord-cdsp2-pas + - qcom,nord-cdsp3-pas + + power-domains: + minItems: 2 + items: + - description: CX power domain + - description: MX power domain + - description: NSP power domain + + power-domain-names: + minItems: 2 + items: + - const: cx + - const: mx + - const: nsp + + reg: + maxItems: 1 + + clocks: + items: + - description: XO clock + + clock-names: + items: + - const: xo + + qcom,qmp: + $ref: /schemas/types.yaml#/definitions/phandle + description: Reference to the AOSS side-channel message RAM. + + smd-edge: false + + firmware-name: + items: + - description: Firmware name of the Hexagon core + - description: Firmware name of the Hexagon Devicetree + + memory-region: + items: + - description: Memory region for main Firmware authentication + - description: Memory region for Devicetree Firmware authentication + + interrupts: + items: + - description: Watchdog interrupt + - description: Fatal interrupt + - description: Ready interrupt + - description: Handover interrupt + - description: Stop acknowledge interrupt + - description: Shutdown acknowledge interrupt + + interrupt-names: + items: + - const: wdog + - const: fatal + - const: ready + - const: handover + - const: stop-ack + - const: shutdown-ack + + qcom,smem-states: + maxItems: 1 + description: States used by the AP to signal the Hexagon core + + qcom,smem-state-names: + maxItems: 1 + description: The names of the state bits used for SMP2P output + +required: + - compatible + - reg + - memory-region + +allOf: + - $ref: /schemas/remoteproc/qcom,pas-common.yaml# + - if: + properties: + compatible: + enum: + - qcom,nord-adsp-pas + then: + properties: + power-domains: + maxItems: 2 + power-domain-names: + maxItems: 2 + else: + properties: + power-domains: + minItems: 3 + power-domain-names: + minItems: 3 + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #define IPCC_MPROC_ADSP0 + + remoteproc@4c00000 { + compatible = "qcom,nord-adsp-pas"; + reg = <0x04c00000 0x10000>; + + clocks = <&rpmhcc RPMH_CXO_CLK>; + clock-names = "xo"; + + interrupts-extended = <&intc GIC_SPI 159 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>, + <&smp2p_adsp_in 7 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog", + "fatal", + "ready", + "handover", + "stop-ack", + "shutdown-ack"; + + memory-region = <&hpass_dsp0_mem>, <&hpass_dsp0_dtb_mem>; + + firmware-name = "qcom/nord/adsp.mbn", + "qcom/nord/adsp_dtb.mbn"; + + power-domains = <&rpmhpd RPMHPD_CX>, + <&rpmhpd RPMHPD_MX>; + power-domain-names = "cx", + "mx"; + + qcom,qmp = <&aoss_qmp>; + qcom,smem-states = <&smp2p_adsp_out 0>; + qcom,smem-state-names = "stop"; + + glink-edge { + interrupts-extended = <&ipcc IPCC_MPROC_ADSP0 + IPCC_MPROC_SIGNAL_GLINK_QMP + IRQ_TYPE_EDGE_RISING>; + mboxes = <&ipcc IPCC_MPROC_ADSP0 IPCC_MPROC_SIGNAL_GLINK_QMP>; + + label = "adsp"; + qcom,remote-pid = <2>; + + /* ... */ + }; + }; From 29a24fe87bc80d81fc5d3b0d7e7615985c0ac29d Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 29 Jul 2026 10:35:08 +0800 Subject: [PATCH 64/64] remoteproc: qcom: pas: Add Nord ADSP and CDSP support Add support for ADSP (HPASS DSP) and 4 CDSPs found on Nord SoC. The ADSP is pre-booted by XBL before Linux starts, so set early_boot flag for attach path rather than a cold boot sequence. Reviewed-by: Konrad Dybcio Signed-off-by: Shawn Guo Link: https://lore.kernel.org/r/20260729023508.879752-4-shengchao.guo@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 110 +++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 428942d8c066..ca8e61254c44 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -1438,6 +1438,111 @@ static const struct qcom_pas_data milos_cdsp_resource = { .smem_host_id = 5, }; +static const struct qcom_pas_data nord_adsp_resource = { + .crash_reason_smem = 423, + .firmware_name = "adsp.mbn", + .dtb_firmware_name = "adsp_dtb.mbn", + .pas_id = 1, + .dtb_pas_id = 36, + .minidump_id = 5, + .auto_boot = true, + .early_boot = true, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + NULL + }, + .load_state = "adsp", + .ssr_name = "lpass", + .sysmon_name = "adsp", + .ssctl_id = 0x14, + .smem_host_id = 2, +}; + +static const struct qcom_pas_data nord_cdsp0_resource = { + .crash_reason_smem = 601, + .firmware_name = "cdsp.mbn", + .dtb_firmware_name = "cdsp_dtb.mbn", + .pas_id = 18, + .dtb_pas_id = 37, + .minidump_id = 7, + .auto_boot = true, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + "nsp", + NULL + }, + .load_state = "cdsp", + .ssr_name = "cdsp0", + .sysmon_name = "cdsp0", + .ssctl_id = 0x17, + .smem_host_id = 5, +}; + +static const struct qcom_pas_data nord_cdsp1_resource = { + .crash_reason_smem = 633, + .firmware_name = "cdsp1.mbn", + .dtb_firmware_name = "cdsp1_dtb.mbn", + .pas_id = 30, + .dtb_pas_id = 59, + .minidump_id = 20, + .auto_boot = true, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + "nsp", + NULL + }, + .load_state = "cdsp1", + .ssr_name = "cdsp1", + .sysmon_name = "cdsp1", + .ssctl_id = 0x20, + .smem_host_id = 69, +}; + +static const struct qcom_pas_data nord_cdsp2_resource = { + .crash_reason_smem = 665, + .firmware_name = "cdsp2.mbn", + .dtb_firmware_name = "cdsp2_dtb.mbn", + .pas_id = 57, + .dtb_pas_id = 60, + .minidump_id = 29, + .auto_boot = true, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + "nsp", + NULL + }, + .load_state = "cdsp2", + .ssr_name = "cdsp2", + .sysmon_name = "cdsp2", + .ssctl_id = 0x1f, + .smem_host_id = 133, +}; + +static const struct qcom_pas_data nord_cdsp3_resource = { + .crash_reason_smem = 666, + .firmware_name = "cdsp3.mbn", + .dtb_firmware_name = "cdsp3_dtb.mbn", + .pas_id = 58, + .dtb_pas_id = 61, + .minidump_id = 30, + .auto_boot = true, + .proxy_pd_names = (char*[]){ + "cx", + "mx", + "nsp", + NULL + }, + .load_state = "cdsp3", + .ssr_name = "cdsp3", + .sysmon_name = "cdsp3", + .ssctl_id = 0x1a, + .smem_host_id = 197, +}; + static const struct qcom_pas_data sm8450_mpss_resource = { .crash_reason_smem = 421, .firmware_name = "modem.mdt", @@ -1732,6 +1837,11 @@ static const struct of_device_id qcom_pas_of_match[] = { { .compatible = "qcom,msm8996-slpi-pil", .data = &msm8996_slpi_resource_init }, { .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource }, { .compatible = "qcom,msm8998-slpi-pas", .data = &msm8996_slpi_resource_init }, + { .compatible = "qcom,nord-adsp-pas", .data = &nord_adsp_resource }, + { .compatible = "qcom,nord-cdsp0-pas", .data = &nord_cdsp0_resource }, + { .compatible = "qcom,nord-cdsp1-pas", .data = &nord_cdsp1_resource }, + { .compatible = "qcom,nord-cdsp2-pas", .data = &nord_cdsp2_resource }, + { .compatible = "qcom,nord-cdsp3-pas", .data = &nord_cdsp3_resource }, { .compatible = "qcom,qcs404-adsp-pas", .data = &adsp_resource_init }, { .compatible = "qcom,qcs404-cdsp-pas", .data = &cdsp_resource_init }, { .compatible = "qcom,qcs404-wcss-pas", .data = &wcss_resource_init },