diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-14 11:17:54 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-14 11:17:54 -0800 |
| commit | 2bfc50c6e6e67b08770c6ef46660c3ee9c6a1519 (patch) | |
| tree | 7ca6fabb929c1ab36d348d006407aafefcb9b0db /drivers | |
| parent | f0a475aedd190db95cf92914ca7760c06fbdb704 (diff) | |
| parent | 26aa5295010ffaebcf8f1991c53fa7cf2ee1b20d (diff) | |
Merge tag 'rproc-v7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux
Pull remoteproc updates from Bjorn Andersson:
- Fix a memory remapping issue and make a few life-cycle improvements
in the i.MX HiFi remoteproc driver
- Add support the System Manager CPU and LMM APIs and use this to
support i.MX95
- Rework the handling of the Mediatek SCP clock to avoid a potential
circular deadlock in the clock providers
- Refactor the Qualcomm secure-world helpers and add support in the
Qualcomm PAS remoteproc driver for reading a resource-table from
secure world. Use this to configure the IOMMU on newer targets where
Linux runs in EL2
* tag 'rproc-v7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux:
remoteproc: imx_rproc: Fix invalid loaded resource table detection
remoteproc: mediatek: Break lock dependency to `prepare_lock`
remoteproc: imx_rproc: Add support for i.MX95
remoteproc: imx_rproc: Add support for System Manager CPU API
remoteproc: imx_rproc: Add support for System Manager LMM API
remoteproc: imx_rproc: Introduce prepare ops for imx_rproc_dcfg
remoteproc: imx_rproc: Add runtime ops copy to support dynamic behavior
dt-bindings: remoteproc: fsl,imx-rproc: Add support for i.MX95
dt-bindings: remoteproc: Add HSM M4F core on TI K3 SoCs
remoteproc: xlnx_r5: Simplify with scoped for each OF child loop
remoteproc: mtk_scp: Simplify with scoped for each OF child loop
remoteproc: imx_dsp_rproc: Only reset carveout memory at RPROC_OFFLINE state
dt-bindings: remoteproc: qcom,sm8550-pas: Drop SM8750 ADSP from if-branch
dt-bindings: remoteproc: qcom,adsp: Allow cx-supply on qcom,sdm845-slpi-pas
remoteproc: imx_dsp_rproc: Fix multiple start/stop operations
remoteproc: imx_rproc: Use strstarts for "rsc-table" check
remoteproc: imx_dsp_rproc: Wait for suspend ACK only if WAIT_FW_CONFIRMATION is set
remoteproc: imx_dsp_rproc: Rename macro to reflect multiple contexts
remoteproc: imx_dsp_rproc: Skip RP_MBOX_SUSPEND_SYSTEM when mailbox TX channel is uninitialized
dt-bindings: remoteproc: Fix dead link to Keystone DSP GPIO binding
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/remoteproc/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/remoteproc/imx_dsp_rproc.c | 95 | ||||
| -rw-r--r-- | drivers/remoteproc/imx_rproc.c | 255 | ||||
| -rw-r--r-- | drivers/remoteproc/imx_rproc.h | 4 | ||||
| -rw-r--r-- | drivers/remoteproc/mtk_scp.c | 46 | ||||
| -rw-r--r-- | drivers/remoteproc/mtk_scp_ipi.c | 4 | ||||
| -rw-r--r-- | drivers/remoteproc/xlnx_r5_remoteproc.c | 9 |
7 files changed, 344 insertions, 71 deletions
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 48a0d3a69ed0..ee54436fea5a 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -27,6 +27,8 @@ config IMX_REMOTEPROC tristate "i.MX remoteproc support" depends on ARCH_MXC depends on HAVE_ARM_SMCCC + depends on IMX_SCMI_CPU_DRV || !IMX_SCMI_CPU_DRV + depends on IMX_SCMI_LMM_DRV || !IMX_SCMI_LMM_DRV select MAILBOX help Say y here to support iMX's remote processors via the remote diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 5130a35214c9..008741af9f11 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -38,15 +38,15 @@ MODULE_PARM_DESC(no_mailboxes, /* Flag indicating that the remote is up and running */ #define REMOTE_IS_READY BIT(0) -/* Flag indicating that the host should wait for a firmware-ready response */ -#define WAIT_FW_READY BIT(1) +/* Flag indicating that the host should wait for a firmware-confirmation response */ +#define WAIT_FW_CONFIRMATION BIT(1) #define REMOTE_READY_WAIT_MAX_RETRIES 500 /* * This flag is set in the DSP resource table's features field to indicate - * that the firmware requires the host NOT to wait for a FW_READY response. + * that the firmware requires the host NOT to wait for a FW_CONFIRMATION response. */ -#define FEATURE_DONT_WAIT_FW_READY BIT(0) +#define FEATURE_SKIP_FW_CONFIRMATION BIT(0) /* att flags */ /* DSP own area */ @@ -287,7 +287,7 @@ static int imx_dsp_rproc_ready(struct rproc *rproc) * @avail: available space in the resource table * * Parse the DSP-specific resource entry and update flags accordingly. - * If the WAIT_FW_READY feature is set, the host must wait for the firmware + * If the WAIT_FW_CONFIRMATION feature is set, the host must wait for the firmware * to signal readiness before proceeding with execution. * * Return: RSC_HANDLED if processed successfully, RSC_IGNORED otherwise. @@ -322,7 +322,7 @@ static int imx_dsp_rproc_handle_rsc(struct rproc *rproc, u32 rsc_type, /* * For now, in struct fw_rsc_imx_dsp, version 0, - * only FEATURE_DONT_WAIT_FW_READY is valid. + * only FEATURE_SKIP_FW_CONFIRMATION is valid. * * When adding new features, please upgrade version. */ @@ -332,8 +332,8 @@ static int imx_dsp_rproc_handle_rsc(struct rproc *rproc, u32 rsc_type, return RSC_IGNORED; } - if (imx_dsp_rsc->features & FEATURE_DONT_WAIT_FW_READY) - priv->flags &= ~WAIT_FW_READY; + if (imx_dsp_rsc->features & FEATURE_SKIP_FW_CONFIRMATION) + priv->flags &= ~WAIT_FW_CONFIRMATION; return RSC_HANDLED; } @@ -385,7 +385,7 @@ static int imx_dsp_rproc_start(struct rproc *rproc) return ret; } - if (priv->flags & WAIT_FW_READY) + if (priv->flags & WAIT_FW_CONFIRMATION) return imx_dsp_rproc_ready(rproc); return 0; @@ -644,6 +644,32 @@ static void imx_dsp_rproc_free_mbox(struct imx_dsp_rproc *priv) mbox_free_channel(priv->rxdb_ch); } +static int imx_dsp_rproc_mem_alloc(struct rproc *rproc, + struct rproc_mem_entry *mem) +{ + struct device *dev = rproc->dev.parent; + void *va; + + va = ioremap_wc(mem->dma, mem->len); + if (!va) { + dev_err(dev, "Unable to map memory region: %pa+%zx\n", + &mem->dma, mem->len); + return -ENOMEM; + } + + mem->va = va; + + return 0; +} + +static int imx_dsp_rproc_mem_release(struct rproc *rproc, + struct rproc_mem_entry *mem) +{ + iounmap(mem->va); + + return 0; +} + /** * imx_dsp_rproc_add_carveout() - request mailbox channels * @priv: private data pointer @@ -659,7 +685,6 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) struct device *dev = rproc->dev.parent; struct device_node *np = dev->of_node; struct rproc_mem_entry *mem; - void __iomem *cpu_addr; int a, i = 0; u64 da; @@ -673,15 +698,10 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) if (imx_dsp_rproc_sys_to_da(priv, att->sa, att->size, &da)) return -EINVAL; - cpu_addr = devm_ioremap_wc(dev, att->sa, att->size); - if (!cpu_addr) { - dev_err(dev, "failed to map memory %p\n", &att->sa); - return -ENOMEM; - } - /* Register memory region */ - mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)att->sa, - att->size, da, NULL, NULL, "dsp_mem"); + mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)att->sa, + att->size, da, imx_dsp_rproc_mem_alloc, + imx_dsp_rproc_mem_release, "dsp_mem"); if (mem) rproc_coredump_add_segment(rproc, da, att->size); @@ -709,15 +729,11 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) if (imx_dsp_rproc_sys_to_da(priv, res.start, resource_size(&res), &da)) return -EINVAL; - cpu_addr = devm_ioremap_resource_wc(dev, &res); - if (IS_ERR(cpu_addr)) { - dev_err(dev, "failed to map memory %pR\n", &res); - return PTR_ERR(cpu_addr); - } - /* Register memory region */ - mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)res.start, - resource_size(&res), da, NULL, NULL, + mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)res.start, + resource_size(&res), da, + imx_dsp_rproc_mem_alloc, + imx_dsp_rproc_mem_release, "%.*s", strchrnul(res.name, '@') - res.name, res.name); if (!mem) return -ENOMEM; @@ -984,9 +1000,11 @@ static int imx_dsp_rproc_load(struct rproc *rproc, const struct firmware *fw) * Clear buffers after pm rumtime for internal ocram is not * accessible if power and clock are not enabled. */ - list_for_each_entry(carveout, &rproc->carveouts, node) { - if (carveout->va) - memset(carveout->va, 0, carveout->len); + if (rproc->state == RPROC_OFFLINE) { + list_for_each_entry(carveout, &rproc->carveouts, node) { + if (carveout->va) + memset(carveout->va, 0, carveout->len); + } } ret = imx_dsp_rproc_elf_load_segments(rproc, fw); @@ -1131,8 +1149,8 @@ static int imx_dsp_rproc_probe(struct platform_device *pdev) priv = rproc->priv; priv->rproc = rproc; priv->dsp_dcfg = dsp_dcfg; - /* By default, host waits for fw_ready reply */ - priv->flags |= WAIT_FW_READY; + /* By default, host waits for fw_confirmation reply */ + priv->flags |= WAIT_FW_CONFIRMATION; if (no_mailboxes) imx_dsp_rproc_mbox_init = imx_dsp_rproc_mbox_no_alloc; @@ -1242,6 +1260,21 @@ static int imx_dsp_suspend(struct device *dev) if (rproc->state != RPROC_RUNNING) goto out; + /* + * No channel available for sending messages; + * indicates no mailboxes present, so trigger PM runtime suspend + */ + if (!priv->tx_ch) { + dev_dbg(dev, "No initialized mbox tx channel, suspend directly.\n"); + goto out; + } + + /* No fw confirmation expected, so trigger PM runtime suspend */ + if (!(priv->flags & WAIT_FW_CONFIRMATION)) { + dev_dbg(dev, "No FW_CONFIRMATION needed, suspend directly.\n"); + goto out; + } + reinit_completion(&priv->pm_comp); /* Tell DSP that suspend is happening */ diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 3be8790c14a2..f5f916d67905 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -8,6 +8,7 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/firmware/imx/sci.h> +#include <linux/firmware/imx/sm.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/mailbox_client.h> @@ -22,6 +23,7 @@ #include <linux/reboot.h> #include <linux/regmap.h> #include <linux/remoteproc.h> +#include <linux/scmi_imx_protocol.h> #include <linux/workqueue.h> #include "imx_rproc.h" @@ -92,9 +94,16 @@ struct imx_rproc_mem { #define ATT_CORE_MASK 0xffff #define ATT_CORE(I) BIT((I)) +/* Linux has permission to handle the Logical Machine of remote cores */ +#define IMX_RPROC_FLAGS_SM_LMM_CTRL BIT(0) + static int imx_rproc_xtr_mbox_init(struct rproc *rproc, bool tx_block); static void imx_rproc_free_mbox(void *data); +/* Forward declarations for platform operations */ +static const struct imx_rproc_plat_ops imx_rproc_ops_sm_lmm; +static const struct imx_rproc_plat_ops imx_rproc_ops_sm_cpu; + struct imx_rproc { struct device *dev; struct regmap *regmap; @@ -116,6 +125,24 @@ struct imx_rproc { u32 entry; /* cpu start address */ u32 core_index; struct dev_pm_domain_list *pd_list; + const struct imx_rproc_plat_ops *ops; + /* + * For i.MX System Manager based systems + * BIT 0: IMX_RPROC_FLAGS_SM_LMM_CTRL(RPROC LM is under Linux control ) + */ + u32 flags; +}; + +static const struct imx_rproc_att imx_rproc_att_imx95_m7[] = { + /* dev addr , sys addr , size , flags */ + /* TCM CODE NON-SECURE */ + { 0x00000000, 0x203C0000, 0x00040000, ATT_OWN | ATT_IOMEM }, + + /* TCM SYS NON-SECURE*/ + { 0x20000000, 0x20400000, 0x00040000, ATT_OWN | ATT_IOMEM }, + + /* DDR */ + { 0x80000000, 0x80000000, 0x50000000, 0 }, }; static const struct imx_rproc_att imx_rproc_att_imx93[] = { @@ -312,21 +339,62 @@ static int imx_rproc_scu_api_start(struct rproc *rproc) return imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, true, priv->entry); } -static int imx_rproc_start(struct rproc *rproc) +static int imx_rproc_sm_cpu_start(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + int ret; + + ret = scmi_imx_cpu_reset_vector_set(dcfg->cpuid, 0, true, false, false); + if (ret) { + dev_err(priv->dev, "Failed to set reset vector cpuid(%u): %d\n", dcfg->cpuid, ret); + return ret; + } + + return scmi_imx_cpu_start(dcfg->cpuid, true); +} + +static int imx_rproc_sm_lmm_start(struct rproc *rproc) { struct imx_rproc *priv = rproc->priv; const struct imx_rproc_dcfg *dcfg = priv->dcfg; struct device *dev = priv->dev; int ret; + /* + * If the remoteproc core can't start the M7, it will already be + * handled in imx_rproc_sm_lmm_prepare(). + */ + ret = scmi_imx_lmm_reset_vector_set(dcfg->lmid, dcfg->cpuid, 0, 0); + if (ret) { + dev_err(dev, "Failed to set reset vector lmid(%u), cpuid(%u): %d\n", + dcfg->lmid, dcfg->cpuid, ret); + return ret; + } + + ret = scmi_imx_lmm_operation(dcfg->lmid, SCMI_IMX_LMM_BOOT, 0); + if (ret) { + dev_err(dev, "Failed to boot lmm(%d): %d\n", dcfg->lmid, ret); + return ret; + } + + return 0; +} + +static int imx_rproc_start(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + struct device *dev = priv->dev; + int ret; + ret = imx_rproc_xtr_mbox_init(rproc, true); if (ret) return ret; - if (!dcfg->ops || !dcfg->ops->start) + if (!priv->ops || !priv->ops->start) return -EOPNOTSUPP; - ret = dcfg->ops->start(rproc); + ret = priv->ops->start(rproc); if (ret) dev_err(dev, "Failed to enable remote core!\n"); @@ -369,17 +437,35 @@ static int imx_rproc_scu_api_stop(struct rproc *rproc) return imx_sc_pm_cpu_start(priv->ipc_handle, priv->rsrc_id, false, priv->entry); } -static int imx_rproc_stop(struct rproc *rproc) +static int imx_rproc_sm_cpu_stop(struct rproc *rproc) { struct imx_rproc *priv = rproc->priv; const struct imx_rproc_dcfg *dcfg = priv->dcfg; + + return scmi_imx_cpu_start(dcfg->cpuid, false); +} + +static int imx_rproc_sm_lmm_stop(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + + if (!(priv->flags & IMX_RPROC_FLAGS_SM_LMM_CTRL)) + return -EACCES; + + return scmi_imx_lmm_operation(dcfg->lmid, SCMI_IMX_LMM_SHUTDOWN, 0); +} + +static int imx_rproc_stop(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; struct device *dev = priv->dev; int ret; - if (!dcfg->ops || !dcfg->ops->stop) + if (!priv->ops || !priv->ops->stop) return -EOPNOTSUPP; - ret = dcfg->ops->stop(rproc); + ret = priv->ops->stop(rproc); if (ret) dev_err(dev, "Failed to stop remote core\n"); else @@ -486,6 +572,36 @@ static int imx_rproc_mem_release(struct rproc *rproc, return 0; } +static int imx_rproc_sm_lmm_prepare(struct rproc *rproc) +{ + struct imx_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + int ret; + + /* + * IMX_RPROC_FLAGS_SM_LMM_CTRL not set indicates Linux is not able + * to start/stop M7, then if rproc is not in detached state, + * prepare should fail. If in detached state, this is in rproc_attach() + * path. + */ + if (rproc->state == RPROC_DETACHED) + return 0; + + if (!(priv->flags & IMX_RPROC_FLAGS_SM_LMM_CTRL)) + return -EACCES; + + /* Power on the Logical Machine to make sure TCM is available. */ + ret = scmi_imx_lmm_operation(dcfg->lmid, SCMI_IMX_LMM_POWER_ON, 0); + if (ret) { + dev_err(priv->dev, "Failed to power on lmm(%d): %d\n", dcfg->lmid, ret); + return ret; + } + + dev_info(priv->dev, "lmm(%d) powered on by Linux\n", dcfg->lmid); + + return 0; +} + static int imx_rproc_prepare(struct rproc *rproc) { struct imx_rproc *priv = rproc->priv; @@ -528,6 +644,11 @@ static int imx_rproc_prepare(struct rproc *rproc) rproc_coredump_add_segment(rproc, da, resource_size(&res)); rproc_add_carveout(rproc, mem); } + + if (priv->ops && priv->ops->prepare) + return priv->ops->prepare(rproc); + + return 0; } static int imx_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) @@ -584,12 +705,11 @@ static int imx_rproc_scu_api_detach(struct rproc *rproc) 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) + if (!priv->ops || !priv->ops->detach) return -EOPNOTSUPP; - return dcfg->ops->detach(rproc); + return priv->ops->detach(rproc); } static struct resource_table *imx_rproc_get_loaded_rsc_table(struct rproc *rproc, size_t *table_sz) @@ -609,6 +729,10 @@ imx_rproc_elf_find_loaded_rsc_table(struct rproc *rproc, const struct firmware * { struct imx_rproc *priv = rproc->priv; + /* No resource table in the firmware */ + if (!rproc->table_ptr) + return NULL; + if (priv->rsc_table) return (struct resource_table *)priv->rsc_table; @@ -694,7 +818,7 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, } priv->mem[b].sys_addr = res.start; priv->mem[b].size = resource_size(&res); - if (!strcmp(res.name, "rsc-table")) + if (strstarts(res.name, "rsc-table")) priv->rsc_table = priv->mem[b].cpu_addr; b++; } @@ -977,20 +1101,97 @@ static int imx_rproc_scu_api_detect_mode(struct rproc *rproc) return 0; } -static int imx_rproc_detect_mode(struct imx_rproc *priv) +/* Check whether remoteproc core is responsible for M7 lifecycle */ +static int imx_rproc_sm_lmm_check(struct rproc *rproc, bool started) +{ + struct imx_rproc *priv = rproc->priv; + const struct imx_rproc_dcfg *dcfg = priv->dcfg; + struct device *dev = priv->dev; + int ret; + + ret = scmi_imx_lmm_operation(dcfg->lmid, SCMI_IMX_LMM_POWER_ON, 0); + if (ret) { + if (ret == -EACCES) { + /* + * M7 is booted before Linux and not under Linux Control, so only + * do IPC between RPROC and Linux, not return failure + */ + dev_info(dev, "lmm(%d) not under Linux Control\n", dcfg->lmid); + return 0; + } + + dev_err(dev, "power on lmm(%d) failed: %d\n", dcfg->lmid, ret); + return ret; + } + + /* Shutdown remote processor if not started */ + if (!started) { + ret = scmi_imx_lmm_operation(dcfg->lmid, SCMI_IMX_LMM_SHUTDOWN, 0); + if (ret) { + dev_err(dev, "shutdown lmm(%d) failed: %d\n", dcfg->lmid, ret); + return ret; + } + } + + priv->flags |= IMX_RPROC_FLAGS_SM_LMM_CTRL; + + return 0; +} + +static int imx_rproc_sm_detect_mode(struct rproc *rproc) { + struct imx_rproc *priv = rproc->priv; const struct imx_rproc_dcfg *dcfg = priv->dcfg; + struct device *dev = priv->dev; + struct scmi_imx_lmm_info info; + bool started = false; + int ret; + + ret = scmi_imx_cpu_started(dcfg->cpuid, &started); + if (ret) { + dev_err(dev, "Failed to detect cpu(%d) status: %d\n", dcfg->cpuid, ret); + return ret; + } + + if (started) + priv->rproc->state = RPROC_DETACHED; + + /* Get current Linux Logical Machine ID */ + ret = scmi_imx_lmm_info(LMM_ID_DISCOVER, &info); + if (ret) { + dev_err(dev, "Failed to get current LMM ID err: %d\n", ret); + return ret; + } /* + * Check whether M7 is in the same LM as host core(running Linux) + * If yes, use CPU protocol API to manage M7. + * If no, use Logical Machine API to manage M7. + */ + if (dcfg->lmid == info.lmid) { + priv->ops = &imx_rproc_ops_sm_cpu; + dev_info(dev, "Using CPU Protocol OPS\n"); + return 0; + } + + priv->ops = &imx_rproc_ops_sm_lmm; + dev_info(dev, "Using LMM Protocol OPS\n"); + + return imx_rproc_sm_lmm_check(rproc, started); +} + +static int imx_rproc_detect_mode(struct imx_rproc *priv) +{ + /* * To i.MX{7,8} ULP, Linux is under control of RTOS, no need - * dcfg->ops or dcfg->ops->detect_mode, it is state RPROC_DETACHED. + * priv->ops or priv->ops->detect_mode, it is state RPROC_DETACHED. */ - if (!dcfg->ops || !dcfg->ops->detect_mode) { + if (!priv->ops || !priv->ops->detect_mode) { priv->rproc->state = RPROC_DETACHED; return 0; } - return dcfg->ops->detect_mode(priv->rproc); + return priv->ops->detect_mode(priv->rproc); } static int imx_rproc_sys_off_handler(struct sys_off_data *data) @@ -1040,6 +1241,9 @@ static int imx_rproc_probe(struct platform_device *pdev) priv->dcfg = dcfg; priv->dev = dev; + if (dcfg->ops) + priv->ops = dcfg->ops; + dev_set_drvdata(dev, rproc); priv->workqueue = create_workqueue(dev_name(dev)); if (!priv->workqueue) { @@ -1151,6 +1355,19 @@ static const struct imx_rproc_plat_ops imx_rproc_ops_scu_api = { .detect_mode = imx_rproc_scu_api_detect_mode, }; +static const struct imx_rproc_plat_ops imx_rproc_ops_sm_lmm = { + .detect_mode = imx_rproc_sm_detect_mode, + .prepare = imx_rproc_sm_lmm_prepare, + .start = imx_rproc_sm_lmm_start, + .stop = imx_rproc_sm_lmm_stop, +}; + +static const struct imx_rproc_plat_ops imx_rproc_ops_sm_cpu = { + .detect_mode = imx_rproc_sm_detect_mode, + .start = imx_rproc_sm_cpu_start, + .stop = imx_rproc_sm_cpu_stop, +}; + static const struct imx_rproc_dcfg imx_rproc_cfg_imx8mn_mmio = { .src_reg = IMX7D_SRC_SCR, .src_mask = IMX7D_M4_RST_MASK, @@ -1234,6 +1451,15 @@ static const struct imx_rproc_dcfg imx_rproc_cfg_imx93 = { .flags = IMX_RPROC_NEED_CLKS, }; +static const struct imx_rproc_dcfg imx_rproc_cfg_imx95_m7 = { + .att = imx_rproc_att_imx95_m7, + .att_size = ARRAY_SIZE(imx_rproc_att_imx95_m7), + .ops = &imx_rproc_ops_sm_lmm, + /* Must align with System Manager Firmware */ + .cpuid = 1, /* Use 1 as cpu id for M7 core */ + .lmid = 1, /* Use 1 as Logical Machine ID where M7 resides */ +}; + static const struct of_device_id imx_rproc_of_match[] = { { .compatible = "fsl,imx7ulp-cm4", .data = &imx_rproc_cfg_imx7ulp }, { .compatible = "fsl,imx7d-cm4", .data = &imx_rproc_cfg_imx7d }, @@ -1248,6 +1474,7 @@ static const struct of_device_id imx_rproc_of_match[] = { { .compatible = "fsl,imx8qm-cm4", .data = &imx_rproc_cfg_imx8qm }, { .compatible = "fsl,imx8ulp-cm33", .data = &imx_rproc_cfg_imx8ulp }, { .compatible = "fsl,imx93-cm33", .data = &imx_rproc_cfg_imx93 }, + { .compatible = "fsl,imx95-cm7", .data = &imx_rproc_cfg_imx95_m7 }, {}, }; MODULE_DEVICE_TABLE(of, imx_rproc_of_match); diff --git a/drivers/remoteproc/imx_rproc.h b/drivers/remoteproc/imx_rproc.h index 1b2d9f4d6d19..d37e6f90548c 100644 --- a/drivers/remoteproc/imx_rproc.h +++ b/drivers/remoteproc/imx_rproc.h @@ -24,6 +24,7 @@ struct imx_rproc_plat_ops { int (*stop)(struct rproc *rproc); int (*detach)(struct rproc *rproc); int (*detect_mode)(struct rproc *rproc); + int (*prepare)(struct rproc *rproc); }; struct imx_rproc_dcfg { @@ -37,6 +38,9 @@ struct imx_rproc_dcfg { size_t att_size; u32 flags; const struct imx_rproc_plat_ops *ops; + /* For System Manager(SM) based SoCs */ + u32 cpuid; /* ID of the remote core */ + u32 lmid; /* ID of the Logcial Machine */ }; #endif /* _IMX_RPROC_H */ diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c index db8fd045468d..4651311aeb07 100644 --- a/drivers/remoteproc/mtk_scp.c +++ b/drivers/remoteproc/mtk_scp.c @@ -283,7 +283,7 @@ static irqreturn_t scp_irq_handler(int irq, void *priv) struct mtk_scp *scp = priv; int ret; - ret = clk_prepare_enable(scp->clk); + ret = clk_enable(scp->clk); if (ret) { dev_err(scp->dev, "failed to enable clocks\n"); return IRQ_NONE; @@ -291,7 +291,7 @@ static irqreturn_t scp_irq_handler(int irq, void *priv) scp->data->scp_irq_handler(scp); - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); return IRQ_HANDLED; } @@ -665,7 +665,7 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw) struct device *dev = scp->dev; int ret; - ret = clk_prepare_enable(scp->clk); + ret = clk_enable(scp->clk); if (ret) { dev_err(dev, "failed to enable clocks\n"); return ret; @@ -680,7 +680,7 @@ static int scp_load(struct rproc *rproc, const struct firmware *fw) ret = scp_elf_load_segments(rproc, fw); leave: - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); return ret; } @@ -691,14 +691,14 @@ static int scp_parse_fw(struct rproc *rproc, const struct firmware *fw) struct device *dev = scp->dev; int ret; - ret = clk_prepare_enable(scp->clk); + ret = clk_enable(scp->clk); if (ret) { dev_err(dev, "failed to enable clocks\n"); return ret; } ret = scp_ipi_init(scp, fw); - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); return ret; } @@ -709,7 +709,7 @@ static int scp_start(struct rproc *rproc) struct scp_run *run = &scp->run; int ret; - ret = clk_prepare_enable(scp->clk); + ret = clk_enable(scp->clk); if (ret) { dev_err(dev, "failed to enable clocks\n"); return ret; @@ -734,14 +734,14 @@ static int scp_start(struct rproc *rproc) goto stop; } - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); dev_info(dev, "SCP is ready. FW version %s\n", run->fw_ver); return 0; stop: scp->data->scp_reset_assert(scp); - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); return ret; } @@ -909,7 +909,7 @@ static int scp_stop(struct rproc *rproc) struct mtk_scp *scp = rproc->priv; int ret; - ret = clk_prepare_enable(scp->clk); + ret = clk_enable(scp->clk); if (ret) { dev_err(scp->dev, "failed to enable clocks\n"); return ret; @@ -917,12 +917,29 @@ static int scp_stop(struct rproc *rproc) scp->data->scp_reset_assert(scp); scp->data->scp_stop(scp); - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); return 0; } +static int scp_prepare(struct rproc *rproc) +{ + struct mtk_scp *scp = rproc->priv; + + return clk_prepare(scp->clk); +} + +static int scp_unprepare(struct rproc *rproc) +{ + struct mtk_scp *scp = rproc->priv; + + clk_unprepare(scp->clk); + return 0; +} + static const struct rproc_ops scp_ops = { + .prepare = scp_prepare, + .unprepare = scp_unprepare, .start = scp_start, .stop = scp_stop, .load = scp_load, @@ -1287,7 +1304,6 @@ static int scp_add_multi_core(struct platform_device *pdev, struct device *dev = &pdev->dev; struct device_node *np = dev_of_node(dev); struct platform_device *cpdev; - struct device_node *child; struct list_head *scp_list = &scp_cluster->mtk_scp_list; const struct mtk_scp_of_data **cluster_of_data; struct mtk_scp *scp, *temp; @@ -1296,11 +1312,10 @@ static int scp_add_multi_core(struct platform_device *pdev, cluster_of_data = (const struct mtk_scp_of_data **)of_device_get_match_data(dev); - for_each_available_child_of_node(np, child) { + for_each_available_child_of_node_scoped(np, child) { if (!cluster_of_data[core_id]) { ret = -EINVAL; dev_err(dev, "Not support core %d\n", core_id); - of_node_put(child); goto init_fail; } @@ -1308,7 +1323,6 @@ static int scp_add_multi_core(struct platform_device *pdev, if (!cpdev) { ret = -ENODEV; dev_err(dev, "Not found platform device for core %d\n", core_id); - of_node_put(child); goto init_fail; } @@ -1317,14 +1331,12 @@ static int scp_add_multi_core(struct platform_device *pdev, if (IS_ERR(scp)) { ret = PTR_ERR(scp); dev_err(dev, "Failed to initialize core %d rproc\n", core_id); - of_node_put(child); goto init_fail; } ret = rproc_add(scp->rproc); if (ret) { dev_err(dev, "Failed to add rproc of core %d\n", core_id); - of_node_put(child); scp_free(scp); goto init_fail; } diff --git a/drivers/remoteproc/mtk_scp_ipi.c b/drivers/remoteproc/mtk_scp_ipi.c index c068227e251e..7a37e273b3af 100644 --- a/drivers/remoteproc/mtk_scp_ipi.c +++ b/drivers/remoteproc/mtk_scp_ipi.c @@ -171,7 +171,7 @@ int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf, unsigned int len, WARN_ON(len > scp_sizes->ipi_share_buffer_size) || WARN_ON(!buf)) return -EINVAL; - ret = clk_prepare_enable(scp->clk); + ret = clk_enable(scp->clk); if (ret) { dev_err(scp->dev, "failed to enable clock\n"); return ret; @@ -211,7 +211,7 @@ int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf, unsigned int len, unlock_mutex: mutex_unlock(&scp->send_lock); - clk_disable_unprepare(scp->clk); + clk_disable(scp->clk); return ret; } diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c index a7b75235f53e..bd619a6c42aa 100644 --- a/drivers/remoteproc/xlnx_r5_remoteproc.c +++ b/drivers/remoteproc/xlnx_r5_remoteproc.c @@ -1271,7 +1271,6 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster) struct zynqmp_r5_core **r5_cores; enum rpu_oper_mode fw_reg_val; struct device **child_devs; - struct device_node *child; enum rpu_tcm_comb tcm_mode; int core_count, ret, i; struct mbox_info *ipi; @@ -1350,10 +1349,9 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster) } i = 0; - for_each_available_child_of_node(dev_node, child) { + for_each_available_child_of_node_scoped(dev_node, child) { child_pdev = of_find_device_by_node(child); if (!child_pdev) { - of_node_put(child); ret = -ENODEV; goto release_r5_cores; } @@ -1363,7 +1361,6 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster) /* create and add remoteproc instance of type struct rproc */ r5_cores[i] = zynqmp_r5_add_rproc_core(&child_pdev->dev); if (IS_ERR(r5_cores[i])) { - of_node_put(child); ret = PTR_ERR(r5_cores[i]); r5_cores[i] = NULL; goto release_r5_cores; @@ -1383,10 +1380,8 @@ static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster) * If two child nodes are available in dts in lockstep mode, * then ignore second child node. */ - if (cluster_mode == LOCKSTEP_MODE) { - of_node_put(child); + if (cluster_mode == LOCKSTEP_MODE) break; - } i++; } |
