From 80405a34e1f8975cdb2d7d8679bca7f768861035 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 26 Sep 2025 20:33:15 +0800 Subject: [PATCH 01/45] remoteproc: imx_rproc: Fix runtime PM cleanup and improve remove path Proper cleanup should be done when rproc_add() fails by invoking both pm_runtime_disable() and pm_runtime_put_noidle() to avoid leaving the device in an inconsistent power state. Fix it by adding pm_runtime_put_noidle() and pm_runtime_disable() in the error path. Also Update the remove() callback to use pm_runtime_put_noidle() instead of pm_runtime_put(), to clearly indicate that only need to restore the usage count. Fixes: a876a3aacc43 ("remoteproc: imx_rproc: detect and attach to pre-booted remote cores") Cc: Ulf Hansson Cc: Hiago De Franco Suggested-by: Ulf Hansson Signed-off-by: Peng Fan Reviewed-by: Ulf Hansson Link: https://lore.kernel.org/r/20250926-imx_rproc_v3-v3-1-4c0ec279cc5f@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_rproc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index bb25221a4a89..8424e6ea5569 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -1136,11 +1136,16 @@ static int imx_rproc_probe(struct platform_device *pdev) ret = rproc_add(rproc); if (ret) { dev_err(dev, "rproc_add failed\n"); - goto err_put_clk; + goto err_put_pm; } return 0; +err_put_pm: + if (dcfg->method == IMX_RPROC_SCU_API) { + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); + } err_put_clk: clk_disable_unprepare(priv->clk); err_put_scu: @@ -1160,7 +1165,7 @@ static void imx_rproc_remove(struct platform_device *pdev) if (priv->dcfg->method == IMX_RPROC_SCU_API) { pm_runtime_disable(priv->dev); - pm_runtime_put(priv->dev); + pm_runtime_put_noidle(priv->dev); } clk_disable_unprepare(priv->clk); rproc_del(rproc); From 6c5c37dc41633f3a42dd9e9d80f6e673cdd91165 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 26 Sep 2025 20:33:16 +0800 Subject: [PATCH 02/45] remoteproc: imx_rproc: Use devm_add_action_or_reset() for workqueue cleanup Replace manual destroy_workqueue() calls in error and remove paths with a devm_add_action_or_reset() helper. Ensure the workqueue is properly cleaned up with the device lifecycle, and simplify error handling in probe by removing now-unnecessary labels and cleanup steps. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20250926-imx_rproc_v3-v3-2-4c0ec279cc5f@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_rproc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 8424e6ea5569..9c44ce56f1ab 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -1046,6 +1046,13 @@ static int imx_rproc_sys_off_handler(struct sys_off_data *data) return NOTIFY_DONE; } +static void imx_rproc_destroy_workqueue(void *data) +{ + struct workqueue_struct *workqueue = data; + + destroy_workqueue(workqueue); +} + static int imx_rproc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1077,11 +1084,15 @@ static int imx_rproc_probe(struct platform_device *pdev) return -ENOMEM; } + ret = devm_add_action_or_reset(dev, imx_rproc_destroy_workqueue, priv->workqueue); + if (ret) + return dev_err_probe(dev, ret, "Failed to add devm destroy workqueue action\n"); + INIT_WORK(&priv->rproc_work, imx_rproc_vq_work); ret = imx_rproc_xtr_mbox_init(rproc, true); if (ret) - goto err_put_wkq; + return ret; ret = imx_rproc_addr_init(priv, pdev); if (ret) { @@ -1152,8 +1163,6 @@ static int imx_rproc_probe(struct platform_device *pdev) imx_rproc_put_scu(rproc); err_put_mbox: imx_rproc_free_mbox(rproc); -err_put_wkq: - destroy_workqueue(priv->workqueue); return ret; } @@ -1171,7 +1180,6 @@ static void imx_rproc_remove(struct platform_device *pdev) rproc_del(rproc); imx_rproc_put_scu(rproc); imx_rproc_free_mbox(rproc); - destroy_workqueue(priv->workqueue); } static const struct imx_rproc_plat_ops imx_rproc_ops_arm_smc = { From b0106defc0ff673d6a29cbc858ea48b5f43ac7e7 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 26 Sep 2025 20:33:17 +0800 Subject: [PATCH 03/45] remoteproc: imx_rproc: Use devm_add_action_or_reset() for mailbox cleanup Convert imx_rproc_free_mbox() to a devm-managed cleanup action using devm_add_action_or_reset(). Ensure the mailbox resources are freed automatically with the device lifecycle, simplify error handling and removing the need for manual cleanup in probe and remove paths. Also improve error reporting by using dev_err_probe() for consistency and clarity. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20250926-imx_rproc_v3-v3-3-4c0ec279cc5f@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_rproc.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 9c44ce56f1ab..3260fd55a713 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -93,7 +93,7 @@ struct imx_rproc_mem { #define ATT_CORE(I) BIT((I)) static int imx_rproc_xtr_mbox_init(struct rproc *rproc, bool tx_block); -static void imx_rproc_free_mbox(struct rproc *rproc); +static void imx_rproc_free_mbox(void *data); struct imx_rproc { struct device *dev; @@ -780,8 +780,9 @@ static int imx_rproc_xtr_mbox_init(struct rproc *rproc, bool tx_block) return 0; } -static void imx_rproc_free_mbox(struct rproc *rproc) +static void imx_rproc_free_mbox(void *data) { + struct rproc *rproc = data; struct imx_rproc *priv = rproc->priv; if (priv->tx_ch) { @@ -1094,15 +1095,18 @@ static int imx_rproc_probe(struct platform_device *pdev) if (ret) return ret; + ret = devm_add_action_or_reset(dev, imx_rproc_free_mbox, rproc); + if (ret) + return dev_err_probe(dev, ret, + "Failed to add devm free mbox action: %d\n", ret); + ret = imx_rproc_addr_init(priv, pdev); - if (ret) { - dev_err(dev, "failed on imx_rproc_addr_init\n"); - goto err_put_mbox; - } + if (ret) + return dev_err_probe(dev, ret, "failed on imx_rproc_addr_init\n"); ret = imx_rproc_detect_mode(priv); if (ret) - goto err_put_mbox; + return dev_err_probe(dev, ret, "failed on detect mode\n"); ret = imx_rproc_clk_enable(priv); if (ret) @@ -1161,8 +1165,6 @@ static int imx_rproc_probe(struct platform_device *pdev) clk_disable_unprepare(priv->clk); err_put_scu: imx_rproc_put_scu(rproc); -err_put_mbox: - imx_rproc_free_mbox(rproc); return ret; } @@ -1179,7 +1181,6 @@ static void imx_rproc_remove(struct platform_device *pdev) clk_disable_unprepare(priv->clk); rproc_del(rproc); imx_rproc_put_scu(rproc); - imx_rproc_free_mbox(rproc); } static const struct imx_rproc_plat_ops imx_rproc_ops_arm_smc = { From 65af722aa86fc58431670b3d95be9e1d9a0b060f Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 26 Sep 2025 20:33:18 +0800 Subject: [PATCH 04/45] remoteproc: imx_rproc: Use devm_clk_get_enabled() and simplify cleanup Replace separate calls to devm_clk_get() and clk_prepare_enable() with devm_clk_get_enabled(), which combines clock acquisition and enabling into a single managed step. Simplify the probe logic and remove the need for manual clock disable in error and remove paths. Also, update error handling to eliminate redundant cleanup steps and use return-based error propagation where appropriate. Improve code clarity and reduce the chance of resource leaks or incorrect ordering in cleanup paths. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20250926-imx_rproc_v3-v3-4-4c0ec279cc5f@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_rproc.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 3260fd55a713..f353a680ba99 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -1006,26 +1006,19 @@ static int imx_rproc_clk_enable(struct imx_rproc *priv) { const struct imx_rproc_dcfg *dcfg = priv->dcfg; struct device *dev = priv->dev; - int ret; /* Remote core is not under control of Linux or it is managed by SCU API */ if (dcfg->method == IMX_RPROC_NONE || dcfg->method == IMX_RPROC_SCU_API) return 0; - priv->clk = devm_clk_get(dev, NULL); - if (IS_ERR(priv->clk)) { - dev_err(dev, "Failed to get clock\n"); - return PTR_ERR(priv->clk); - } - /* * clk for M4 block including memory. Should be * enabled before .start for FW transfer. */ - ret = clk_prepare_enable(priv->clk); - if (ret) { + priv->clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(priv->clk)) { dev_err(dev, "Failed to enable clock\n"); - return ret; + return PTR_ERR(priv->clk); } return 0; @@ -1127,7 +1120,7 @@ static int imx_rproc_probe(struct platform_device *pdev) imx_rproc_sys_off_handler, rproc); if (ret) { dev_err(dev, "register power off handler failure\n"); - goto err_put_clk; + goto err_put_scu; } ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART_PREPARE, @@ -1135,7 +1128,7 @@ static int imx_rproc_probe(struct platform_device *pdev) imx_rproc_sys_off_handler, rproc); if (ret) { dev_err(dev, "register restart handler failure\n"); - goto err_put_clk; + goto err_put_scu; } } @@ -1144,7 +1137,7 @@ static int imx_rproc_probe(struct platform_device *pdev) ret = pm_runtime_resume_and_get(dev); if (ret) { dev_err(dev, "pm_runtime get failed: %d\n", ret); - goto err_put_clk; + goto err_put_scu; } } @@ -1161,8 +1154,6 @@ static int imx_rproc_probe(struct platform_device *pdev) pm_runtime_disable(dev); pm_runtime_put_noidle(dev); } -err_put_clk: - clk_disable_unprepare(priv->clk); err_put_scu: imx_rproc_put_scu(rproc); @@ -1178,7 +1169,6 @@ static void imx_rproc_remove(struct platform_device *pdev) pm_runtime_disable(priv->dev); pm_runtime_put_noidle(priv->dev); } - clk_disable_unprepare(priv->clk); rproc_del(rproc); imx_rproc_put_scu(rproc); } From 9b2451658afa9d144706f4b8d8727bb458fb4514 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 26 Sep 2025 20:33:19 +0800 Subject: [PATCH 05/45] remoteproc: imx_rproc: Use devm_add_action_or_reset() for scu cleanup Replace the explicit call to imx_rproc_put_scu() in the remove path with devm_add_action_or_reset(). Ensure proper cleanup of scu resources and simplify the code by leveraging the device-managed resource framework. Additionally: - Remove the IMX_RPROC_SCU_API check from imx_rproc_put_scu(), as devm_add_action_or_reset() now exclusively handles SCU cleanup. - Improve error reporting by using dev_err_probe() for consistency and clarity. - Drop the err_put_scu label, as it is now redundant due to the updated error handling approach. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20250926-imx_rproc_v3-v3-5-4c0ec279cc5f@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_rproc.c | 35 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index f353a680ba99..76feda868cb6 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -796,13 +796,9 @@ static void imx_rproc_free_mbox(void *data) } } -static void imx_rproc_put_scu(struct rproc *rproc) +static void imx_rproc_put_scu(void *data) { - struct imx_rproc *priv = rproc->priv; - const struct imx_rproc_dcfg *dcfg = priv->dcfg; - - if (dcfg->method != IMX_RPROC_SCU_API) - return; + struct imx_rproc *priv = data; if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) { dev_pm_domain_detach_list(priv->pd_list); @@ -944,6 +940,10 @@ static int imx_rproc_scu_api_detect_mode(struct rproc *rproc) else priv->core_index = 0; + ret = devm_add_action_or_reset(dev, imx_rproc_put_scu, priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to add action for put scu\n"); + /* * If Mcore resource is not owned by Acore partition, It is kicked by ROM, * and Linux could only do IPC with Mcore and nothing else. @@ -1103,7 +1103,7 @@ static int imx_rproc_probe(struct platform_device *pdev) ret = imx_rproc_clk_enable(priv); if (ret) - goto err_put_scu; + return dev_err_probe(dev, ret, "failed to enable clks\n"); if (rproc->state != RPROC_DETACHED) rproc->auto_boot = of_property_read_bool(np, "fsl,auto-boot"); @@ -1118,27 +1118,21 @@ static int imx_rproc_probe(struct platform_device *pdev) ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_DEFAULT, imx_rproc_sys_off_handler, rproc); - if (ret) { - dev_err(dev, "register power off handler failure\n"); - goto err_put_scu; - } + if (ret) + return dev_err_probe(dev, ret, "register power off handler failure\n"); ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART_PREPARE, SYS_OFF_PRIO_DEFAULT, imx_rproc_sys_off_handler, rproc); - if (ret) { - dev_err(dev, "register restart handler failure\n"); - goto err_put_scu; - } + if (ret) + return dev_err_probe(dev, ret, "register restart handler failure\n"); } if (dcfg->method == IMX_RPROC_SCU_API) { pm_runtime_enable(dev); ret = pm_runtime_resume_and_get(dev); - if (ret) { - dev_err(dev, "pm_runtime get failed: %d\n", ret); - goto err_put_scu; - } + if (ret) + return dev_err_probe(dev, ret, "pm_runtime get failed\n"); } ret = rproc_add(rproc); @@ -1154,8 +1148,6 @@ static int imx_rproc_probe(struct platform_device *pdev) pm_runtime_disable(dev); pm_runtime_put_noidle(dev); } -err_put_scu: - imx_rproc_put_scu(rproc); return ret; } @@ -1170,7 +1162,6 @@ static void imx_rproc_remove(struct platform_device *pdev) pm_runtime_put_noidle(priv->dev); } rproc_del(rproc); - imx_rproc_put_scu(rproc); } static const struct imx_rproc_plat_ops imx_rproc_ops_arm_smc = { From ff7c763b91981b9037086eae4ae4f127d5cceb63 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 26 Sep 2025 20:33:20 +0800 Subject: [PATCH 06/45] remoteproc: imx_rproc: Use devm_rproc_add() helper Replace manual rproc_add() and cleanup logic with devm_rproc_add(), which ties the remoteproc lifecycle to the device's lifecycle. This simplifies error handling and ensures proper cleanup. With no need to invoke rproc_del(), the remove() ops could be removed. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20250926-imx_rproc_v3-v3-6-4c0ec279cc5f@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_rproc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 76feda868cb6..68e01b647b66 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -1135,7 +1135,7 @@ static int imx_rproc_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "pm_runtime get failed\n"); } - ret = rproc_add(rproc); + ret = devm_rproc_add(dev, rproc); if (ret) { dev_err(dev, "rproc_add failed\n"); goto err_put_pm; @@ -1161,7 +1161,6 @@ static void imx_rproc_remove(struct platform_device *pdev) pm_runtime_disable(priv->dev); pm_runtime_put_noidle(priv->dev); } - rproc_del(rproc); } static const struct imx_rproc_plat_ops imx_rproc_ops_arm_smc = { From 8fd705c5e72776c2f1a0212bdedcb9a9753b5bce Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 15 Oct 2025 10:41:03 +0200 Subject: [PATCH 07/45] remoteproc: mtk_scp: Construct FW path if firmware-name not present After a reply on the mailing lists [1] it emerged that the DT property "firmware-name" should not be relied on because of possible issues with firmware versions. For MediaTek SCP, there has never been any firmware version vs driver version desync issue but, regardless, the firmwares are always using the same name and they're always located in a path with a specific pattern. Instead of unconditionally always relying on the firmware-name devicetree property to get a path to the SCP FW file, drivers should construct a name based on what firmware it knows and what hardware it is running on. In order to do that, add a `scp_get_default_fw_path()` function that constructs the path and filename based on two of the infos that the driver can get: 1. The compatible string with the highest priority (so, the first one at index 0); and 2. The type of SCP HW - single-core or multi-core. This means that the default firmware path is generated as: - Single core SCP: mediatek/(soc_model)/scp.img for example: mediatek/mt8183/scp.img; - Multi core SCP: mediatek/(soc_model)/scp_c(core_number).img for example: mediatek/mt8188/scp_c0.img for Core 0, and mediatek/mt8188/scp_c1.img for Core 1. Note that the generated firmware path is being used only if the "firmware-name" devicetree property is not present in the SCP node or in the SCP Core node(s). [1 - Reply regarding firmware-name property] Link: https://lore.kernel.org/all/7e8718b0-df78-44a6-a102-89529d6abcce@app.fastmail.com/ Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Arnd Bergmann Link: https://lore.kernel.org/r/20251015084103.10737-1-angelogioacchino.delregno@collabora.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/mtk_scp.c | 65 ++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c index 8206a1766481..10e3f9eb8cd2 100644 --- a/drivers/remoteproc/mtk_scp.c +++ b/drivers/remoteproc/mtk_scp.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "mtk_common.h" #include "remoteproc_internal.h" @@ -1093,22 +1094,74 @@ static void scp_remove_rpmsg_subdev(struct mtk_scp *scp) } } +/** + * scp_get_default_fw_path() - Get default SCP firmware path + * @dev: SCP Device + * @core_id: SCP Core number + * + * This function generates a path based on the following format: + * mediatek/(soc_model)/scp(_cX).img; for multi-core or + * mediatek/(soc_model)/scp.img for single core SCP HW + * + * Return: A devm allocated string containing the full path to + * a SCP firmware or an error pointer + */ +static const char *scp_get_default_fw_path(struct device *dev, int core_id) +{ + struct device_node *np = core_id < 0 ? dev->of_node : dev->parent->of_node; + const char *compatible, *soc; + char scp_fw_file[7]; + int ret; + + /* Use only the first compatible string */ + ret = of_property_read_string_index(np, "compatible", 0, &compatible); + if (ret) + return ERR_PTR(ret); + + /* If the compatible string's length is implausible bail out early */ + if (strlen(compatible) < strlen("mediatek,mtXXXX-scp")) + return ERR_PTR(-EINVAL); + + /* If the compatible string starts with "mediatek,mt" assume that it's ok */ + if (!str_has_prefix(compatible, "mediatek,mt")) + return ERR_PTR(-EINVAL); + + if (core_id >= 0) + ret = snprintf(scp_fw_file, ARRAY_SIZE(scp_fw_file), "scp_c%1d", core_id); + else + ret = snprintf(scp_fw_file, ARRAY_SIZE(scp_fw_file), "scp"); + if (ret <= 0) + return ERR_PTR(ret); + + /* Not using strchr here, as strlen of a const gets optimized by compiler */ + soc = &compatible[strlen("mediatek,")]; + + return devm_kasprintf(dev, GFP_KERNEL, "mediatek/%.*s/%s.img", + (int)strlen("mtXXXX"), soc, scp_fw_file); +} + static struct mtk_scp *scp_rproc_init(struct platform_device *pdev, struct mtk_scp_of_cluster *scp_cluster, - const struct mtk_scp_of_data *of_data) + const struct mtk_scp_of_data *of_data, + int core_id) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct mtk_scp *scp; struct rproc *rproc; struct resource *res; - const char *fw_name = "scp.img"; + const char *fw_name; int ret, i; const struct mtk_scp_sizes_data *scp_sizes; ret = rproc_of_parse_firmware(dev, 0, &fw_name); - if (ret < 0 && ret != -EINVAL) - return ERR_PTR(ret); + if (ret) { + fw_name = scp_get_default_fw_path(dev, core_id); + if (IS_ERR(fw_name)) { + dev_err(dev, "Cannot get firmware path: %ld\n", PTR_ERR(fw_name)); + return ERR_CAST(fw_name); + } + } rproc = devm_rproc_alloc(dev, np->name, &scp_ops, fw_name, sizeof(*scp)); if (!rproc) { @@ -1212,7 +1265,7 @@ static int scp_add_single_core(struct platform_device *pdev, struct mtk_scp *scp; int ret; - scp = scp_rproc_init(pdev, scp_cluster, of_device_get_match_data(dev)); + scp = scp_rproc_init(pdev, scp_cluster, of_device_get_match_data(dev), -1); if (IS_ERR(scp)) return PTR_ERR(scp); @@ -1259,7 +1312,7 @@ static int scp_add_multi_core(struct platform_device *pdev, goto init_fail; } - scp = scp_rproc_init(cpdev, scp_cluster, cluster_of_data[core_id]); + scp = scp_rproc_init(cpdev, scp_cluster, cluster_of_data[core_id], core_id); put_device(&cpdev->dev); if (IS_ERR(scp)) { ret = PTR_ERR(scp); From ddbec021a3e5ddd38c89516c30b53ab747824207 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 24 Oct 2025 10:51:28 +0800 Subject: [PATCH 08/45] remoteproc: imx_rproc: Simplify clock enable logic using dcfg flags Simplify the clock enable logic by removing the dedicated imx_rproc_clk_enable() function and integrate the clock handling directly into the probe function to simplify the code. Add a new IMX_RPROC_NEED_CLKS flag in dcfg to indicate whether clock management is required for a given SoC. Update probe logic to conditionally enable clocks based on the new flag. Set the flag for applicable SoCs (e.g., i.MX7D, i.MX8MQ, i.MX93, etc.). No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251024-imx_rproc_c4-v4-1-af83ed3fdbba@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_rproc.c | 40 +++++++++++++--------------------- drivers/remoteproc/imx_rproc.h | 1 + 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 68e01b647b66..2a71863c09e9 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -1002,28 +1002,6 @@ static int imx_rproc_detect_mode(struct imx_rproc *priv) return dcfg->ops->detect_mode(priv->rproc); } -static int imx_rproc_clk_enable(struct imx_rproc *priv) -{ - const struct imx_rproc_dcfg *dcfg = priv->dcfg; - struct device *dev = priv->dev; - - /* Remote core is not under control of Linux or it is managed by SCU API */ - if (dcfg->method == IMX_RPROC_NONE || dcfg->method == IMX_RPROC_SCU_API) - return 0; - - /* - * clk for M4 block including memory. Should be - * enabled before .start for FW transfer. - */ - priv->clk = devm_clk_get_enabled(dev, NULL); - if (IS_ERR(priv->clk)) { - dev_err(dev, "Failed to enable clock\n"); - return PTR_ERR(priv->clk); - } - - return 0; -} - static int imx_rproc_sys_off_handler(struct sys_off_data *data) { struct rproc *rproc = data->cb_data; @@ -1101,9 +1079,15 @@ static int imx_rproc_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "failed on detect mode\n"); - ret = imx_rproc_clk_enable(priv); - if (ret) - return dev_err_probe(dev, ret, "failed to enable clks\n"); + /* + * Handle clocks when remote core is under control of Linux AND the + * clocks are not managed by system firmware. + */ + if (dcfg->flags & IMX_RPROC_NEED_CLKS) { + priv->clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(priv->clk)) + return dev_err_probe(dev, PTR_ERR(priv->clk), "Failed to enable clock\n"); + } if (rproc->state != RPROC_DETACHED) rproc->auto_boot = of_property_read_bool(np, "fsl,auto-boot"); @@ -1192,6 +1176,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn_mmio = { .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), .method = IMX_RPROC_MMIO, .ops = &imx_rproc_ops_mmio, + .flags = IMX_RPROC_NEED_CLKS, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { @@ -1199,6 +1184,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), .method = IMX_RPROC_SMC, .ops = &imx_rproc_ops_arm_smc, + .flags = IMX_RPROC_NEED_CLKS, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { @@ -1210,6 +1196,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { .att_size = ARRAY_SIZE(imx_rproc_att_imx8mq), .method = IMX_RPROC_MMIO, .ops = &imx_rproc_ops_mmio, + .flags = IMX_RPROC_NEED_CLKS, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx8qm = { @@ -1248,6 +1235,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = { .att_size = ARRAY_SIZE(imx_rproc_att_imx7d), .method = IMX_RPROC_MMIO, .ops = &imx_rproc_ops_mmio, + .flags = IMX_RPROC_NEED_CLKS, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = { @@ -1259,6 +1247,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = { .att_size = ARRAY_SIZE(imx_rproc_att_imx6sx), .method = IMX_RPROC_MMIO, .ops = &imx_rproc_ops_mmio, + .flags = IMX_RPROC_NEED_CLKS, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = { @@ -1266,6 +1255,7 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = { .att_size = ARRAY_SIZE(imx_rproc_att_imx93), .method = IMX_RPROC_SMC, .ops = &imx_rproc_ops_arm_smc, + .flags = IMX_RPROC_NEED_CLKS, }; static const struct of_device_id imx_rproc_of_match[] = { diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h index 3a9adaaf048b..a9cba623560c 100644 --- a/drivers/remoteproc/imx_rproc.h +++ b/drivers/remoteproc/imx_rproc.h @@ -30,6 +30,7 @@ enum imx_rproc_method { /* dcfg flags */ #define IMX_RPROC_NEED_SYSTEM_OFF BIT(0) +#define IMX_RPROC_NEED_CLKS BIT(1) struct imx_rproc_plat_ops { int (*start)(struct rproc *rproc); From 016a3d4bcf92400b4f91b33fe4c8bdecdabc3c2a Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 24 Oct 2025 10:51:29 +0800 Subject: [PATCH 09/45] remoteproc: imx_rproc: Make detach operation platform-specific Refactor the detach logic to support platform-specific implementations via the dcfg->ops->detach callback. Allow finer control over detach behavior depending on the remote processor management method, and make it easier to add detach support for new SoCs. The previous hardcoded SCU API detach logic is now moved into a dedicated imx_rproc_scu_api_detach() function, and registered via the plat ops structure. The generic imx_rproc_detach() now delegates to the platform-specific handler if available. Also, the dcfg->method check with IMX_RPROC_SCU_API is removed. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251024-imx_rproc_c4-v4-2-af83ed3fdbba@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_rproc.c | 18 +++++++++++++----- drivers/remoteproc/imx_rproc.h | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 2a71863c09e9..820b0cd5adbb 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -575,13 +575,9 @@ static int imx_rproc_attach(struct rproc *rproc) return imx_rproc_xtr_mbox_init(rproc, true); } -static int imx_rproc_detach(struct rproc *rproc) +static int imx_rproc_scu_api_detach(struct rproc *rproc) { struct imx_rproc *priv = rproc->priv; - const struct imx_rproc_dcfg *dcfg = priv->dcfg; - - if (dcfg->method != IMX_RPROC_SCU_API) - return -EOPNOTSUPP; if (imx_sc_rm_is_resource_owned(priv->ipc_handle, priv->rsrc_id)) return -EOPNOTSUPP; @@ -591,6 +587,17 @@ static int imx_rproc_detach(struct rproc *rproc) return 0; } +static int imx_rproc_detach(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + + if (!dcfg->ops || !dcfg->ops->detach) + return -EOPNOTSUPP; + + return dcfg->ops->detach(rproc); +} + static struct resource_table *imx_rproc_get_loaded_rsc_table(struct rproc *rproc, size_t *table_sz) { struct imx_rproc *priv = rproc->priv; @@ -1162,6 +1169,7 @@ static const struct imx_rproc_plat_ops imx_rproc_ops_mmio = { static const struct imx_rproc_plat_ops imx_rproc_ops_scu_api = { .start = imx_rproc_scu_api_start, .stop = imx_rproc_scu_api_stop, + .detach = imx_rproc_scu_api_detach, .detect_mode = imx_rproc_scu_api_detect_mode, }; diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h index a9cba623560c..aeed08bdfb56 100644 --- a/drivers/remoteproc/imx_rproc.h +++ b/drivers/remoteproc/imx_rproc.h @@ -35,6 +35,7 @@ enum imx_rproc_method { struct imx_rproc_plat_ops { int (*start)(struct rproc *rproc); int (*stop)(struct rproc *rproc); + int (*detach)(struct rproc *rproc); int (*detect_mode)(struct rproc *rproc); }; From b2d66cd137e73e5ef5918d910cb42a8c882664d3 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 24 Oct 2025 10:51:30 +0800 Subject: [PATCH 10/45] remoteproc: imx_rproc: Enable PM runtime support unconditionally PM runtime support is safe and applicable across all i.MX platforms, not just those using the SCU API. Remove the conditional check and enable PM runtime unconditionally to simplify the code and ensure consistent power management behavior. Reviewed-by: Daniel Baluta Reviewed-by: Frank Li Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251024-imx_rproc_c4-v4-3-af83ed3fdbba@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_rproc.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 820b0cd5adbb..25f5cb4d414e 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -1119,12 +1119,10 @@ static int imx_rproc_probe(struct platform_device *pdev) return dev_err_probe(dev, ret, "register restart handler failure\n"); } - if (dcfg->method == IMX_RPROC_SCU_API) { - pm_runtime_enable(dev); - ret = pm_runtime_resume_and_get(dev); - if (ret) - return dev_err_probe(dev, ret, "pm_runtime get failed\n"); - } + pm_runtime_enable(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) + return dev_err_probe(dev, ret, "pm_runtime get failed\n"); ret = devm_rproc_add(dev, rproc); if (ret) { @@ -1135,10 +1133,8 @@ static int imx_rproc_probe(struct platform_device *pdev) return 0; err_put_pm: - if (dcfg->method == IMX_RPROC_SCU_API) { - pm_runtime_disable(dev); - pm_runtime_put_noidle(dev); - } + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); return ret; } @@ -1148,10 +1144,8 @@ static void imx_rproc_remove(struct platform_device *pdev) struct rproc *rproc = platform_get_drvdata(pdev); struct imx_rproc *priv = rproc->priv; - if (priv->dcfg->method == IMX_RPROC_SCU_API) { - pm_runtime_disable(priv->dev); - pm_runtime_put_noidle(priv->dev); - } + pm_runtime_disable(priv->dev); + pm_runtime_put_noidle(priv->dev); } static const struct imx_rproc_plat_ops imx_rproc_ops_arm_smc = { From 5a4d08351b466a53d5144ba909a0fbb5cc5f2100 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Fri, 24 Oct 2025 10:51:31 +0800 Subject: [PATCH 11/45] remoteproc: imx_rproc: Remove the assignement to method 'method' is no longer used in imx_rproc.c, so remove the assignment. But imx_dsp_rproc.c is still using 'method', so still keep the field in struct imx_rrpoc_dcfg. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251024-imx_rproc_c4-v4-4-af83ed3fdbba@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_rproc.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 25f5cb4d414e..02e155e96794 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -1176,7 +1176,6 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn_mmio = { .gpr_wait = IMX8M_GPR22_CM7_CPUWAIT, .att = imx_rproc_att_imx8mn, .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), - .method = IMX_RPROC_MMIO, .ops = &imx_rproc_ops_mmio, .flags = IMX_RPROC_NEED_CLKS, }; @@ -1184,7 +1183,6 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn_mmio = { static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn = { .att = imx_rproc_att_imx8mn, .att_size = ARRAY_SIZE(imx_rproc_att_imx8mn), - .method = IMX_RPROC_SMC, .ops = &imx_rproc_ops_arm_smc, .flags = IMX_RPROC_NEED_CLKS, }; @@ -1196,7 +1194,6 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { .src_stop = IMX7D_M4_STOP, .att = imx_rproc_att_imx8mq, .att_size = ARRAY_SIZE(imx_rproc_att_imx8mq), - .method = IMX_RPROC_MMIO, .ops = &imx_rproc_ops_mmio, .flags = IMX_RPROC_NEED_CLKS, }; @@ -1204,27 +1201,23 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mq = { static const struct imx_rproc_dcfg imx_rproc_cfg_imx8qm = { .att = imx_rproc_att_imx8qm, .att_size = ARRAY_SIZE(imx_rproc_att_imx8qm), - .method = IMX_RPROC_SCU_API, .ops = &imx_rproc_ops_scu_api, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx8qxp = { .att = imx_rproc_att_imx8qxp, .att_size = ARRAY_SIZE(imx_rproc_att_imx8qxp), - .method = IMX_RPROC_SCU_API, .ops = &imx_rproc_ops_scu_api, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx8ulp = { .att = imx_rproc_att_imx8ulp, .att_size = ARRAY_SIZE(imx_rproc_att_imx8ulp), - .method = IMX_RPROC_NONE, }; static const struct imx_rproc_dcfg imx_rproc_cfg_imx7ulp = { .att = imx_rproc_att_imx7ulp, .att_size = ARRAY_SIZE(imx_rproc_att_imx7ulp), - .method = IMX_RPROC_NONE, .flags = IMX_RPROC_NEED_SYSTEM_OFF, }; @@ -1235,7 +1228,6 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx7d = { .src_stop = IMX7D_M4_STOP, .att = imx_rproc_att_imx7d, .att_size = ARRAY_SIZE(imx_rproc_att_imx7d), - .method = IMX_RPROC_MMIO, .ops = &imx_rproc_ops_mmio, .flags = IMX_RPROC_NEED_CLKS, }; @@ -1247,7 +1239,6 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = { .src_stop = IMX6SX_M4_STOP, .att = imx_rproc_att_imx6sx, .att_size = ARRAY_SIZE(imx_rproc_att_imx6sx), - .method = IMX_RPROC_MMIO, .ops = &imx_rproc_ops_mmio, .flags = IMX_RPROC_NEED_CLKS, }; @@ -1255,7 +1246,6 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx6sx = { static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = { .att = imx_rproc_att_imx93, .att_size = ARRAY_SIZE(imx_rproc_att_imx93), - .method = IMX_RPROC_SMC, .ops = &imx_rproc_ops_arm_smc, .flags = IMX_RPROC_NEED_CLKS, }; From 4531b6bad5af669511c348ad5225d9f697af221b Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 16 Oct 2025 19:47:58 +0800 Subject: [PATCH 12/45] remoteproc: core: Drop redundant initialization of 'ret' in rproc_shutdown() The variable ret is immediately assigned the return value of mutex_lock_interruptible(), making its prior initialization to zero unnecessary. Remove the redundant assignment No functional changes. Signed-off-by: Peng Fan Acked-by: Andrew Davis Link: https://lore.kernel.org/r/20251016-rproc-cleanup-v3-v3-1-774083716e8a@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/remoteproc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 825672100528..29bbaa349e34 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1989,7 +1989,7 @@ EXPORT_SYMBOL(rproc_boot); int rproc_shutdown(struct rproc *rproc) { struct device *dev = &rproc->dev; - int ret = 0; + int ret; ret = mutex_lock_interruptible(&rproc->lock); if (ret) { From f1b26faafdc3bb9afd8d3b67089980ef34c7f7db Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 16 Oct 2025 19:47:59 +0800 Subject: [PATCH 13/45] remoteproc: core: Sort header includes Reordered the header includes in drivers/remoteproc/remoteproc_core.c to follow alphabetical order to simplify future maintenance. No functional changes. Signed-off-by: Peng Fan Acked-by: Andrew Davis Link: https://lore.kernel.org/r/20251016-rproc-cleanup-v3-v3-2-774083716e8a@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/remoteproc_core.c | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 29bbaa349e34..f7d21e99d171 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -16,29 +16,29 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include #include #include -#include -#include #include "remoteproc_internal.h" From 6e863a57dd27f642b77fa196d0f4e2a167e27316 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 16 Oct 2025 19:48:00 +0800 Subject: [PATCH 14/45] remoteproc: core: Removed unused headers There is no user of crc32.h, debugfs.h, of_reserved_mem.h, virtio_ids.h, so remove from the included headers. No functional changes. Signed-off-by: Peng Fan Acked-by: Andrew Davis Link: https://lore.kernel.org/r/20251016-rproc-cleanup-v3-v3-3-774083716e8a@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/remoteproc_core.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index f7d21e99d171..8004a4803483 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -17,8 +17,6 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ #include -#include -#include #include #include #include @@ -30,14 +28,12 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include #include "remoteproc_internal.h" From 12dc929c6cc5fb5f82d6f245ceb3548b4c800121 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 16 Oct 2025 19:48:01 +0800 Subject: [PATCH 15/45] remoteproc: core: Remove unused export of rproc_va_to_pa Commit 086d08725d34 ("remoteproc: create vdev subdevice with specific dma memory pool") added an export for rproc_va_to_pa. However, since its introduction, this symbol has not been used by any loadable modules. It remains only referenced within remoteproc_virtio.c, which is always built together with remoteproc_core.c. As such, exporting rproc_va_to_pa is unnecessary, so remove the export. No functional changes. Signed-off-by: Peng Fan Acked-by: Andrew Davis Link: https://lore.kernel.org/r/20251016-rproc-cleanup-v3-v3-4-774083716e8a@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/remoteproc_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 8004a4803483..aada2780b343 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -155,7 +155,6 @@ phys_addr_t rproc_va_to_pa(void *cpu_addr) WARN_ON(!virt_addr_valid(cpu_addr)); return virt_to_phys(cpu_addr); } -EXPORT_SYMBOL(rproc_va_to_pa); /** * rproc_da_to_va() - lookup the kernel virtual address for a remoteproc address From 5a3d530caab22c235c994b38a860549da04171a4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 27 Oct 2025 10:08:51 +0300 Subject: [PATCH 16/45] remoteproc: mediatek: Change the snprintf() checking The snprintf() calls here work but they have several minor style issues: 1) It uses ARRAY_SIZE() which is the number of elements in an array. Since were talking about char that works, but it's more common to use sizeof() which is the number of bytes. 2) The printf format is "%1d". The "1" ensures we always print at least 1 character but since numbers all have at least 1 digit this can be removed. 3) The kernel implementation of snprintf() cannot return negative error codes. Also these particular calls to snprintf() can't return zero and the code to handle that zero return is sort of questionable. 4) In the current kernel the only "core_id" we print is "0" but if it was more than 9 then the output would be truncated so GCC complains. Add an "a >= sizeof(scp_fw_file)" check for output which is too long. Signed-off-by: Dan Carpenter Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/aP8agyKj73bLZrTQ@stanley.mountain Signed-off-by: Mathieu Poirier --- drivers/remoteproc/mtk_scp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c index 10e3f9eb8cd2..db8fd045468d 100644 --- a/drivers/remoteproc/mtk_scp.c +++ b/drivers/remoteproc/mtk_scp.c @@ -1127,11 +1127,11 @@ static const char *scp_get_default_fw_path(struct device *dev, int core_id) return ERR_PTR(-EINVAL); if (core_id >= 0) - ret = snprintf(scp_fw_file, ARRAY_SIZE(scp_fw_file), "scp_c%1d", core_id); + ret = snprintf(scp_fw_file, sizeof(scp_fw_file), "scp_c%d", core_id); else - ret = snprintf(scp_fw_file, ARRAY_SIZE(scp_fw_file), "scp"); - if (ret <= 0) - return ERR_PTR(ret); + ret = snprintf(scp_fw_file, sizeof(scp_fw_file), "scp"); + if (ret >= sizeof(scp_fw_file)) + return ERR_PTR(-ENAMETOOLONG); /* Not using strchr here, as strlen of a const gets optimized by compiler */ soc = &compatible[strlen("mediatek,")]; From 3003773ad67ace7c2a0394efdca122824c709dd5 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:46 +0800 Subject: [PATCH 17/45] remoteproc: imx_dsp_rproc: Simplify power domain attach and error handling Refactor imx_dsp_attach_pm_domains() to use devm_pm_domain_attach_list() directly, removing manual detach logic and simplifying resource management. Also replace verbose error handling in imx_dsp_rproc_probe() with dev_err_probe() for cleaner and more consistent error reporting. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Reviewed-by: Shengjiu Wang Reviewed-by: Iuliana Prodan Tested-by: Iuliana Prodan Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-1-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 6e78a01755c7..1f7d15227ce4 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -1062,14 +1062,12 @@ static const struct rproc_ops imx_dsp_rproc_ops = { static int imx_dsp_attach_pm_domains(struct imx_dsp_rproc *priv) { struct device *dev = priv->rproc->dev.parent; - int ret; /* A single PM domain is already attached. */ if (dev->pm_domain) return 0; - ret = dev_pm_domain_attach_list(dev, NULL, &priv->pd_list); - return ret < 0 ? ret : 0; + return devm_pm_domain_attach_list(dev, NULL, &priv->pd_list); } /** @@ -1186,45 +1184,33 @@ static int imx_dsp_rproc_probe(struct platform_device *pdev) /* There are multiple power domains required by DSP on some platform */ ret = imx_dsp_attach_pm_domains(priv); - if (ret) { - dev_err(dev, "failed on imx_dsp_attach_pm_domains\n"); - return ret; - } + if (ret < 0) + return dev_err_probe(dev, ret, "failed on imx_dsp_attach_pm_domains\n"); + /* Get clocks */ ret = imx_dsp_rproc_clk_get(priv); - if (ret) { - dev_err(dev, "failed on imx_dsp_rproc_clk_get\n"); - goto err_detach_domains; - } + if (ret) + return dev_err_probe(dev, ret, "failed on imx_dsp_rproc_clk_get\n"); init_completion(&priv->pm_comp); rproc->auto_boot = false; ret = rproc_add(rproc); - if (ret) { - dev_err(dev, "rproc_add failed\n"); - goto err_detach_domains; - } + if (ret) + return dev_err_probe(dev, ret, "rproc_add failed\n"); rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_XTENSA); pm_runtime_enable(dev); return 0; - -err_detach_domains: - dev_pm_domain_detach_list(priv->pd_list); - - return ret; } static void imx_dsp_rproc_remove(struct platform_device *pdev) { struct rproc *rproc = platform_get_drvdata(pdev); - struct imx_dsp_rproc *priv = rproc->priv; pm_runtime_disable(&pdev->dev); rproc_del(rproc); - dev_pm_domain_detach_list(priv->pd_list); } /* pm runtime functions */ From 36951036a725271826773e7feb852496b16dc38d Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:47 +0800 Subject: [PATCH 18/45] remoteproc: imx_dsp_rproc: Use devm_rproc_add() helper Replace manual rproc_add() and cleanup logic with devm_rproc_add(), which ties the remoteproc lifecycle to the device's lifecycle. This simplifies error handling and ensures proper cleanup. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Reviewed-by: Shengjiu Wang Reviewed-by: Iuliana Prodan Tested-by: Iuliana Prodan Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-2-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 1f7d15227ce4..418bd3ac70a4 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -1194,7 +1194,7 @@ static int imx_dsp_rproc_probe(struct platform_device *pdev) init_completion(&priv->pm_comp); rproc->auto_boot = false; - ret = rproc_add(rproc); + ret = devm_rproc_add(dev, rproc); if (ret) return dev_err_probe(dev, ret, "rproc_add failed\n"); @@ -1207,10 +1207,7 @@ static int imx_dsp_rproc_probe(struct platform_device *pdev) static void imx_dsp_rproc_remove(struct platform_device *pdev) { - struct rproc *rproc = platform_get_drvdata(pdev); - pm_runtime_disable(&pdev->dev); - rproc_del(rproc); } /* pm runtime functions */ From 412060242303d3c6aae55b1e0b7d040c30bd207d Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:48 +0800 Subject: [PATCH 19/45] remoteproc: imx_dsp_rproc: Use devm_pm_runtime_enable() helper Current code on the cleanup path just disables runtime PM for a device. Using resource managed version devm_pm_runtime_enable() registers a cleanup callback that sets autosuspend to false and then disables runtime PM for a device. So, basically the same functionality as we don't use autosuspend anyway. As a result, the .remove callback is no longer needed, reducing boilerplate code. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Reviewed-by: Shengjiu Wang Reviewed-by: Iuliana Prodan Tested-by: Iuliana Prodan Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-3-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 418bd3ac70a4..f5d0aec52c56 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -1200,14 +1200,7 @@ static int imx_dsp_rproc_probe(struct platform_device *pdev) rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_XTENSA); - pm_runtime_enable(dev); - - return 0; -} - -static void imx_dsp_rproc_remove(struct platform_device *pdev) -{ - pm_runtime_disable(&pdev->dev); + return devm_pm_runtime_enable(dev); } /* pm runtime functions */ @@ -1358,7 +1351,6 @@ MODULE_DEVICE_TABLE(of, imx_dsp_rproc_of_match); static struct platform_driver imx_dsp_rproc_driver = { .probe = imx_dsp_rproc_probe, - .remove = imx_dsp_rproc_remove, .driver = { .name = "imx-dsp-rproc", .of_match_table = imx_dsp_rproc_of_match, From e819a62d52030a26205ec09cba8797b6dc987a87 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:49 +0800 Subject: [PATCH 20/45] remoteproc: imx_dsp_rproc: Use dev_err_probe() for firmware and mode errors Use dev_err_probe() to simplify the code. No functional change. Reviewed-by: Daniel Baluta Reviewed-by: Shengjiu Wang Reviewed-by: Frank Li Reviewed-by: Iuliana Prodan Tested-by: Iuliana Prodan Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-4-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index f5d0aec52c56..87f4a026c05f 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -1150,11 +1150,8 @@ static int imx_dsp_rproc_probe(struct platform_device *pdev) return -ENODEV; ret = rproc_of_parse_firmware(dev, 0, &fw_name); - if (ret) { - dev_err(dev, "failed to parse firmware-name property, ret = %d\n", - ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to parse firmware-name property\n"); rproc = devm_rproc_alloc(dev, "imx-dsp-rproc", &imx_dsp_rproc_ops, fw_name, sizeof(*priv)); @@ -1177,10 +1174,8 @@ static int imx_dsp_rproc_probe(struct platform_device *pdev) INIT_WORK(&priv->rproc_work, imx_dsp_rproc_vq_work); ret = imx_dsp_rproc_detect_mode(priv); - if (ret) { - dev_err(dev, "failed on imx_dsp_rproc_detect_mode\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed on imx_dsp_rproc_detect_mode\n"); /* There are multiple power domains required by DSP on some platform */ ret = imx_dsp_attach_pm_domains(priv); From 8049dc7b631e33a42d8413fe48b043113afa914c Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:50 +0800 Subject: [PATCH 21/45] remoteproc: imx_dsp_rproc: Drop extra space Drop extra space between return and zero. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Reviewed-by: Shengjiu Wang Reviewed-by: Iuliana Prodan Tested-by: Iuliana Prodan Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-5-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 87f4a026c05f..1726aaa1eafb 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -784,7 +784,7 @@ static int imx_dsp_rproc_prepare(struct rproc *rproc) pm_runtime_get_sync(dev); - return 0; + return 0; } /* Unprepare function for rproc_ops */ @@ -792,7 +792,7 @@ static int imx_dsp_rproc_unprepare(struct rproc *rproc) { pm_runtime_put_sync(rproc->dev.parent); - return 0; + return 0; } /* Kick function for rproc_ops */ From 606e4811694a334fe8a1190a4e1d8e62d4c582df Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:51 +0800 Subject: [PATCH 22/45] remoteproc: imx_dsp_rproc: Use start/stop/detect_mode ops from imx_rproc_dcfg Allow each platform to provide its own implementation of start/stop/ detect_mode operations, and prepare to eliminate the need for multiple switch-case statements. Improve code readability and maintainability by encapsulating platform-specific behavior. No functional changes. Reviewed-by: Daniel Baluta Reviewed-by: Shengjiu Wang Reviewed-by: Frank Li Reviewed-by: Iuliana Prodan Tested-by: Iuliana Prodan Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-6-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 1726aaa1eafb..833b1bd40196 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -404,6 +404,11 @@ static int imx_dsp_rproc_start(struct rproc *rproc) struct device *dev = rproc->dev.parent; int ret; + if (dcfg->ops && dcfg->ops->start) { + ret = dcfg->ops->start(rproc); + goto start_ret; + } + switch (dcfg->method) { case IMX_RPROC_MMIO: ret = regmap_update_bits(priv->regmap, @@ -424,6 +429,7 @@ static int imx_dsp_rproc_start(struct rproc *rproc) return -EOPNOTSUPP; } +start_ret: if (ret) dev_err(dev, "Failed to enable remote core!\n"); else if (priv->flags & WAIT_FW_READY) @@ -449,6 +455,11 @@ static int imx_dsp_rproc_stop(struct rproc *rproc) return 0; } + if (dcfg->ops && dcfg->ops->stop) { + ret = dcfg->ops->stop(rproc); + goto stop_ret; + } + switch (dcfg->method) { case IMX_RPROC_MMIO: ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, @@ -467,6 +478,7 @@ static int imx_dsp_rproc_stop(struct rproc *rproc) return -EOPNOTSUPP; } +stop_ret: if (ret) dev_err(dev, "Failed to stop remote core\n"); else @@ -1085,10 +1097,14 @@ static int imx_dsp_attach_pm_domains(struct imx_dsp_rproc *priv) static int imx_dsp_rproc_detect_mode(struct imx_dsp_rproc *priv) { const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; + const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; struct device *dev = priv->rproc->dev.parent; struct regmap *regmap; int ret = 0; + if (dcfg->ops && dcfg->ops->detect_mode) + return dcfg->ops->detect_mode(priv->rproc); + switch (dsp_dcfg->dcfg->method) { case IMX_RPROC_SCU_API: ret = imx_scu_get_handle(&priv->ipc_handle); From 66395eac5d557d76a599858f6b67f7bf8a84a005 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:52 +0800 Subject: [PATCH 23/45] remoteproc: imx_dsp_rproc: Move imx_dsp_rproc_dcfg closer to imx_dsp_rproc_of_match Move the imx_dsp_rproc_dcfg structure definitions closer to imx_dsp_rproc_of_match to prepare for adding start/stop/detect_mode ops for each i.MX variant. Avoids the need to declare function prototypes such as 'static int imx_dsp_rproc_mbox_init(struct imx_dsp_rproc *priv)' at the beginning of the file, improving code organization and readability. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Reviewed-by: Shengjiu Wang Reviewed-by: Iuliana Prodan Tested-by: Iuliana Prodan Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-7-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 100 ++++++++++++++--------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 833b1bd40196..f28d25cab3f1 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -261,56 +261,6 @@ static int imx8ulp_dsp_reset(struct imx_dsp_rproc *priv) return 0; } -/* Specific configuration for i.MX8MP */ -static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8mp = { - .att = imx_dsp_rproc_att_imx8mp, - .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8mp), - .method = IMX_RPROC_RESET_CONTROLLER, -}; - -static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8mp = { - .dcfg = &dsp_rproc_cfg_imx8mp, - .reset = imx8mp_dsp_reset, -}; - -/* Specific configuration for i.MX8ULP */ -static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8ulp = { - .src_reg = IMX8ULP_SIM_LPAV_REG_SYSCTRL0, - .src_mask = IMX8ULP_SYSCTRL0_DSP_STALL, - .src_start = 0, - .src_stop = IMX8ULP_SYSCTRL0_DSP_STALL, - .att = imx_dsp_rproc_att_imx8ulp, - .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8ulp), - .method = IMX_RPROC_MMIO, -}; - -static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8ulp = { - .dcfg = &dsp_rproc_cfg_imx8ulp, - .reset = imx8ulp_dsp_reset, -}; - -/* Specific configuration for i.MX8QXP */ -static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8qxp = { - .att = imx_dsp_rproc_att_imx8qxp, - .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8qxp), - .method = IMX_RPROC_SCU_API, -}; - -static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8qxp = { - .dcfg = &dsp_rproc_cfg_imx8qxp, -}; - -/* Specific configuration for i.MX8QM */ -static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8qm = { - .att = imx_dsp_rproc_att_imx8qm, - .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8qm), - .method = IMX_RPROC_SCU_API, -}; - -static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8qm = { - .dcfg = &dsp_rproc_cfg_imx8qm, -}; - static int imx_dsp_rproc_ready(struct rproc *rproc) { struct imx_dsp_rproc *priv = rproc->priv; @@ -1351,6 +1301,56 @@ static const struct dev_pm_ops imx_dsp_rproc_pm_ops = { RUNTIME_PM_OPS(imx_dsp_runtime_suspend, imx_dsp_runtime_resume, NULL) }; +/* Specific configuration for i.MX8MP */ +static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8mp = { + .att = imx_dsp_rproc_att_imx8mp, + .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8mp), + .method = IMX_RPROC_RESET_CONTROLLER, +}; + +static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8mp = { + .dcfg = &dsp_rproc_cfg_imx8mp, + .reset = imx8mp_dsp_reset, +}; + +/* Specific configuration for i.MX8ULP */ +static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8ulp = { + .src_reg = IMX8ULP_SIM_LPAV_REG_SYSCTRL0, + .src_mask = IMX8ULP_SYSCTRL0_DSP_STALL, + .src_start = 0, + .src_stop = IMX8ULP_SYSCTRL0_DSP_STALL, + .att = imx_dsp_rproc_att_imx8ulp, + .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8ulp), + .method = IMX_RPROC_MMIO, +}; + +static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8ulp = { + .dcfg = &dsp_rproc_cfg_imx8ulp, + .reset = imx8ulp_dsp_reset, +}; + +/* Specific configuration for i.MX8QXP */ +static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8qxp = { + .att = imx_dsp_rproc_att_imx8qxp, + .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8qxp), + .method = IMX_RPROC_SCU_API, +}; + +static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8qxp = { + .dcfg = &dsp_rproc_cfg_imx8qxp, +}; + +/* Specific configuration for i.MX8QM */ +static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8qm = { + .att = imx_dsp_rproc_att_imx8qm, + .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8qm), + .method = IMX_RPROC_SCU_API, +}; + +static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8qm = { + .dcfg = &dsp_rproc_cfg_imx8qm, +}; + static const struct of_device_id imx_dsp_rproc_of_match[] = { { .compatible = "fsl,imx8qxp-hifi4", .data = &imx_dsp_rproc_cfg_imx8qxp }, { .compatible = "fsl,imx8qm-hifi4", .data = &imx_dsp_rproc_cfg_imx8qm }, From 9f356d1277343861810c1e762742cf383b639a3a Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:53 +0800 Subject: [PATCH 24/45] remoteproc: imx_dsp_rproc: Simplify IMX_RPROC_MMIO switch case Introduce imx_dsp_rproc_mmio_{start, stop, detect_mode}() helper functions for i.MX variants using IMX_RPROC_MMIO to manage remote processors. Allows the removal of the IMX_RPROC_MMIO switch-case blocks from imx_dsp_rproc_[start,stop,detect_mode](), resulting in cleaner and more maintainable code. No functional changes. Reviewed-by: Daniel Baluta Reviewed-by: Shengjiu Wang Reviewed-by: Frank Li Reviewed-by: Iuliana Prodan Tested-by: Iuliana Prodan Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-8-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 61 ++++++++++++++++++++---------- drivers/remoteproc/imx_rproc.h | 2 - 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index f28d25cab3f1..71776816c350 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -338,6 +338,14 @@ static int imx_dsp_rproc_handle_rsc(struct rproc *rproc, u32 rsc_type, return RSC_HANDLED; } +static int imx_dsp_rproc_mmio_start(struct rproc *rproc) +{ + struct imx_dsp_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dsp_dcfg->dcfg; + + return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_start); +} + /* * Start function for rproc_ops * @@ -360,12 +368,6 @@ static int imx_dsp_rproc_start(struct rproc *rproc) } switch (dcfg->method) { - case IMX_RPROC_MMIO: - ret = regmap_update_bits(priv->regmap, - dcfg->src_reg, - dcfg->src_mask, - dcfg->src_start); - break; case IMX_RPROC_SCU_API: ret = imx_sc_pm_cpu_start(priv->ipc_handle, IMX_SC_R_DSP, @@ -388,6 +390,14 @@ static int imx_dsp_rproc_start(struct rproc *rproc) return ret; } +static int imx_dsp_rproc_mmio_stop(struct rproc *rproc) +{ + struct imx_dsp_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dsp_dcfg->dcfg; + + return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_stop); +} + /* * Stop function for rproc_ops * It clears the REMOTE_IS_READY flags @@ -411,10 +421,6 @@ static int imx_dsp_rproc_stop(struct rproc *rproc) } switch (dcfg->method) { - case IMX_RPROC_MMIO: - ret = regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, - dcfg->src_stop); - break; case IMX_RPROC_SCU_API: ret = imx_sc_pm_cpu_start(priv->ipc_handle, IMX_SC_R_DSP, @@ -1032,6 +1038,23 @@ static int imx_dsp_attach_pm_domains(struct imx_dsp_rproc *priv) return devm_pm_domain_attach_list(dev, NULL, &priv->pd_list); } +static int imx_dsp_rproc_mmio_detect_mode(struct rproc *rproc) +{ + struct imx_dsp_rproc *priv = rproc->priv; + struct device *dev = rproc->dev.parent; + struct regmap *regmap; + + regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,dsp-ctrl"); + if (IS_ERR(regmap)) { + dev_err(dev, "failed to find syscon\n"); + return PTR_ERR(regmap); + } + + priv->regmap = regmap; + + return 0; +} + /** * imx_dsp_rproc_detect_mode() - detect DSP control mode * @priv: private data pointer @@ -1049,7 +1072,6 @@ static int imx_dsp_rproc_detect_mode(struct imx_dsp_rproc *priv) const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; struct device *dev = priv->rproc->dev.parent; - struct regmap *regmap; int ret = 0; if (dcfg->ops && dcfg->ops->detect_mode) @@ -1061,15 +1083,6 @@ static int imx_dsp_rproc_detect_mode(struct imx_dsp_rproc *priv) if (ret) return ret; break; - case IMX_RPROC_MMIO: - regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "fsl,dsp-ctrl"); - if (IS_ERR(regmap)) { - dev_err(dev, "failed to find syscon\n"); - return PTR_ERR(regmap); - } - - priv->regmap = regmap; - break; case IMX_RPROC_RESET_CONTROLLER: priv->run_stall = devm_reset_control_get_exclusive(dev, "runstall"); if (IS_ERR(priv->run_stall)) { @@ -1301,6 +1314,12 @@ static const struct dev_pm_ops imx_dsp_rproc_pm_ops = { RUNTIME_PM_OPS(imx_dsp_runtime_suspend, imx_dsp_runtime_resume, NULL) }; +static const struct imx_rproc_plat_ops imx_dsp_rproc_ops_mmio = { + .start = imx_dsp_rproc_mmio_start, + .stop = imx_dsp_rproc_mmio_stop, + .detect_mode = imx_dsp_rproc_mmio_detect_mode, +}; + /* Specific configuration for i.MX8MP */ static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8mp = { .att = imx_dsp_rproc_att_imx8mp, @@ -1321,7 +1340,7 @@ static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8ulp = { .src_stop = IMX8ULP_SYSCTRL0_DSP_STALL, .att = imx_dsp_rproc_att_imx8ulp, .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8ulp), - .method = IMX_RPROC_MMIO, + .ops = &imx_dsp_rproc_ops_mmio, }; static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8ulp = { diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h index aeed08bdfb56..912827c39c0d 100644 --- a/drivers/remoteproc/imx_rproc.h +++ b/drivers/remoteproc/imx_rproc.h @@ -18,8 +18,6 @@ struct imx_rproc_att { /* Remote core start/stop method */ enum imx_rproc_method { IMX_RPROC_NONE, - /* Through syscon regmap */ - IMX_RPROC_MMIO, /* Through ARM SMCCC */ IMX_RPROC_SMC, /* Through System Control Unit API */ From d5eb4d512fb70a6c85bb5a1ec8c6b642f45c518f Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:54 +0800 Subject: [PATCH 25/45] remoteproc: imx_dsp_rproc: Simplify IMX_RPROC_SCU_API switch case Introduce imx_dsp_rproc_scu_api_{start, stop, detect_mode}() helper functions for i.MX variants using IMX_RPROC_SCU_API to manage remote processors. Allows the removal of the IMX_RPROC_SCU_API switch-case blocks from imx_dsp_rproc_[start,stop,detect_mode](), resulting in cleaner and more maintainable code. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Reviewed-by: Shengjiu Wang Reviewed-by: Iuliana Prodan Tested-by: Iuliana Prodan Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-9-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 48 ++++++++++++++++++------------ drivers/remoteproc/imx_rproc.h | 2 -- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 71776816c350..91d041c15ac1 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -346,6 +346,13 @@ static int imx_dsp_rproc_mmio_start(struct rproc *rproc) return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_start); } +static int imx_dsp_rproc_scu_api_start(struct rproc *rproc) +{ + struct imx_dsp_rproc *priv = rproc->priv; + + return imx_sc_pm_cpu_start(priv->ipc_handle, IMX_SC_R_DSP, true, rproc->bootaddr); +} + /* * Start function for rproc_ops * @@ -368,12 +375,6 @@ static int imx_dsp_rproc_start(struct rproc *rproc) } switch (dcfg->method) { - case IMX_RPROC_SCU_API: - ret = imx_sc_pm_cpu_start(priv->ipc_handle, - IMX_SC_R_DSP, - true, - rproc->bootaddr); - break; case IMX_RPROC_RESET_CONTROLLER: ret = reset_control_deassert(priv->run_stall); break; @@ -398,6 +399,13 @@ static int imx_dsp_rproc_mmio_stop(struct rproc *rproc) return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_stop); } +static int imx_dsp_rproc_scu_api_stop(struct rproc *rproc) +{ + struct imx_dsp_rproc *priv = rproc->priv; + + return imx_sc_pm_cpu_start(priv->ipc_handle, IMX_SC_R_DSP, false, rproc->bootaddr); +} + /* * Stop function for rproc_ops * It clears the REMOTE_IS_READY flags @@ -421,12 +429,6 @@ static int imx_dsp_rproc_stop(struct rproc *rproc) } switch (dcfg->method) { - case IMX_RPROC_SCU_API: - ret = imx_sc_pm_cpu_start(priv->ipc_handle, - IMX_SC_R_DSP, - false, - rproc->bootaddr); - break; case IMX_RPROC_RESET_CONTROLLER: ret = reset_control_assert(priv->run_stall); break; @@ -1055,6 +1057,13 @@ static int imx_dsp_rproc_mmio_detect_mode(struct rproc *rproc) return 0; } +static int imx_dsp_rproc_scu_api_detect_mode(struct rproc *rproc) +{ + struct imx_dsp_rproc *priv = rproc->priv; + + return imx_scu_get_handle(&priv->ipc_handle); +} + /** * imx_dsp_rproc_detect_mode() - detect DSP control mode * @priv: private data pointer @@ -1078,11 +1087,6 @@ static int imx_dsp_rproc_detect_mode(struct imx_dsp_rproc *priv) return dcfg->ops->detect_mode(priv->rproc); switch (dsp_dcfg->dcfg->method) { - case IMX_RPROC_SCU_API: - ret = imx_scu_get_handle(&priv->ipc_handle); - if (ret) - return ret; - break; case IMX_RPROC_RESET_CONTROLLER: priv->run_stall = devm_reset_control_get_exclusive(dev, "runstall"); if (IS_ERR(priv->run_stall)) { @@ -1320,6 +1324,12 @@ static const struct imx_rproc_plat_ops imx_dsp_rproc_ops_mmio = { .detect_mode = imx_dsp_rproc_mmio_detect_mode, }; +static const struct imx_rproc_plat_ops imx_dsp_rproc_ops_scu_api = { + .start = imx_dsp_rproc_scu_api_start, + .stop = imx_dsp_rproc_scu_api_stop, + .detect_mode = imx_dsp_rproc_scu_api_detect_mode, +}; + /* Specific configuration for i.MX8MP */ static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8mp = { .att = imx_dsp_rproc_att_imx8mp, @@ -1352,7 +1362,7 @@ static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8ulp = { static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8qxp = { .att = imx_dsp_rproc_att_imx8qxp, .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8qxp), - .method = IMX_RPROC_SCU_API, + .ops = &imx_dsp_rproc_ops_scu_api, }; static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8qxp = { @@ -1363,7 +1373,7 @@ static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8qxp = { static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8qm = { .att = imx_dsp_rproc_att_imx8qm, .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8qm), - .method = IMX_RPROC_SCU_API, + .ops = &imx_dsp_rproc_ops_scu_api, }; static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8qm = { diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h index 912827c39c0d..a6b4625e8be7 100644 --- a/drivers/remoteproc/imx_rproc.h +++ b/drivers/remoteproc/imx_rproc.h @@ -20,8 +20,6 @@ enum imx_rproc_method { IMX_RPROC_NONE, /* Through ARM SMCCC */ IMX_RPROC_SMC, - /* Through System Control Unit API */ - IMX_RPROC_SCU_API, /* Through Reset Controller API */ IMX_RPROC_RESET_CONTROLLER, }; From 3f5c1277a9e947d251983042bf406405a35a52cc Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:55 +0800 Subject: [PATCH 26/45] remoteproc: imx_dsp_rproc: Simplify IMX_RPROC_RESET_CONTROLLER switch case Introduce imx_dsp_rproc_reset_ctr_{start, stop, detect_mode}() helper functions for i.MX variants using IMX_RPROC_RESET_CONTROLLER to manage remote processors. Allows the removal of the IMX_RPROC_RESET_CONTROLLER switch-case blocks from imx_dsp_rproc_[start,stop,detect_mode](), resulting in cleaner and more maintainable code. No functional changes. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Reviewed-by: Shengjiu Wang Reviewed-by: Iuliana Prodan Tested-by: Iuliana Prodan Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-10-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 69 ++++++++++++++++-------------- drivers/remoteproc/imx_rproc.h | 2 - 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 91d041c15ac1..6237e8db2eff 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -346,6 +346,13 @@ static int imx_dsp_rproc_mmio_start(struct rproc *rproc) return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_start); } +static int imx_dsp_rproc_reset_ctrl_start(struct rproc *rproc) +{ + struct imx_dsp_rproc *priv = rproc->priv; + + return reset_control_deassert(priv->run_stall); +} + static int imx_dsp_rproc_scu_api_start(struct rproc *rproc) { struct imx_dsp_rproc *priv = rproc->priv; @@ -374,13 +381,7 @@ static int imx_dsp_rproc_start(struct rproc *rproc) goto start_ret; } - switch (dcfg->method) { - case IMX_RPROC_RESET_CONTROLLER: - ret = reset_control_deassert(priv->run_stall); - break; - default: - return -EOPNOTSUPP; - } + return -EOPNOTSUPP; start_ret: if (ret) @@ -399,6 +400,13 @@ static int imx_dsp_rproc_mmio_stop(struct rproc *rproc) return regmap_update_bits(priv->regmap, dcfg->src_reg, dcfg->src_mask, dcfg->src_stop); } +static int imx_dsp_rproc_reset_ctrl_stop(struct rproc *rproc) +{ + struct imx_dsp_rproc *priv = rproc->priv; + + return reset_control_assert(priv->run_stall); +} + static int imx_dsp_rproc_scu_api_stop(struct rproc *rproc) { struct imx_dsp_rproc *priv = rproc->priv; @@ -428,13 +436,7 @@ static int imx_dsp_rproc_stop(struct rproc *rproc) goto stop_ret; } - switch (dcfg->method) { - case IMX_RPROC_RESET_CONTROLLER: - ret = reset_control_assert(priv->run_stall); - break; - default: - return -EOPNOTSUPP; - } + return -EOPNOTSUPP; stop_ret: if (ret) @@ -1057,6 +1059,20 @@ static int imx_dsp_rproc_mmio_detect_mode(struct rproc *rproc) return 0; } +static int imx_dsp_rproc_reset_ctrl_detect_mode(struct rproc *rproc) +{ + struct imx_dsp_rproc *priv = rproc->priv; + struct device *dev = rproc->dev.parent; + + priv->run_stall = devm_reset_control_get_exclusive(dev, "runstall"); + if (IS_ERR(priv->run_stall)) { + dev_err(dev, "Failed to get DSP runstall reset control\n"); + return PTR_ERR(priv->run_stall); + } + + return 0; +} + static int imx_dsp_rproc_scu_api_detect_mode(struct rproc *rproc) { struct imx_dsp_rproc *priv = rproc->priv; @@ -1080,26 +1096,11 @@ static int imx_dsp_rproc_detect_mode(struct imx_dsp_rproc *priv) { const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; - struct device *dev = priv->rproc->dev.parent; - int ret = 0; if (dcfg->ops && dcfg->ops->detect_mode) return dcfg->ops->detect_mode(priv->rproc); - switch (dsp_dcfg->dcfg->method) { - case IMX_RPROC_RESET_CONTROLLER: - priv->run_stall = devm_reset_control_get_exclusive(dev, "runstall"); - if (IS_ERR(priv->run_stall)) { - dev_err(dev, "Failed to get DSP runstall reset control\n"); - return PTR_ERR(priv->run_stall); - } - break; - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; + return -EOPNOTSUPP; } static const char *imx_dsp_clks_names[DSP_RPROC_CLK_MAX] = { @@ -1324,6 +1325,12 @@ static const struct imx_rproc_plat_ops imx_dsp_rproc_ops_mmio = { .detect_mode = imx_dsp_rproc_mmio_detect_mode, }; +static const struct imx_rproc_plat_ops imx_dsp_rproc_ops_reset_ctrl = { + .start = imx_dsp_rproc_reset_ctrl_start, + .stop = imx_dsp_rproc_reset_ctrl_stop, + .detect_mode = imx_dsp_rproc_reset_ctrl_detect_mode, +}; + static const struct imx_rproc_plat_ops imx_dsp_rproc_ops_scu_api = { .start = imx_dsp_rproc_scu_api_start, .stop = imx_dsp_rproc_scu_api_stop, @@ -1334,7 +1341,7 @@ static const struct imx_rproc_plat_ops imx_dsp_rproc_ops_scu_api = { static const struct imx_rproc_dcfg dsp_rproc_cfg_imx8mp = { .att = imx_dsp_rproc_att_imx8mp, .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8mp), - .method = IMX_RPROC_RESET_CONTROLLER, + .ops = &imx_dsp_rproc_ops_reset_ctrl, }; static const struct imx_dsp_rproc_dcfg imx_dsp_rproc_cfg_imx8mp = { diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h index a6b4625e8be7..6a7359f05178 100644 --- a/drivers/remoteproc/imx_rproc.h +++ b/drivers/remoteproc/imx_rproc.h @@ -20,8 +20,6 @@ enum imx_rproc_method { IMX_RPROC_NONE, /* Through ARM SMCCC */ IMX_RPROC_SMC, - /* Through Reset Controller API */ - IMX_RPROC_RESET_CONTROLLER, }; /* dcfg flags */ From 5c33a631a5780df70e2b392539a98e4a624cd752 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:56 +0800 Subject: [PATCH 27/45] remoteproc: imx_rproc: Remove enum imx_rproc_method There is no user of enum imx_rproc_method after moved to ops based method. Remove it. Reviewed-by: Frank Li Reviewed-by: Daniel Baluta Reviewed-by: Shengjiu Wang Reviewed-by: Iuliana Prodan Tested-by: Iuliana Prodan Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-11-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_rproc.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h index 6a7359f05178..1b2d9f4d6d19 100644 --- a/drivers/remoteproc/imx_rproc.h +++ b/drivers/remoteproc/imx_rproc.h @@ -15,13 +15,6 @@ struct imx_rproc_att { int flags; }; -/* Remote core start/stop method */ -enum imx_rproc_method { - IMX_RPROC_NONE, - /* Through ARM SMCCC */ - IMX_RPROC_SMC, -}; - /* dcfg flags */ #define IMX_RPROC_NEED_SYSTEM_OFF BIT(0) #define IMX_RPROC_NEED_CLKS BIT(1) @@ -42,7 +35,6 @@ struct imx_rproc_dcfg { u32 gpr_wait; const struct imx_rproc_att *att; size_t att_size; - enum imx_rproc_method method; u32 flags; const struct imx_rproc_plat_ops *ops; }; From 6f880e7bd103c38d583326f176db8aae8c8b71c2 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 19 Nov 2025 12:21:57 +0800 Subject: [PATCH 28/45] remoteproc: imx_dsp_rproc: Simplify start/stop error handling Replace goto-based error handling with early return pattern in imx_dsp_rproc_{start,stop}() functions, and simplify if-else logic. No functional changes, only code structure improvements for better maintainability. Signed-off-by: Peng Fan Reviewed-by: Daniel Baluta Reviewed-by: Frank Li Link: https://lore.kernel.org/r/20251119-imx-dsp-2025-11-19-v4-12-adafd342d07b@nxp.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 39 ++++++++++++++---------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 6237e8db2eff..1a1438823e7f 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -376,20 +376,19 @@ static int imx_dsp_rproc_start(struct rproc *rproc) struct device *dev = rproc->dev.parent; int ret; - if (dcfg->ops && dcfg->ops->start) { - ret = dcfg->ops->start(rproc); - goto start_ret; + if (!dcfg->ops || !dcfg->ops->start) + return -EOPNOTSUPP; + + ret = dcfg->ops->start(rproc); + if (ret) { + dev_err(dev, "Failed to enable remote core!\n"); + return ret; } - return -EOPNOTSUPP; - -start_ret: - if (ret) - dev_err(dev, "Failed to enable remote core!\n"); - else if (priv->flags & WAIT_FW_READY) + if (priv->flags & WAIT_FW_READY) return imx_dsp_rproc_ready(rproc); - return ret; + return 0; } static int imx_dsp_rproc_mmio_stop(struct rproc *rproc) @@ -431,20 +430,18 @@ static int imx_dsp_rproc_stop(struct rproc *rproc) return 0; } - if (dcfg->ops && dcfg->ops->stop) { - ret = dcfg->ops->stop(rproc); - goto stop_ret; + if (!dcfg->ops || !dcfg->ops->stop) + return -EOPNOTSUPP; + + ret = dcfg->ops->stop(rproc); + if (ret) { + dev_err(dev, "Failed to stop remote core\n"); + return ret; } - return -EOPNOTSUPP; + priv->flags &= ~REMOTE_IS_READY; -stop_ret: - if (ret) - dev_err(dev, "Failed to stop remote core\n"); - else - priv->flags &= ~REMOTE_IS_READY; - - return ret; + return 0; } /** From 67a7bc7f0358bf619d314b5b6c1f06b35931f12c Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Mon, 24 Nov 2025 12:27:47 -0600 Subject: [PATCH 29/45] remoteproc: Use of_reserved_mem_region_* functions for "memory-region" Use the newly added of_reserved_mem_region_to_resource() and of_reserved_mem_region_count() functions to handle "memory-region" properties. The error handling is a bit different in some cases. Often "memory-region" is optional, so failed lookup is not an error. But then an error in of_reserved_mem_lookup() is treated as an error. However, that distinction is not really important. Either the region is available and usable or it is not. So now, it is just of_reserved_mem_region_to_resource() which is checked for an error. Acked-by: Arnaud Pouliquen Tested-by: Peng Fan # i.MX93-11x11-EVK for imx_rproc.c Reviewed-by: Geert Uytterhoeven # rcar Tested-by: Beleswar Padhi # TI Signed-off-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20251124182751.507624-1-robh@kernel.org Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 47 +++++++---------- drivers/remoteproc/imx_rproc.c | 70 ++++++++++--------------- drivers/remoteproc/rcar_rproc.c | 36 +++++-------- drivers/remoteproc/st_remoteproc.c | 41 +++++++-------- drivers/remoteproc/stm32_rproc.c | 46 +++++++--------- drivers/remoteproc/ti_k3_common.c | 28 ++++------ drivers/remoteproc/xlnx_r5_remoteproc.c | 53 +++++++------------ 7 files changed, 127 insertions(+), 194 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 1a1438823e7f..be83b5f20f15 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -658,11 +658,9 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) struct rproc *rproc = priv->rproc; struct device *dev = rproc->dev.parent; struct device_node *np = dev->of_node; - struct of_phandle_iterator it; struct rproc_mem_entry *mem; - struct reserved_mem *rmem; void __iomem *cpu_addr; - int a; + int a, i = 0; u64 da; /* Remap required addresses */ @@ -693,49 +691,40 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) rproc_add_carveout(rproc, mem); } - of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); - while (of_phandle_iterator_next(&it) == 0) { + while (1) { + int err; + struct resource res; + + err = of_reserved_mem_region_to_resource(np, i++, &res); + if (err) + return 0; + /* * Ignore the first memory region which will be used vdev buffer. * No need to do extra handlings, rproc_add_virtio_dev will handle it. */ - if (!strcmp(it.node->name, "vdev0buffer")) + if (strstarts(res.name, "vdev0buffer")) continue; - rmem = of_reserved_mem_lookup(it.node); - if (!rmem) { - of_node_put(it.node); - dev_err(dev, "unable to acquire memory-region\n"); + if (imx_dsp_rproc_sys_to_da(priv, res.start, resource_size(&res), &da)) return -EINVAL; - } - if (imx_dsp_rproc_sys_to_da(priv, rmem->base, rmem->size, &da)) { - of_node_put(it.node); - return -EINVAL; - } - - cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size); + cpu_addr = devm_ioremap_resource_wc(dev, &res); if (!cpu_addr) { - of_node_put(it.node); - dev_err(dev, "failed to map memory %p\n", &rmem->base); + dev_err(dev, "failed to map memory %pR\n", &res); return -ENOMEM; } /* Register memory region */ - mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)rmem->base, - rmem->size, da, NULL, NULL, it.node->name); - - if (mem) { - rproc_coredump_add_segment(rproc, da, rmem->size); - } else { - of_node_put(it.node); + mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)res.start, + resource_size(&res), da, NULL, NULL, + "%.*s", strchrnul(res.name, '@') - res.name, res.name); + if (!mem) return -ENOMEM; - } + rproc_coredump_add_segment(rproc, da, resource_size(&res)); rproc_add_carveout(rproc, mem); } - - return 0; } /* Prepare function for rproc_ops */ diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 02e155e96794..3be8790c14a2 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -490,50 +490,44 @@ static int imx_rproc_prepare(struct rproc *rproc) { struct imx_rproc *priv = rproc->priv; struct device_node *np = priv->dev->of_node; - struct of_phandle_iterator it; struct rproc_mem_entry *mem; - struct reserved_mem *rmem; + int i = 0; u32 da; /* Register associated reserved memory regions */ - of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); - while (of_phandle_iterator_next(&it) == 0) { + while (1) { + int err; + struct resource res; + + err = of_reserved_mem_region_to_resource(np, i++, &res); + if (err) + return 0; + /* * Ignore the first memory region which will be used vdev buffer. * No need to do extra handlings, rproc_add_virtio_dev will handle it. */ - if (!strcmp(it.node->name, "vdev0buffer")) + if (strstarts(res.name, "vdev0buffer")) continue; - if (!strcmp(it.node->name, "rsc-table")) + if (strstarts(res.name, "rsc-table")) continue; - rmem = of_reserved_mem_lookup(it.node); - if (!rmem) { - of_node_put(it.node); - dev_err(priv->dev, "unable to acquire memory-region\n"); - return -EINVAL; - } - /* No need to translate pa to da, i.MX use same map */ - da = rmem->base; + da = res.start; /* Register memory region */ - mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)rmem->base, rmem->size, da, + 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, - it.node->name); - - if (mem) { - rproc_coredump_add_segment(rproc, da, rmem->size); - } else { - of_node_put(it.node); + "%.*s", strchrnul(res.name, '@') - res.name, + res.name); + if (!mem) return -ENOMEM; - } + rproc_coredump_add_segment(rproc, da, resource_size(&res)); rproc_add_carveout(rproc, mem); } - - return 0; } static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) @@ -671,47 +665,37 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, } /* memory-region is optional property */ - nph = of_count_phandle_with_args(np, "memory-region", NULL); + nph = of_reserved_mem_region_count(np); if (nph <= 0) return 0; /* remap optional addresses */ for (a = 0; a < nph; a++) { - struct device_node *node; struct resource res; - node = of_parse_phandle(np, "memory-region", a); - if (!node) - continue; - /* Not map vdevbuffer, vdevring region */ - if (!strncmp(node->name, "vdev", strlen("vdev"))) { - of_node_put(node); - continue; - } - err = of_address_to_resource(node, 0, &res); + err = of_reserved_mem_region_to_resource(np, a, &res); if (err) { dev_err(dev, "unable to resolve memory region\n"); - of_node_put(node); return err; } - if (b >= IMX_RPROC_MEM_MAX) { - of_node_put(node); + /* Not map vdevbuffer, vdevring region */ + if (strstarts(res.name, "vdev")) + continue; + + if (b >= IMX_RPROC_MEM_MAX) break; - } /* Not use resource version, because we might share region */ - priv->mem[b].cpu_addr = devm_ioremap_wc(&pdev->dev, res.start, resource_size(&res)); + priv->mem[b].cpu_addr = devm_ioremap_resource_wc(&pdev->dev, &res); if (!priv->mem[b].cpu_addr) { dev_err(dev, "failed to remap %pr\n", &res); - of_node_put(node); return -ENOMEM; } priv->mem[b].sys_addr = res.start; priv->mem[b].size = resource_size(&res); - if (!strcmp(node->name, "rsc-table")) + if (!strcmp(res.name, "rsc-table")) priv->rsc_table = priv->mem[b].cpu_addr; - of_node_put(node); b++; } diff --git a/drivers/remoteproc/rcar_rproc.c b/drivers/remoteproc/rcar_rproc.c index 921d853594f4..3c25625f966d 100644 --- a/drivers/remoteproc/rcar_rproc.c +++ b/drivers/remoteproc/rcar_rproc.c @@ -52,46 +52,36 @@ static int rcar_rproc_prepare(struct rproc *rproc) { struct device *dev = rproc->dev.parent; struct device_node *np = dev->of_node; - struct of_phandle_iterator it; struct rproc_mem_entry *mem; - struct reserved_mem *rmem; + int i = 0; u32 da; /* Register associated reserved memory regions */ - of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); - while (of_phandle_iterator_next(&it) == 0) { + while (1) { + struct resource res; + int ret; - rmem = of_reserved_mem_lookup(it.node); - if (!rmem) { - of_node_put(it.node); - dev_err(&rproc->dev, - "unable to acquire memory-region\n"); - return -EINVAL; - } + ret = of_reserved_mem_region_to_resource(np, i++, &res); + if (ret) + return 0; - if (rmem->base > U32_MAX) { - of_node_put(it.node); + if (res.start > U32_MAX) return -EINVAL; - } /* No need to translate pa to da, R-Car use same map */ - da = rmem->base; + da = res.start; mem = rproc_mem_entry_init(dev, NULL, - rmem->base, - rmem->size, da, + res.start, + resource_size(&res), da, rcar_rproc_mem_alloc, rcar_rproc_mem_release, - it.node->name); + res.name); - if (!mem) { - of_node_put(it.node); + if (!mem) return -ENOMEM; - } rproc_add_carveout(rproc, mem); } - - return 0; } static int rcar_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c index e6566a9839dc..747bbe7f6f7c 100644 --- a/drivers/remoteproc/st_remoteproc.c +++ b/drivers/remoteproc/st_remoteproc.c @@ -120,40 +120,39 @@ static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) struct device *dev = rproc->dev.parent; struct device_node *np = dev->of_node; struct rproc_mem_entry *mem; - struct reserved_mem *rmem; - struct of_phandle_iterator it; - int index = 0; + int entries; - of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); - while (of_phandle_iterator_next(&it) == 0) { - rmem = of_reserved_mem_lookup(it.node); - if (!rmem) { - of_node_put(it.node); - dev_err(dev, "unable to acquire memory-region\n"); - return -EINVAL; - } + entries = of_reserved_mem_region_count(np); + + for (int index = 0; index < entries; index++) { + struct resource res; + int ret; + + ret = of_reserved_mem_region_to_resource(np, index, &res); + if (ret) + return ret; /* No need to map vdev buffer */ - if (strcmp(it.node->name, "vdev0buffer")) { + if (!strstarts(res.name, "vdev0buffer")) { /* Register memory region */ mem = rproc_mem_entry_init(dev, NULL, - (dma_addr_t)rmem->base, - rmem->size, rmem->base, + (dma_addr_t)res.start, + resource_size(&res), res.start, st_rproc_mem_alloc, st_rproc_mem_release, - it.node->name); + "%.*s", + strchrnul(res.name, '@') - res.name, + res.name); } else { /* Register reserved memory for vdev buffer allocation */ mem = rproc_of_resm_mem_entry_init(dev, index, - rmem->size, - rmem->base, - it.node->name); + resource_size(&res), + res.start, + "vdev0buffer"); } - if (!mem) { - of_node_put(it.node); + if (!mem) return -ENOMEM; - } rproc_add_carveout(rproc, mem); index++; diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c index 431648607d53..c28679d3b43c 100644 --- a/drivers/remoteproc/stm32_rproc.c +++ b/drivers/remoteproc/stm32_rproc.c @@ -213,60 +213,52 @@ static int stm32_rproc_prepare(struct rproc *rproc) { struct device *dev = rproc->dev.parent; struct device_node *np = dev->of_node; - struct of_phandle_iterator it; struct rproc_mem_entry *mem; - struct reserved_mem *rmem; u64 da; - int index = 0; + int index = 0, mr = 0; /* Register associated reserved memory regions */ - of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); - while (of_phandle_iterator_next(&it) == 0) { - rmem = of_reserved_mem_lookup(it.node); - if (!rmem) { - of_node_put(it.node); - dev_err(dev, "unable to acquire memory-region\n"); - return -EINVAL; - } + while (1) { + struct resource res; + int ret; - if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) { - of_node_put(it.node); - dev_err(dev, "memory region not valid %pa\n", - &rmem->base); + ret = of_reserved_mem_region_to_resource(np, mr++, &res); + if (ret) + return 0; + + if (stm32_rproc_pa_to_da(rproc, res.start, &da) < 0) { + dev_err(dev, "memory region not valid %pR\n", &res); return -EINVAL; } /* No need to map vdev buffer */ - if (strcmp(it.node->name, "vdev0buffer")) { + if (!strstarts(res.name, "vdev0buffer")) { /* Register memory region */ mem = rproc_mem_entry_init(dev, NULL, - (dma_addr_t)rmem->base, - rmem->size, da, + (dma_addr_t)res.start, + resource_size(&res), da, stm32_rproc_mem_alloc, stm32_rproc_mem_release, - it.node->name); - + "%.*s", strchrnul(res.name, '@') - res.name, + res.name); if (mem) rproc_coredump_add_segment(rproc, da, - rmem->size); + resource_size(&res)); } else { /* Register reserved memory for vdev buffer alloc */ mem = rproc_of_resm_mem_entry_init(dev, index, - rmem->size, - rmem->base, - it.node->name); + resource_size(&res), + res.start, + "vdev0buffer"); } if (!mem) { - of_node_put(it.node); return -ENOMEM; } rproc_add_carveout(rproc, mem); index++; } - - return 0; } static int stm32_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) diff --git a/drivers/remoteproc/ti_k3_common.c b/drivers/remoteproc/ti_k3_common.c index 56b71652e449..32aa954dc5be 100644 --- a/drivers/remoteproc/ti_k3_common.c +++ b/drivers/remoteproc/ti_k3_common.c @@ -470,13 +470,10 @@ int k3_reserved_mem_init(struct k3_rproc *kproc) { struct device *dev = kproc->dev; struct device_node *np = dev->of_node; - struct device_node *rmem_np; - struct reserved_mem *rmem; int num_rmems; int ret, i; - num_rmems = of_property_count_elems_of_size(np, "memory-region", - sizeof(phandle)); + num_rmems = of_reserved_mem_region_count(np); if (num_rmems < 0) { dev_err(dev, "device does not reserved memory regions (%d)\n", num_rmems); @@ -505,23 +502,20 @@ int k3_reserved_mem_init(struct k3_rproc *kproc) /* use remaining reserved memory regions for static carveouts */ for (i = 0; i < num_rmems; i++) { - rmem_np = of_parse_phandle(np, "memory-region", i + 1); - if (!rmem_np) - return -EINVAL; + struct resource res; - rmem = of_reserved_mem_lookup(rmem_np); - of_node_put(rmem_np); - if (!rmem) - return -EINVAL; + ret = of_reserved_mem_region_to_resource(np, i + 1, &res); + if (ret) + return ret; - kproc->rmem[i].bus_addr = rmem->base; + kproc->rmem[i].bus_addr = res.start; /* 64-bit address regions currently not supported */ - kproc->rmem[i].dev_addr = (u32)rmem->base; - kproc->rmem[i].size = rmem->size; - kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size); + kproc->rmem[i].dev_addr = (u32)res.start; + kproc->rmem[i].size = resource_size(&res); + kproc->rmem[i].cpu_addr = devm_ioremap_resource_wc(dev, &res); if (!kproc->rmem[i].cpu_addr) { - dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n", - i + 1, &rmem->base, &rmem->size); + dev_err(dev, "failed to map reserved memory#%d at %pR\n", + i + 1, &res); return -ENOMEM; } diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c index 0b7b173d0d26..a7b75235f53e 100644 --- a/drivers/remoteproc/xlnx_r5_remoteproc.c +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c @@ -492,53 +492,46 @@ static int add_mem_regions_carveout(struct rproc *rproc) { struct rproc_mem_entry *rproc_mem; struct zynqmp_r5_core *r5_core; - struct of_phandle_iterator it; - struct reserved_mem *rmem; int i = 0; r5_core = rproc->priv; /* Register associated reserved memory regions */ - of_phandle_iterator_init(&it, r5_core->np, "memory-region", NULL, 0); + while (1) { + int err; + struct resource res; - while (of_phandle_iterator_next(&it) == 0) { - rmem = of_reserved_mem_lookup(it.node); - if (!rmem) { - of_node_put(it.node); - dev_err(&rproc->dev, "unable to acquire memory-region\n"); - return -EINVAL; - } + err = of_reserved_mem_region_to_resource(r5_core->np, i, &res); + if (err) + return 0; - if (!strcmp(it.node->name, "vdev0buffer")) { + if (strstarts(res.name, "vdev0buffer")) { /* Init reserved memory for vdev buffer */ rproc_mem = rproc_of_resm_mem_entry_init(&rproc->dev, i, - rmem->size, - rmem->base, - it.node->name); + resource_size(&res), + res.start, + "vdev0buffer"); } else { /* Register associated reserved memory regions */ rproc_mem = rproc_mem_entry_init(&rproc->dev, NULL, - (dma_addr_t)rmem->base, - rmem->size, rmem->base, + (dma_addr_t)res.start, + resource_size(&res), res.start, zynqmp_r5_mem_region_map, zynqmp_r5_mem_region_unmap, - it.node->name); + "%.*s", + strchrnul(res.name, '@') - res.name, + res.name); } - if (!rproc_mem) { - of_node_put(it.node); + if (!rproc_mem) return -ENOMEM; - } rproc_add_carveout(rproc, rproc_mem); - rproc_coredump_add_segment(rproc, rmem->base, rmem->size); + rproc_coredump_add_segment(rproc, res.start, resource_size(&res)); - dev_dbg(&rproc->dev, "reserved mem carveout %s addr=%llx, size=0x%llx", - it.node->name, rmem->base, rmem->size); + dev_dbg(&rproc->dev, "reserved mem carveout %pR\n", &res); i++; } - - return 0; } static int add_sram_carveouts(struct rproc *rproc) @@ -808,7 +801,6 @@ static int zynqmp_r5_get_rsc_table_va(struct zynqmp_r5_core *r5_core) struct device *dev = r5_core->dev; struct rsc_tbl_data *rsc_data_va; struct resource res_mem; - struct device_node *np; int ret; /* @@ -818,14 +810,7 @@ static int zynqmp_r5_get_rsc_table_va(struct zynqmp_r5_core *r5_core) * contains that data structure which holds resource table address, size * and some magic number to validate correct resource table entry. */ - np = of_parse_phandle(r5_core->np, "memory-region", 0); - if (!np) { - dev_err(dev, "failed to get memory region dev node\n"); - return -EINVAL; - } - - ret = of_address_to_resource(np, 0, &res_mem); - of_node_put(np); + ret = of_reserved_mem_region_to_resource(r5_core->np, 0, &res_mem); if (ret) { dev_err(dev, "failed to get memory-region resource addr\n"); return -EINVAL; From 3d447dcdae53b13b5d7df32c4d1d35971d460008 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sat, 21 Jun 2025 15:19:56 +0200 Subject: [PATCH 30/45] dt-bindings: remoteproc: qcom,adsp: Make msm8974 use CX as power domain Using CX as a regulator is an artifact of earlier times. Instead use CX power rail as power domain from rpmpd. Signed-off-by: Luca Weiss Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250621-msm8974-rpmpd-switch-v1-1-0a2cb303c446@lucaweiss.eu Signed-off-by: Bjorn Andersson --- .../bindings/remoteproc/qcom,adsp.yaml | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index 661c2b425da3..03e28d77da50 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -31,9 +31,6 @@ properties: reg: maxItems: 1 - cx-supply: - description: Phandle to the CX regulator - px-supply: description: Phandle to the PX regulator @@ -103,16 +100,6 @@ allOf: interrupt-names: maxItems: 5 - - if: - properties: - compatible: - contains: - enum: - - qcom,msm8974-adsp-pil - then: - required: - - cx-supply - - if: properties: compatible: @@ -120,6 +107,7 @@ allOf: enum: - qcom,msm8226-adsp-pil - qcom,msm8953-adsp-pil + - qcom,msm8974-adsp-pil - qcom,msm8996-adsp-pil - qcom,msm8998-adsp-pas then: @@ -187,6 +175,7 @@ examples: #include #include #include + #include adsp { compatible = "qcom,msm8974-adsp-pil"; @@ -204,7 +193,8 @@ examples: clocks = <&rpmcc RPM_CXO_CLK>; clock-names = "xo"; - cx-supply = <&pm8841_s2>; + power-domains = <&rpmpd MSM8974_VDDCX>; + power-domain-names = "cx"; memory-region = <&adsp_region>; From a1f2c2d55a81c38d63c251ebb7e73e00be37c229 Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sat, 21 Jun 2025 15:19:57 +0200 Subject: [PATCH 31/45] remoteproc: qcom_q6v5_pas: Use resource with CX PD for MSM8974 MSM8974 requires the CX power domain, so use the msm8996_adsp_resource which has cx under proxy_pd_names and is otherwise equivalent. Signed-off-by: Luca Weiss Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20250621-msm8974-rpmpd-switch-v1-2-0a2cb303c446@lucaweiss.eu Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 158bcd6cc85c..712bf3503e2b 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -1461,7 +1461,7 @@ static const struct of_device_id qcom_pas_of_match[] = { { .compatible = "qcom,milos-wpss-pas", .data = &sc7280_wpss_resource}, { .compatible = "qcom,msm8226-adsp-pil", .data = &msm8996_adsp_resource}, { .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource}, - { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init}, + { .compatible = "qcom,msm8974-adsp-pil", .data = &msm8996_adsp_resource}, { .compatible = "qcom,msm8996-adsp-pil", .data = &msm8996_adsp_resource}, { .compatible = "qcom,msm8996-slpi-pil", .data = &msm8996_slpi_resource_init}, { .compatible = "qcom,msm8998-adsp-pas", .data = &msm8996_adsp_resource}, From c70b9d5fdcd707ddac29284ea425fd433f374696 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Mon, 24 Nov 2025 12:27:48 -0600 Subject: [PATCH 32/45] remoteproc: qcom: Use of_reserved_mem_region_* functions for "memory-region" Use the newly added of_reserved_mem_region_to_resource() and of_reserved_mem_region_count() functions to handle "memory-region" properties. The error handling is a bit different in some cases. Often "memory-region" is optional, so failed lookup is not an error. But then an error in of_reserved_mem_lookup() is treated as an error. However, that distinction is not really important. Either the region is available and usable or it is not. So now, it is just of_reserved_mem_region_to_resource() which is checked for an error. Signed-off-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20251124182751.507624-2-robh@kernel.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_adsp.c | 24 ++++------- drivers/remoteproc/qcom_q6v5_mss.c | 60 ++++++++------------------ drivers/remoteproc/qcom_q6v5_pas.c | 67 +++++++++++------------------ drivers/remoteproc/qcom_q6v5_wcss.c | 25 +++++------ drivers/remoteproc/qcom_wcnss.c | 23 ++++------ 5 files changed, 71 insertions(+), 128 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c index e98b7e03162c..d3933a66ed3d 100644 --- a/drivers/remoteproc/qcom_q6v5_adsp.c +++ b/drivers/remoteproc/qcom_q6v5_adsp.c @@ -625,26 +625,20 @@ static int adsp_init_mmio(struct qcom_adsp *adsp, static int adsp_alloc_memory_region(struct qcom_adsp *adsp) { - struct reserved_mem *rmem = NULL; - struct device_node *node; + int ret; + struct resource res; - node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0); - if (node) - rmem = of_reserved_mem_lookup(node); - of_node_put(node); - - if (!rmem) { + ret = of_reserved_mem_region_to_resource(adsp->dev->of_node, 0, &res); + if (ret) { dev_err(adsp->dev, "unable to resolve memory-region\n"); - return -EINVAL; + return ret; } - adsp->mem_phys = adsp->mem_reloc = rmem->base; - adsp->mem_size = rmem->size; - adsp->mem_region = devm_ioremap_wc(adsp->dev, - adsp->mem_phys, adsp->mem_size); + adsp->mem_phys = adsp->mem_reloc = res.start; + adsp->mem_size = resource_size(&res); + adsp->mem_region = devm_ioremap_resource_wc(adsp->dev, &res); if (!adsp->mem_region) { - dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n", - &rmem->base, adsp->mem_size); + dev_err(adsp->dev, "unable to map memory region: %pR\n", &res); return -EBUSY; } diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c index 3087d895b87f..91940977ca89 100644 --- a/drivers/remoteproc/qcom_q6v5_mss.c +++ b/drivers/remoteproc/qcom_q6v5_mss.c @@ -1970,8 +1970,8 @@ static int q6v5_init_reset(struct q6v5 *qproc) static int q6v5_alloc_memory_region(struct q6v5 *qproc) { struct device_node *child; - struct reserved_mem *rmem; - struct device_node *node; + struct resource res; + int ret; /* * In the absence of mba/mpss sub-child, extract the mba and mpss @@ -1979,71 +1979,49 @@ static int q6v5_alloc_memory_region(struct q6v5 *qproc) */ child = of_get_child_by_name(qproc->dev->of_node, "mba"); if (!child) { - node = of_parse_phandle(qproc->dev->of_node, - "memory-region", 0); + ret = of_reserved_mem_region_to_resource(qproc->dev->of_node, 0, &res); } else { - node = of_parse_phandle(child, "memory-region", 0); + ret = of_reserved_mem_region_to_resource(child, 0, &res); of_node_put(child); } - if (!node) { - dev_err(qproc->dev, "no mba memory-region specified\n"); - return -EINVAL; - } - - rmem = of_reserved_mem_lookup(node); - of_node_put(node); - if (!rmem) { + if (ret) { dev_err(qproc->dev, "unable to resolve mba region\n"); - return -EINVAL; + return ret; } - qproc->mba_phys = rmem->base; - qproc->mba_size = rmem->size; + qproc->mba_phys = res.start; + qproc->mba_size = resource_size(&res); if (!child) { - node = of_parse_phandle(qproc->dev->of_node, - "memory-region", 1); + ret = of_reserved_mem_region_to_resource(qproc->dev->of_node, 1, &res); } else { child = of_get_child_by_name(qproc->dev->of_node, "mpss"); - node = of_parse_phandle(child, "memory-region", 0); + ret = of_reserved_mem_region_to_resource(child, 0, &res); of_node_put(child); } - if (!node) { - dev_err(qproc->dev, "no mpss memory-region specified\n"); - return -EINVAL; - } - - rmem = of_reserved_mem_lookup(node); - of_node_put(node); - if (!rmem) { + if (ret) { dev_err(qproc->dev, "unable to resolve mpss region\n"); - return -EINVAL; + return ret; } - qproc->mpss_phys = qproc->mpss_reloc = rmem->base; - qproc->mpss_size = rmem->size; + qproc->mpss_phys = qproc->mpss_reloc = res.start; + qproc->mpss_size = resource_size(&res); if (!child) { - node = of_parse_phandle(qproc->dev->of_node, "memory-region", 2); + ret = of_reserved_mem_region_to_resource(qproc->dev->of_node, 2, &res); } else { child = of_get_child_by_name(qproc->dev->of_node, "metadata"); - node = of_parse_phandle(child, "memory-region", 0); + ret = of_reserved_mem_region_to_resource(child, 0, &res); of_node_put(child); } - if (!node) + if (ret) return 0; - rmem = of_reserved_mem_lookup(node); - if (!rmem) { - dev_err(qproc->dev, "unable to resolve metadata region\n"); - return -EINVAL; - } - - qproc->mdata_phys = rmem->base; - qproc->mdata_size = rmem->size; + qproc->mdata_phys = res.start; + qproc->mdata_size = resource_size(&res); return 0; } diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 712bf3503e2b..f7c2b04c115a 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -547,53 +547,37 @@ static void qcom_pas_pds_detach(struct qcom_pas *pas, struct device **pds, size_ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) { - struct reserved_mem *rmem; - struct device_node *node; + struct resource res; + int ret; - node = of_parse_phandle(pas->dev->of_node, "memory-region", 0); - if (!node) { - dev_err(pas->dev, "no memory-region specified\n"); - return -EINVAL; - } - - rmem = of_reserved_mem_lookup(node); - of_node_put(node); - if (!rmem) { + ret = of_reserved_mem_region_to_resource(pas->dev->of_node, 0, &res); + if (ret) { dev_err(pas->dev, "unable to resolve memory-region\n"); - return -EINVAL; + return ret; } - pas->mem_phys = pas->mem_reloc = rmem->base; - pas->mem_size = rmem->size; - pas->mem_region = devm_ioremap_wc(pas->dev, pas->mem_phys, pas->mem_size); + 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 (!pas->mem_region) { - dev_err(pas->dev, "unable to map memory region: %pa+%zx\n", - &rmem->base, pas->mem_size); + dev_err(pas->dev, "unable to map memory region: %pR\n", &res); return -EBUSY; } if (!pas->dtb_pas_id) return 0; - node = of_parse_phandle(pas->dev->of_node, "memory-region", 1); - if (!node) { - dev_err(pas->dev, "no dtb memory-region specified\n"); - return -EINVAL; - } - - rmem = of_reserved_mem_lookup(node); - of_node_put(node); - if (!rmem) { + ret = of_reserved_mem_region_to_resource(pas->dev->of_node, 1, &res); + if (ret) { dev_err(pas->dev, "unable to resolve dtb memory-region\n"); - return -EINVAL; + return ret; } - pas->dtb_mem_phys = pas->dtb_mem_reloc = rmem->base; - pas->dtb_mem_size = rmem->size; - pas->dtb_mem_region = devm_ioremap_wc(pas->dev, pas->dtb_mem_phys, pas->dtb_mem_size); + 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 (!pas->dtb_mem_region) { - dev_err(pas->dev, "unable to map dtb memory region: %pa+%zx\n", - &rmem->base, pas->dtb_mem_size); + dev_err(pas->dev, "unable to map dtb memory region: %pR\n", &res); return -EBUSY; } @@ -603,7 +587,6 @@ static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) static int qcom_pas_assign_memory_region(struct qcom_pas *pas) { struct qcom_scm_vmperm perm[MAX_ASSIGN_COUNT]; - struct device_node *node; unsigned int perm_size; int offset; int ret; @@ -612,17 +595,15 @@ static int qcom_pas_assign_memory_region(struct qcom_pas *pas) return 0; for (offset = 0; offset < pas->region_assign_count; ++offset) { - struct reserved_mem *rmem = NULL; + struct resource res; - node = of_parse_phandle(pas->dev->of_node, "memory-region", - pas->region_assign_idx + offset); - if (node) - rmem = of_reserved_mem_lookup(node); - of_node_put(node); - if (!rmem) { + ret = of_reserved_mem_region_to_resource(pas->dev->of_node, + pas->region_assign_idx + offset, + &res); + if (ret) { dev_err(pas->dev, "unable to resolve shareable memory-region index %d\n", offset); - return -EINVAL; + return ret; } if (pas->region_assign_shared) { @@ -637,8 +618,8 @@ static int qcom_pas_assign_memory_region(struct qcom_pas *pas) perm_size = 1; } - pas->region_assign_phys[offset] = rmem->base; - pas->region_assign_size[offset] = rmem->size; + pas->region_assign_phys[offset] = res.start; + pas->region_assign_size[offset] = resource_size(&res); pas->region_assign_owners[offset] = BIT(QCOM_SCM_VMID_HLOS); ret = qcom_scm_assign_mem(pas->region_assign_phys[offset], diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c index 07c88623f597..ca748e3bcc7f 100644 --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -873,27 +873,22 @@ static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss, static int q6v5_alloc_memory_region(struct q6v5_wcss *wcss) { - struct reserved_mem *rmem = NULL; - struct device_node *node; struct device *dev = wcss->dev; + struct resource res; + int ret; - node = of_parse_phandle(dev->of_node, "memory-region", 0); - if (node) - rmem = of_reserved_mem_lookup(node); - of_node_put(node); - - if (!rmem) { + ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res); + if (ret) { dev_err(dev, "unable to acquire memory-region\n"); - return -EINVAL; + return ret; } - wcss->mem_phys = rmem->base; - wcss->mem_reloc = rmem->base; - wcss->mem_size = rmem->size; - wcss->mem_region = devm_ioremap_wc(dev, wcss->mem_phys, wcss->mem_size); + wcss->mem_phys = res.start; + wcss->mem_reloc = res.start; + wcss->mem_size = resource_size(&res); + wcss->mem_region = devm_ioremap_resource_wc(dev, &res); if (!wcss->mem_region) { - dev_err(dev, "unable to map memory region: %pa+%pa\n", - &rmem->base, &rmem->size); + dev_err(dev, "unable to map memory region: %pR\n", &res); return -EBUSY; } diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 2c7e519a2254..14005fb049a2 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -526,25 +526,20 @@ static int wcnss_request_irq(struct qcom_wcnss *wcnss, static int wcnss_alloc_memory_region(struct qcom_wcnss *wcnss) { - struct reserved_mem *rmem = NULL; - struct device_node *node; + struct resource res; + int ret; - node = of_parse_phandle(wcnss->dev->of_node, "memory-region", 0); - if (node) - rmem = of_reserved_mem_lookup(node); - of_node_put(node); - - if (!rmem) { + ret = of_reserved_mem_region_to_resource(wcnss->dev->of_node, 0, &res); + if (ret) { dev_err(wcnss->dev, "unable to resolve memory-region\n"); - return -EINVAL; + return ret; } - wcnss->mem_phys = wcnss->mem_reloc = rmem->base; - wcnss->mem_size = rmem->size; - wcnss->mem_region = devm_ioremap_wc(wcnss->dev, wcnss->mem_phys, wcnss->mem_size); + wcnss->mem_phys = wcnss->mem_reloc = res.start; + wcnss->mem_size = resource_size(&res); + wcnss->mem_region = devm_ioremap_resource_wc(wcnss->dev, &res); if (!wcnss->mem_region) { - dev_err(wcnss->dev, "unable to map memory region: %pa+%zx\n", - &rmem->base, wcnss->mem_size); + dev_err(wcnss->dev, "unable to map memory region: %pR\n", &res); return -EBUSY; } From 7f07a5c3e2f5f50f354dab622c1b9cc46ee89f67 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 4 Jul 2025 10:54:45 +0300 Subject: [PATCH 33/45] remoteproc: omap: Remove redundant pm_runtime_mark_last_busy() calls pm_runtime_put_autosuspend(), pm_runtime_put_sync_autosuspend(), pm_runtime_autosuspend() and pm_request_autosuspend() now include a call to pm_runtime_mark_last_busy(). Remove the now-reduntant explicit call to pm_runtime_mark_last_busy(). Signed-off-by: Sakari Ailus Link: https://lore.kernel.org/r/20250704075445.3221481-1-sakari.ailus@linux.intel.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/omap_remoteproc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 9c9e9c3cf378..cb01354248af 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -555,7 +555,6 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid) dev_err(dev, "failed to send mailbox message, status = %d\n", ret); - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); } @@ -656,7 +655,6 @@ static int omap_rproc_start(struct rproc *rproc) pm_runtime_use_autosuspend(dev); pm_runtime_get_noresume(dev); pm_runtime_enable(dev); - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); return 0; @@ -714,7 +712,6 @@ static int omap_rproc_stop(struct rproc *rproc) reset_control_deassert(oproc->reset); out: /* schedule the next auto-suspend */ - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); return ret; } From ca079ec3ebed19a12c1bf080496dacbc6fdfbb39 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Tue, 4 Nov 2025 20:31:07 +0100 Subject: [PATCH 34/45] dt-bindings: remoteproc: qcom,sc8280xp-pas: Fix CDSP power desc The power requirements for the CDSP instances on SC8280XP aren't fully described, with only one of the three present. Fix that. Fixes: ee651cd1e944 ("dt-bindings: remoteproc: qcom: pas: Add sc8280xp adsp and nsp pair") Signed-off-by: Konrad Dybcio Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20251104-topic-8280_mxc-v1-2-df545af0ef94@oss.qualcomm.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml index 96d53baf6e00..5dbda3a55047 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,sc8280xp-pas.yaml @@ -91,9 +91,13 @@ allOf: power-domains: items: - description: NSP power domain + - description: CX power domain + - description: MXC power domain power-domain-names: items: - const: nsp + - const: cx + - const: mxc unevaluatedProperties: false From db03780e43781d48effef75c9b1960987f6751d4 Mon Sep 17 00:00:00 2001 From: Nickolay Goppen Date: Mon, 10 Nov 2025 21:29:43 +0300 Subject: [PATCH 35/45] dt-bindings: remoteproc: qcom: adsp: Add missing constrains for SDM660 ADSP Since SDM660 ADSP node uses "xo" clock, interrupts and "cx" power domain properties add corresponding constrains for SDM660 ADSP. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Nickolay Goppen Link: https://lore.kernel.org/r/20251110-qcom-sdm660-cdsp-v3-1-cc3c37287e72@mainlining.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index 03e28d77da50..10ceb6cc9841 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -66,6 +66,7 @@ allOf: - qcom,msm8996-slpi-pil - qcom,msm8998-adsp-pas - qcom,msm8998-slpi-pas + - qcom,sdm660-adsp-pas - qcom,sdm845-adsp-pas - qcom,sdm845-cdsp-pas - qcom,sdm845-slpi-pas @@ -90,6 +91,7 @@ allOf: - qcom,msm8996-slpi-pil - qcom,msm8998-adsp-pas - qcom,msm8998-slpi-pas + - qcom,sdm660-adsp-pas - qcom,sdm845-adsp-pas - qcom,sdm845-cdsp-pas - qcom,sdm845-slpi-pas @@ -110,6 +112,7 @@ allOf: - qcom,msm8974-adsp-pil - qcom,msm8996-adsp-pil - qcom,msm8998-adsp-pas + - qcom,sdm660-adsp-pas then: properties: power-domains: From acd6c28a2503f1e53ef06fb3dc1b6cbf9cc6cec3 Mon Sep 17 00:00:00 2001 From: Nickolay Goppen Date: Mon, 10 Nov 2025 21:29:44 +0300 Subject: [PATCH 36/45] dt-bindings: remoteproc: qcom: adsp: Add SDM660 CDSP compatible Add compatible for the compute DSP remoteproc found in SDM660. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Nickolay Goppen Link: https://lore.kernel.org/r/20251110-qcom-sdm660-cdsp-v3-2-cc3c37287e72@mainlining.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml index 10ceb6cc9841..137f95028313 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.yaml @@ -24,6 +24,7 @@ properties: - 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 @@ -67,6 +68,7 @@ allOf: - 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 @@ -92,6 +94,7 @@ allOf: - 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 @@ -113,6 +116,7 @@ allOf: - qcom,msm8996-adsp-pil - qcom,msm8998-adsp-pas - qcom,sdm660-adsp-pas + - qcom,sdm660-cdsp-pas then: properties: power-domains: @@ -169,6 +173,7 @@ allOf: - qcom,msm8998-adsp-pas - qcom,msm8998-slpi-pas - qcom,sdm660-adsp-pas + - qcom,sdm660-cdsp-pas then: properties: qcom,qmp: false From 950c74fd6cd80ae6773aa3bf4cb4321b83f194d2 Mon Sep 17 00:00:00 2001 From: Nickolay Goppen Date: Mon, 10 Nov 2025 21:29:45 +0300 Subject: [PATCH 37/45] remoteproc: qcom: pas: Add support for SDM660 CDSP Compute DSP in SDM660 is compatible with generic cdsp_resource_init descriptor. Reviewed-by: Dmitry Baryshkov Tested-by: Dmitry Baryshkov # ifc6560 Signed-off-by: Nickolay Goppen Link: https://lore.kernel.org/r/20251110-qcom-sdm660-cdsp-v3-3-cc3c37287e72@mainlining.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index f7c2b04c115a..609df141ecb1 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -1469,6 +1469,7 @@ static const struct of_device_id qcom_pas_of_match[] = { { .compatible = "qcom,sc8280xp-nsp0-pas", .data = &sc8280xp_nsp0_resource}, { .compatible = "qcom,sc8280xp-nsp1-pas", .data = &sc8280xp_nsp1_resource}, { .compatible = "qcom,sdm660-adsp-pas", .data = &adsp_resource_init}, + { .compatible = "qcom,sdm660-cdsp-pas", .data = &cdsp_resource_init}, { .compatible = "qcom,sdm845-adsp-pas", .data = &sdm845_adsp_resource_init}, { .compatible = "qcom,sdm845-cdsp-pas", .data = &sdm845_cdsp_resource_init}, { .compatible = "qcom,sdm845-slpi-pas", .data = &sdm845_slpi_resource_init}, From ac82dbc539c4c167f351e2e91c93508de73a5cd1 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Wed, 26 Nov 2025 12:17:59 -0600 Subject: [PATCH 38/45] remoteproc: st: Fix indexing of memory-regions The recent transition to use of_reserved_mem_region_to_resource() changes the while loop to a for loop, but the increment of the "index" variable was left behind at the end of the loop, as highlighted by the following error/warning: error: variable 'index' is incremented both in the loop header and in the loop body [-Werror,-Wfor-loop-analysis] Drop the extra increment to avoid skipping over every other memory-region in the loop. Fixes: 67a7bc7f0358 ("remoteproc: Use of_reserved_mem_region_* functions for "memory-region"") Signed-off-by: Bjorn Andersson Link: https://lore.kernel.org/r/20251126-st-remoteproc-double-index-v1-1-3b0a8b21ac18@oss.qualcomm.com Signed-off-by: Mathieu Poirier --- drivers/remoteproc/st_remoteproc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c index 747bbe7f6f7c..a07edf7217d2 100644 --- a/drivers/remoteproc/st_remoteproc.c +++ b/drivers/remoteproc/st_remoteproc.c @@ -155,7 +155,6 @@ static int st_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) return -ENOMEM; rproc_add_carveout(rproc, mem); - index++; } return rproc_elf_load_rsc_table(rproc, fw); From 099a60cca1b84e60fdaefcd5d93736de9dba9cf9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 27 Nov 2025 10:14:01 +0300 Subject: [PATCH 39/45] remoteproc: imx_dsp_rproc: Fix NULL vs IS_ERR() bug in imx_dsp_rproc_add_carveout() The devm_ioremap_resource_wc() function never returns NULL, it returns error pointers. Update the error checking to match. Fixes: 67a7bc7f0358 ("remoteproc: Use of_reserved_mem_region_* functions for "memory-region"") Signed-off-by: Dan Carpenter Reviewed-by: Iuliana Prodan Link: https://lore.kernel.org/r/aSf6OerBbPcxBUVt@stanley.mountain Signed-off-by: Mathieu Poirier --- drivers/remoteproc/imx_dsp_rproc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index be83b5f20f15..5130a35214c9 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -710,9 +710,9 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) return -EINVAL; cpu_addr = devm_ioremap_resource_wc(dev, &res); - if (!cpu_addr) { + if (IS_ERR(cpu_addr)) { dev_err(dev, "failed to map memory %pR\n", &res); - return -ENOMEM; + return PTR_ERR(cpu_addr); } /* Register memory region */ From 5e6fee736ee0d85acd74f955cab0110b15de4d11 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 29 Nov 2025 17:50:53 +0300 Subject: [PATCH 40/45] remoteproc: qcom_q6v5_adsp: Fix a NULL vs IS_ERR() check in adsp_alloc_memory_region() The devm_ioremap_resource_wc() function never returns NULL, it returns error pointers. Update the check to match. Fixes: c70b9d5fdcd7 ("remoteproc: qcom: Use of_reserved_mem_region_* functions for "memory-region"") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/6d6b1b0fb6a61b5155a640507217fd7e658858cf.1764427595.git.dan.carpenter@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_adsp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c index d3933a66ed3d..b5c8d6d38c9c 100644 --- a/drivers/remoteproc/qcom_q6v5_adsp.c +++ b/drivers/remoteproc/qcom_q6v5_adsp.c @@ -637,9 +637,10 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp) adsp->mem_phys = adsp->mem_reloc = res.start; adsp->mem_size = resource_size(&res); adsp->mem_region = devm_ioremap_resource_wc(adsp->dev, &res); - if (!adsp->mem_region) { + if (IS_ERR(adsp->mem_region)) { dev_err(adsp->dev, "unable to map memory region: %pR\n", &res); - return -EBUSY; + return PTR_ERR(adsp->mem_region); + } return 0; From e7839f773eef2072144fc858b4456aa346fcd665 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 29 Nov 2025 17:51:00 +0300 Subject: [PATCH 41/45] remoteproc: qcom: pas: Fix a couple NULL vs IS_ERR() bugs The devm_ioremap_resource_wc() function never returns NULL, it returns error pointers. Update the checking to match. Fixes: c70b9d5fdcd7 ("remoteproc: qcom: Use of_reserved_mem_region_* functions for "memory-region"") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/0599691acc394d9390da8fa0b5de3399b132b187.1764427595.git.dan.carpenter@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_pas.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index 609df141ecb1..52680ac99589 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -559,9 +559,9 @@ 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 (!pas->mem_region) { + if (IS_ERR(pas->mem_region)) { dev_err(pas->dev, "unable to map memory region: %pR\n", &res); - return -EBUSY; + return PTR_ERR(pas->mem_region); } if (!pas->dtb_pas_id) @@ -576,9 +576,9 @@ 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 (!pas->dtb_mem_region) { + if (IS_ERR(pas->dtb_mem_region)) { dev_err(pas->dev, "unable to map dtb memory region: %pR\n", &res); - return -EBUSY; + return PTR_ERR(pas->dtb_mem_region); } return 0; From cb200e41ed61c571f9b7fe9fbeb5dd8976e80c60 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 29 Nov 2025 17:51:05 +0300 Subject: [PATCH 42/45] remoteproc: qcom: q6v5: Fix NULL vs IS_ERR() bug in q6v5_alloc_memory_region() The devm_ioremap_resource_wc() function never returns NULL, it returns error pointers. Update the checking to match. Fixes: c70b9d5fdcd7 ("remoteproc: qcom: Use of_reserved_mem_region_* functions for "memory-region"") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/674b32a78563282adeaf3cdf941314a0b8181026.1764427595.git.dan.carpenter@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_wcss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c index ca748e3bcc7f..d96af0e0f665 100644 --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -887,9 +887,9 @@ static int q6v5_alloc_memory_region(struct q6v5_wcss *wcss) wcss->mem_reloc = res.start; wcss->mem_size = resource_size(&res); wcss->mem_region = devm_ioremap_resource_wc(dev, &res); - if (!wcss->mem_region) { + if (IS_ERR(wcss->mem_region)) { dev_err(dev, "unable to map memory region: %pR\n", &res); - return -EBUSY; + return PTR_ERR(wcss->mem_region); } return 0; From cda5dc12eb12cd1dd125c2bfc8952bc498a77cba Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 29 Nov 2025 17:51:10 +0300 Subject: [PATCH 43/45] remoteproc: qcom_wcnss: Fix NULL vs IS_ERR() bug in wcnss_alloc_memory_region() The devm_ioremap_resource_wc() function never returns NULL, it returns error pointers. Update the checking to match. Fixes: c70b9d5fdcd7 ("remoteproc: qcom: Use of_reserved_mem_region_* functions for "memory-region"") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/09a43da41ee277a80a3265348831e747f7b62620.1764427595.git.dan.carpenter@linaro.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_wcnss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c index 14005fb049a2..ee18bf2e8054 100644 --- a/drivers/remoteproc/qcom_wcnss.c +++ b/drivers/remoteproc/qcom_wcnss.c @@ -538,9 +538,9 @@ static int wcnss_alloc_memory_region(struct qcom_wcnss *wcnss) wcnss->mem_phys = wcnss->mem_reloc = res.start; wcnss->mem_size = resource_size(&res); wcnss->mem_region = devm_ioremap_resource_wc(wcnss->dev, &res); - if (!wcnss->mem_region) { + if (IS_ERR(wcnss->mem_region)) { dev_err(wcnss->dev, "unable to map memory region: %pR\n", &res); - return -EBUSY; + return PTR_ERR(wcnss->mem_region); } return 0; From 7e81fa8d809ed1e67ae9ecd52d20a20c2c65d877 Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Fri, 28 Nov 2025 19:32:05 -0600 Subject: [PATCH 44/45] remoteproc: qcom_q6v5_wcss: fix parsing of qcom,halt-regs The "qcom,halt-regs" consists of a phandle reference followed by the three offsets within syscon for halt registers. Thus, we need to request 4 integers from of_property_read_variable_u32_array(), with the halt_reg ofsets at indexes 1, 2, and 3. Offset 0 is the phandle. With MAX_HALT_REG at 3, of_property_read_variable_u32_array() returns -EOVERFLOW, causing .probe() to fail. Increase MAX_HALT_REG to 4, and update the indexes accordingly. Fixes: 0af65b9b915e ("remoteproc: qcom: wcss: Add non pas wcss Q6 support for QCS404") Signed-off-by: Alexandru Gagniuc Link: https://lore.kernel.org/r/20251129013207.3981517-1-mr.nuke.me@gmail.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_wcss.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c index d96af0e0f665..83fe5b9a0240 100644 --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -85,7 +85,7 @@ #define TCSR_WCSS_CLK_MASK 0x1F #define TCSR_WCSS_CLK_ENABLE 0x14 -#define MAX_HALT_REG 3 +#define MAX_HALT_REG 4 enum { WCSS_IPQ8074, WCSS_QCS404, @@ -864,9 +864,9 @@ static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss, return -EINVAL; } - wcss->halt_q6 = halt_reg[0]; - wcss->halt_wcss = halt_reg[1]; - wcss->halt_nc = halt_reg[2]; + wcss->halt_q6 = halt_reg[1]; + wcss->halt_wcss = halt_reg[2]; + wcss->halt_nc = halt_reg[3]; return 0; } From 641092c1bc1bbc3be059d9d723b1cec10a368617 Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Fri, 28 Nov 2025 19:32:06 -0600 Subject: [PATCH 45/45] remoteproc: qcom_q6v5_wcss: use optional reset for wcss_q6_bcr_reset The "wcss_q6_bcr_reset" is not used on IPQ8074, and IPQ6018. Use devm_reset_control_get_optional_exclusive() for this reset so that probe() does not fail on platforms where it is not used. Signed-off-by: Alexandru Gagniuc Link: https://lore.kernel.org/r/20251129013207.3981517-2-mr.nuke.me@gmail.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c index 83fe5b9a0240..c27200159a88 100644 --- a/drivers/remoteproc/qcom_q6v5_wcss.c +++ b/drivers/remoteproc/qcom_q6v5_wcss.c @@ -811,7 +811,8 @@ static int q6v5_wcss_init_reset(struct q6v5_wcss *wcss, } } - wcss->wcss_q6_bcr_reset = devm_reset_control_get_exclusive(dev, "wcss_q6_bcr_reset"); + wcss->wcss_q6_bcr_reset = devm_reset_control_get_optional_exclusive(dev, + "wcss_q6_bcr_reset"); if (IS_ERR(wcss->wcss_q6_bcr_reset)) { dev_err(wcss->dev, "unable to acquire wcss_q6_bcr_reset\n"); return PTR_ERR(wcss->wcss_q6_bcr_reset);