summaryrefslogtreecommitdiff
path: root/drivers/remoteproc/imx_dsp_rproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/remoteproc/imx_dsp_rproc.c')
-rw-r--r--drivers/remoteproc/imx_dsp_rproc.c541
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,