diff options
Diffstat (limited to 'drivers/remoteproc/imx_dsp_rproc.c')
| -rw-r--r-- | drivers/remoteproc/imx_dsp_rproc.c | 541 |
1 files changed, 333 insertions, 208 deletions
diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c index 376187ad5754..5130a35214c9 100644 --- a/drivers/remoteproc/imx_dsp_rproc.c +++ b/drivers/remoteproc/imx_dsp_rproc.c @@ -19,6 +19,7 @@ #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/remoteproc.h> +#include <linux/reset.h> #include <linux/slab.h> #include "imx_rproc.h" @@ -35,9 +36,18 @@ module_param_named(no_mailboxes, no_mailboxes, int, 0644); MODULE_PARM_DESC(no_mailboxes, "There is no mailbox between cores, so ignore remote proc reply after start, default is 0 (off)."); +/* 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) #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. + */ +#define FEATURE_DONT_WAIT_FW_READY BIT(0) + /* att flags */ /* DSP own area */ #define ATT_OWN BIT(31) @@ -72,6 +82,10 @@ MODULE_PARM_DESC(no_mailboxes, #define IMX8ULP_SIP_HIFI_XRDC 0xc200000e +#define FW_RSC_NXP_S_MAGIC ((uint32_t)'n' << 24 | \ + (uint32_t)'x' << 16 | \ + (uint32_t)'p' << 8 | \ + (uint32_t)'s') /* * enum - Predefined Mailbox Messages * @@ -95,6 +109,7 @@ enum imx_dsp_rp_mbox_messages { /** * struct imx_dsp_rproc - DSP remote processor state * @regmap: regmap handler + * @run_stall: reset control handle used for Run/Stall operation * @rproc: rproc handler * @dsp_dcfg: device configuration pointer * @clks: clocks needed by this device @@ -111,6 +126,7 @@ enum imx_dsp_rp_mbox_messages { */ struct imx_dsp_rproc { struct regmap *regmap; + struct reset_control *run_stall; struct rproc *rproc; const struct imx_dsp_rproc_dcfg *dsp_dcfg; struct clk_bulk_data clks[DSP_RPROC_CLK_MAX]; @@ -136,6 +152,24 @@ struct imx_dsp_rproc_dcfg { int (*reset)(struct imx_dsp_rproc *priv); }; +/** + * struct fw_rsc_imx_dsp - i.MX DSP specific info + * + * @len: length of the resource entry + * @magic_num: 32-bit magic number + * @version: version of data structure + * @features: feature flags supported by the i.MX DSP firmware + * + * This represents a DSP-specific resource in the firmware's + * resource table, providing information on supported features. + */ +struct fw_rsc_imx_dsp { + uint32_t len; + uint32_t magic_num; + uint32_t version; + uint32_t features; +} __packed; + static const struct imx_rproc_att imx_dsp_rproc_att_imx8qm[] = { /* dev addr , sys addr , size , flags */ { 0x596e8000, 0x556e8000, 0x00008000, ATT_OWN }, @@ -192,9 +226,7 @@ static int imx8mp_dsp_reset(struct imx_dsp_rproc *priv) /* Keep reset asserted for 10 cycles */ usleep_range(1, 2); - regmap_update_bits(priv->regmap, IMX8M_AudioDSP_REG2, - IMX8M_AudioDSP_REG2_RUNSTALL, - IMX8M_AudioDSP_REG2_RUNSTALL); + reset_control_assert(priv->run_stall); /* Take the DSP out of reset and keep stalled for FW loading */ pwrctl = readl(dap + IMX8M_DAP_PWRCTL); @@ -229,60 +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 = { - .src_reg = IMX8M_AudioDSP_REG2, - .src_mask = IMX8M_AudioDSP_REG2_RUNSTALL, - .src_start = 0, - .src_stop = IMX8M_AudioDSP_REG2_RUNSTALL, - .att = imx_dsp_rproc_att_imx8mp, - .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8mp), - .method = IMX_RPROC_MMIO, -}; - -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; @@ -300,6 +278,88 @@ static int imx_dsp_rproc_ready(struct rproc *rproc) return -ETIMEDOUT; } +/** + * imx_dsp_rproc_handle_rsc() - Handle DSP-specific resource table entries + * @rproc: remote processor instance + * @rsc_type: resource type identifier + * @rsc: pointer to the resource entry + * @offset: offset of the resource entry + * @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 + * to signal readiness before proceeding with execution. + * + * Return: RSC_HANDLED if processed successfully, RSC_IGNORED otherwise. + */ +static int imx_dsp_rproc_handle_rsc(struct rproc *rproc, u32 rsc_type, + void *rsc, int offset, int avail) +{ + struct imx_dsp_rproc *priv = rproc->priv; + struct fw_rsc_imx_dsp *imx_dsp_rsc = rsc; + struct device *dev = rproc->dev.parent; + + if (!imx_dsp_rsc) { + dev_dbg(dev, "Invalid fw_rsc_imx_dsp.\n"); + return RSC_IGNORED; + } + + /* Make sure resource isn't truncated */ + if (sizeof(struct fw_rsc_imx_dsp) > avail || + sizeof(struct fw_rsc_imx_dsp) != imx_dsp_rsc->len) { + dev_dbg(dev, "Resource fw_rsc_imx_dsp is truncated.\n"); + return RSC_IGNORED; + } + + /* + * If FW_RSC_NXP_S_MAGIC number is not found then + * wait for fw_ready reply (default work flow) + */ + if (imx_dsp_rsc->magic_num != FW_RSC_NXP_S_MAGIC) { + dev_dbg(dev, "Invalid resource table magic number.\n"); + return RSC_IGNORED; + } + + /* + * For now, in struct fw_rsc_imx_dsp, version 0, + * only FEATURE_DONT_WAIT_FW_READY is valid. + * + * When adding new features, please upgrade version. + */ + if (imx_dsp_rsc->version > 0) { + dev_warn(dev, "Unexpected fw_rsc_imx_dsp version %d.\n", + imx_dsp_rsc->version); + return RSC_IGNORED; + } + + if (imx_dsp_rsc->features & FEATURE_DONT_WAIT_FW_READY) + priv->flags &= ~WAIT_FW_READY; + + 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); +} + +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; + + return imx_sc_pm_cpu_start(priv->ipc_handle, IMX_SC_R_DSP, true, rproc->bootaddr); +} + /* * Start function for rproc_ops * @@ -316,29 +376,41 @@ static int imx_dsp_rproc_start(struct rproc *rproc) struct device *dev = rproc->dev.parent; int ret; - 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, - true, - rproc->bootaddr); - break; - default: + if (!dcfg->ops || !dcfg->ops->start) return -EOPNOTSUPP; - } - if (ret) + ret = dcfg->ops->start(rproc); + if (ret) { dev_err(dev, "Failed to enable remote core!\n"); - else - ret = imx_dsp_rproc_ready(rproc); + return ret; + } - return ret; + if (priv->flags & WAIT_FW_READY) + return imx_dsp_rproc_ready(rproc); + + return 0; +} + +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); +} + +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; + + return imx_sc_pm_cpu_start(priv->ipc_handle, IMX_SC_R_DSP, false, rproc->bootaddr); } /* @@ -358,27 +430,18 @@ static int imx_dsp_rproc_stop(struct rproc *rproc) return 0; } - 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, - false, - rproc->bootaddr); - break; - default: + if (!dcfg->ops || !dcfg->ops->stop) return -EOPNOTSUPP; - } - if (ret) + ret = dcfg->ops->stop(rproc); + if (ret) { dev_err(dev, "Failed to stop remote core\n"); - else - priv->flags &= ~REMOTE_IS_READY; + return ret; + } - return ret; + priv->flags &= ~REMOTE_IS_READY; + + return 0; } /** @@ -595,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 */ @@ -630,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"); - return -EINVAL; - } - - if (imx_dsp_rproc_sys_to_da(priv, rmem->base, rmem->size, &da)) { - of_node_put(it.node); + if (imx_dsp_rproc_sys_to_da(priv, res.start, resource_size(&res), &da)) return -EINVAL; - } - cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size); - if (!cpu_addr) { - of_node_put(it.node); - dev_err(dev, "failed to map memory %p\n", &rmem->base); - return -ENOMEM; + 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)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 */ @@ -680,7 +732,6 @@ static int imx_dsp_rproc_prepare(struct rproc *rproc) { struct imx_dsp_rproc *priv = rproc->priv; struct device *dev = rproc->dev.parent; - struct rproc_mem_entry *carveout; int ret; ret = imx_dsp_rproc_add_carveout(priv); @@ -691,16 +742,7 @@ static int imx_dsp_rproc_prepare(struct rproc *rproc) pm_runtime_get_sync(dev); - /* - * 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); - } - - return 0; + return 0; } /* Unprepare function for rproc_ops */ @@ -708,7 +750,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 */ @@ -928,14 +970,41 @@ static int imx_dsp_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw return 0; } +static int imx_dsp_rproc_load(struct rproc *rproc, const struct firmware *fw) +{ + struct imx_dsp_rproc *priv = rproc->priv; + const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; + struct rproc_mem_entry *carveout; + int ret; + + /* Reset DSP if needed */ + if (dsp_dcfg->reset) + dsp_dcfg->reset(priv); + /* + * 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); + } + + ret = imx_dsp_rproc_elf_load_segments(rproc, fw); + if (ret) + return ret; + + return 0; +} + static const struct rproc_ops imx_dsp_rproc_ops = { .prepare = imx_dsp_rproc_prepare, .unprepare = imx_dsp_rproc_unprepare, .start = imx_dsp_rproc_start, .stop = imx_dsp_rproc_stop, .kick = imx_dsp_rproc_kick, - .load = imx_dsp_rproc_elf_load_segments, + .load = imx_dsp_rproc_load, .parse_fw = imx_dsp_rproc_parse_fw, + .handle_rsc = imx_dsp_rproc_handle_rsc, .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, .sanity_check = rproc_elf_sanity_check, .get_boot_addr = rproc_elf_get_boot_addr, @@ -951,14 +1020,50 @@ 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); +} + +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; +} + +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; + + return imx_scu_get_handle(&priv->ipc_handle); } /** @@ -976,31 +1081,12 @@ 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; - struct device *dev = priv->rproc->dev.parent; - struct regmap *regmap; - int ret = 0; - - 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_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); - } + const struct imx_rproc_dcfg *dcfg = dsp_dcfg->dcfg; - priv->regmap = regmap; - break; - default: - ret = -EOPNOTSUPP; - break; - } + if (dcfg->ops && dcfg->ops->detect_mode) + return dcfg->ops->detect_mode(priv->rproc); - return ret; + return -EOPNOTSUPP; } static const char *imx_dsp_clks_names[DSP_RPROC_CLK_MAX] = { @@ -1034,11 +1120,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)); @@ -1048,6 +1131,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; if (no_mailboxes) imx_dsp_rproc_mbox_init = imx_dsp_rproc_mbox_no_alloc; @@ -1059,50 +1144,28 @@ 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); - 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; - } - - pm_runtime_enable(dev); - - return 0; - -err_detach_domains: - dev_pm_domain_detach_list(priv->pd_list); - - return ret; -} + ret = devm_rproc_add(dev, rproc); + if (ret) + return dev_err_probe(dev, ret, "rproc_add failed\n"); -static void imx_dsp_rproc_remove(struct platform_device *pdev) -{ - struct rproc *rproc = platform_get_drvdata(pdev); - struct imx_dsp_rproc *priv = rproc->priv; + rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_XTENSA); - pm_runtime_disable(&pdev->dev); - rproc_del(rproc); - dev_pm_domain_detach_list(priv->pd_list); + return devm_pm_runtime_enable(dev); } /* pm runtime functions */ @@ -1110,7 +1173,6 @@ static int imx_dsp_runtime_resume(struct device *dev) { struct rproc *rproc = dev_get_drvdata(dev); struct imx_dsp_rproc *priv = rproc->priv; - const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg; int ret; /* @@ -1131,10 +1193,6 @@ static int imx_dsp_runtime_resume(struct device *dev) return ret; } - /* Reset DSP if needed */ - if (dsp_dcfg->reset) - dsp_dcfg->reset(priv); - return 0; } @@ -1247,6 +1305,74 @@ 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, +}; + +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, + .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, + .att_size = ARRAY_SIZE(imx_dsp_rproc_att_imx8mp), + .ops = &imx_dsp_rproc_ops_reset_ctrl, +}; + +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), + .ops = &imx_dsp_rproc_ops_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), + .ops = &imx_dsp_rproc_ops_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), + .ops = &imx_dsp_rproc_ops_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 }, @@ -1258,7 +1384,6 @@ MODULE_DEVICE_TABLE(of, imx_dsp_rproc_of_match); static struct platform_driver imx_dsp_rproc_driver = { .probe = imx_dsp_rproc_probe, - .remove_new = imx_dsp_rproc_remove, .driver = { .name = "imx-dsp-rproc", .of_match_table = imx_dsp_rproc_of_match, |
