summaryrefslogtreecommitdiff
path: root/drivers/remoteproc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/remoteproc')
-rw-r--r--drivers/remoteproc/imx_rproc.c4
-rw-r--r--drivers/remoteproc/mtk_scp.c12
-rw-r--r--drivers/remoteproc/omap_remoteproc.c17
-rw-r--r--drivers/remoteproc/qcom_q6v5_mss.c21
-rw-r--r--drivers/remoteproc/qcom_q6v5_pas.c13
-rw-r--r--drivers/remoteproc/qcom_wcnss.c34
-rw-r--r--drivers/remoteproc/qcom_wcnss_iris.c2
-rw-r--r--drivers/remoteproc/remoteproc_core.c21
-rw-r--r--drivers/remoteproc/ti_k3_dsp_remoteproc.c14
-rw-r--r--drivers/remoteproc/ti_k3_m4_remoteproc.c8
-rw-r--r--drivers/remoteproc/ti_k3_r5_remoteproc.c188
-rw-r--r--drivers/remoteproc/xlnx_r5_remoteproc.c2
12 files changed, 186 insertions, 150 deletions
diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 800015ff7ff9..cc3f5b7fe9dd 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -1029,8 +1029,8 @@ static int imx_rproc_clk_enable(struct imx_rproc *priv)
struct device *dev = priv->dev;
int ret;
- /* Remote core is not under control of Linux */
- if (dcfg->method == IMX_RPROC_NONE)
+ /* 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);
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index e744c07507ee..f98a11d4cf29 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -1326,6 +1326,11 @@ static int scp_cluster_init(struct platform_device *pdev, struct mtk_scp_of_clus
return ret;
}
+static const struct of_device_id scp_core_match[] = {
+ { .compatible = "mediatek,scp-core" },
+ {}
+};
+
static int scp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1357,13 +1362,15 @@ static int scp_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&scp_cluster->mtk_scp_list);
mutex_init(&scp_cluster->cluster_lock);
- ret = devm_of_platform_populate(dev);
+ ret = of_platform_populate(dev_of_node(dev), scp_core_match, NULL, dev);
if (ret)
return dev_err_probe(dev, ret, "Failed to populate platform devices\n");
ret = scp_cluster_init(pdev, scp_cluster);
- if (ret)
+ if (ret) {
+ of_platform_depopulate(dev);
return ret;
+ }
return 0;
}
@@ -1379,6 +1386,7 @@ static void scp_remove(struct platform_device *pdev)
rproc_del(scp->rproc);
scp_free(scp);
}
+ of_platform_depopulate(&pdev->dev);
mutex_destroy(&scp_cluster->cluster_lock);
}
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
index 9ae2e831456d..3260dd512491 100644
--- a/drivers/remoteproc/omap_remoteproc.c
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -37,6 +37,10 @@
#include <linux/platform_data/dmtimer-omap.h>
+#ifdef CONFIG_ARM_DMA_USE_IOMMU
+#include <asm/dma-iommu.h>
+#endif
+
#include "omap_remoteproc.h"
#include "remoteproc_internal.h"
@@ -1323,6 +1327,19 @@ static int omap_rproc_probe(struct platform_device *pdev)
/* All existing OMAP IPU and DSP processors have an MMU */
rproc->has_iommu = true;
+#ifdef CONFIG_ARM_DMA_USE_IOMMU
+ /*
+ * Throw away the ARM DMA mapping that we'll never use, so it doesn't
+ * interfere with the core rproc->domain and we get the right DMA ops.
+ */
+ if (pdev->dev.archdata.mapping) {
+ struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(&pdev->dev);
+
+ arm_iommu_detach_device(&pdev->dev);
+ arm_iommu_release_mapping(mapping);
+ }
+#endif
+
ret = omap_rproc_of_get_internal_memories(pdev, rproc);
if (ret)
return ret;
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index 32c3531b20c7..e19081d53022 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -1839,6 +1839,13 @@ static int q6v5_pds_attach(struct device *dev, struct device **devs,
while (pd_names[num_pds])
num_pds++;
+ /* Handle single power domain */
+ if (num_pds == 1 && dev->pm_domain) {
+ devs[0] = dev;
+ pm_runtime_enable(dev);
+ return 1;
+ }
+
for (i = 0; i < num_pds; i++) {
devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
if (IS_ERR_OR_NULL(devs[i])) {
@@ -1859,8 +1866,15 @@ unroll_attach:
static void q6v5_pds_detach(struct q6v5 *qproc, struct device **pds,
size_t pd_count)
{
+ struct device *dev = qproc->dev;
int i;
+ /* Handle single power domain */
+ if (pd_count == 1 && dev->pm_domain) {
+ pm_runtime_disable(dev);
+ return;
+ }
+
for (i = 0; i < pd_count; i++)
dev_pm_domain_detach(pds[i], false);
}
@@ -2469,13 +2483,13 @@ static const struct rproc_hexagon_res msm8974_mss = {
.supply = "pll",
.uA = 100000,
},
- {}
- },
- .fallback_proxy_supply = (struct qcom_mss_reg_res[]) {
{
.supply = "mx",
.uV = 1050000,
},
+ {}
+ },
+ .fallback_proxy_supply = (struct qcom_mss_reg_res[]) {
{
.supply = "cx",
.uA = 100000,
@@ -2501,7 +2515,6 @@ static const struct rproc_hexagon_res msm8974_mss = {
NULL
},
.proxy_pd_names = (char*[]){
- "mx",
"cx",
NULL
},
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index 1a2d08ec9de9..ea4a91f37b50 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -509,16 +509,16 @@ static int adsp_pds_attach(struct device *dev, struct device **devs,
if (!pd_names)
return 0;
+ while (pd_names[num_pds])
+ num_pds++;
+
/* Handle single power domain */
- if (dev->pm_domain) {
+ if (num_pds == 1 && dev->pm_domain) {
devs[0] = dev;
pm_runtime_enable(dev);
return 1;
}
- while (pd_names[num_pds])
- num_pds++;
-
for (i = 0; i < num_pds; i++) {
devs[i] = dev_pm_domain_attach_by_name(dev, pd_names[i]);
if (IS_ERR_OR_NULL(devs[i])) {
@@ -543,7 +543,7 @@ static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds,
int i;
/* Handle single power domain */
- if (dev->pm_domain && pd_count) {
+ if (pd_count == 1 && dev->pm_domain) {
pm_runtime_disable(dev);
return;
}
@@ -1356,6 +1356,7 @@ static const struct adsp_data sc7280_wpss_resource = {
.crash_reason_smem = 626,
.firmware_name = "wpss.mdt",
.pas_id = 6,
+ .minidump_id = 4,
.auto_boot = false,
.proxy_pd_names = (char*[]){
"cx",
@@ -1418,7 +1419,7 @@ static const struct adsp_data sm8650_mpss_resource = {
};
static const struct of_device_id adsp_of_match[] = {
- { .compatible = "qcom,msm8226-adsp-pil", .data = &adsp_resource_init},
+ { .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,msm8996-adsp-pil", .data = &msm8996_adsp_resource},
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index a7bb9da27029..a2ae6adf0053 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -117,10 +117,10 @@ static const struct wcnss_data pronto_v1_data = {
.pmu_offset = 0x1004,
.spare_offset = 0x1088,
- .pd_names = { "mx", "cx" },
+ .pd_names = { "cx", "mx" },
.vregs = (struct wcnss_vreg_info[]) {
- { "vddmx", 950000, 1150000, 0 },
{ "vddcx", .super_turbo = true},
+ { "vddmx", 950000, 1150000, 0 },
{ "vddpx", 1800000, 1800000, 0 },
},
.num_pd_vregs = 2,
@@ -131,10 +131,10 @@ static const struct wcnss_data pronto_v2_data = {
.pmu_offset = 0x1004,
.spare_offset = 0x1088,
- .pd_names = { "mx", "cx" },
+ .pd_names = { "cx", "mx" },
.vregs = (struct wcnss_vreg_info[]) {
- { "vddmx", 1287500, 1287500, 0 },
{ "vddcx", .super_turbo = true },
+ { "vddmx", 1287500, 1287500, 0 },
{ "vddpx", 1800000, 1800000, 0 },
},
.num_pd_vregs = 2,
@@ -397,8 +397,17 @@ static irqreturn_t wcnss_stop_ack_interrupt(int irq, void *dev)
static int wcnss_init_pds(struct qcom_wcnss *wcnss,
const char * const pd_names[WCNSS_MAX_PDS])
{
+ struct device *dev = wcnss->dev;
int i, ret;
+ /* Handle single power domain */
+ if (dev->pm_domain) {
+ wcnss->pds[0] = dev;
+ wcnss->num_pds = 1;
+ pm_runtime_enable(dev);
+ return 0;
+ }
+
for (i = 0; i < WCNSS_MAX_PDS; i++) {
if (!pd_names[i])
break;
@@ -418,8 +427,15 @@ static int wcnss_init_pds(struct qcom_wcnss *wcnss,
static void wcnss_release_pds(struct qcom_wcnss *wcnss)
{
+ struct device *dev = wcnss->dev;
int i;
+ /* Handle single power domain */
+ if (wcnss->num_pds == 1 && dev->pm_domain) {
+ pm_runtime_disable(dev);
+ return;
+ }
+
for (i = 0; i < wcnss->num_pds; i++)
dev_pm_domain_detach(wcnss->pds[i], false);
}
@@ -437,10 +453,14 @@ static int wcnss_init_regulators(struct qcom_wcnss *wcnss,
* the regulators for the power domains. For old device trees we need to
* reserve extra space to manage them through the regulator interface.
*/
- if (wcnss->num_pds)
- info += num_pd_vregs;
- else
+ if (wcnss->num_pds) {
+ info += wcnss->num_pds;
+ /* Handle single power domain case */
+ if (wcnss->num_pds < num_pd_vregs)
+ num_vregs += num_pd_vregs - wcnss->num_pds;
+ } else {
num_vregs += num_pd_vregs;
+ }
bulk = devm_kcalloc(wcnss->dev,
num_vregs, sizeof(struct regulator_bulk_data),
diff --git a/drivers/remoteproc/qcom_wcnss_iris.c b/drivers/remoteproc/qcom_wcnss_iris.c
index dd36fd077911..1e197f773474 100644
--- a/drivers/remoteproc/qcom_wcnss_iris.c
+++ b/drivers/remoteproc/qcom_wcnss_iris.c
@@ -197,6 +197,7 @@ struct qcom_iris *qcom_iris_probe(struct device *parent, bool *use_48mhz_xo)
err_device_del:
device_del(&iris->dev);
+ put_device(&iris->dev);
return ERR_PTR(ret);
}
@@ -204,4 +205,5 @@ err_device_del:
void qcom_iris_remove(struct qcom_iris *iris)
{
device_del(&iris->dev);
+ put_device(&iris->dev);
}
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index f276956f2c5c..b7011eb384a5 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1617,7 +1617,7 @@ static int rproc_attach(struct rproc *rproc)
ret = rproc_set_rsc_table(rproc);
if (ret) {
dev_err(dev, "can't load resource table: %d\n", ret);
- goto unprepare_device;
+ goto clean_up_resources;
}
/* reset max_notifyid */
@@ -1634,7 +1634,7 @@ static int rproc_attach(struct rproc *rproc)
ret = rproc_handle_resources(rproc, rproc_loading_handlers);
if (ret) {
dev_err(dev, "Failed to process resources: %d\n", ret);
- goto unprepare_device;
+ goto clean_up_resources;
}
/* Allocate carveout resources associated to rproc */
@@ -1653,9 +1653,9 @@ static int rproc_attach(struct rproc *rproc)
clean_up_resources:
rproc_resource_cleanup(rproc);
-unprepare_device:
/* release HW resources if needed */
rproc_unprepare_device(rproc);
+ kfree(rproc->clean_table);
disable_iommu:
rproc_disable_iommu(rproc);
return ret;
@@ -2025,6 +2025,7 @@ int rproc_shutdown(struct rproc *rproc)
kfree(rproc->cached_table);
rproc->cached_table = NULL;
rproc->table_ptr = NULL;
+ rproc->table_sz = 0;
out:
mutex_unlock(&rproc->lock);
return ret;
@@ -2486,6 +2487,13 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
rproc->dev.driver_data = rproc;
idr_init(&rproc->notifyids);
+ /* Assign a unique device index and name */
+ rproc->index = ida_alloc(&rproc_dev_index, GFP_KERNEL);
+ if (rproc->index < 0) {
+ dev_err(dev, "ida_alloc failed: %d\n", rproc->index);
+ goto put_device;
+ }
+
rproc->name = kstrdup_const(name, GFP_KERNEL);
if (!rproc->name)
goto put_device;
@@ -2496,13 +2504,6 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
if (rproc_alloc_ops(rproc, ops))
goto put_device;
- /* Assign a unique device index and name */
- rproc->index = ida_alloc(&rproc_dev_index, GFP_KERNEL);
- if (rproc->index < 0) {
- dev_err(dev, "ida_alloc failed: %d\n", rproc->index);
- goto put_device;
- }
-
dev_set_name(&rproc->dev, "remoteproc%d", rproc->index);
atomic_set(&rproc->power, 0);
diff --git a/drivers/remoteproc/ti_k3_dsp_remoteproc.c b/drivers/remoteproc/ti_k3_dsp_remoteproc.c
index 8be3f631c192..73be3d216791 100644
--- a/drivers/remoteproc/ti_k3_dsp_remoteproc.c
+++ b/drivers/remoteproc/ti_k3_dsp_remoteproc.c
@@ -115,10 +115,6 @@ static void k3_dsp_rproc_mbox_callback(struct mbox_client *client, void *data)
const char *name = kproc->rproc->name;
u32 msg = omap_mbox_message(data);
- /* Do not forward messages from a detached core */
- if (kproc->rproc->state == RPROC_DETACHED)
- return;
-
dev_dbg(dev, "mbox msg: 0x%x\n", msg);
switch (msg) {
@@ -159,10 +155,6 @@ static void k3_dsp_rproc_kick(struct rproc *rproc, int vqid)
mbox_msg_t msg = (mbox_msg_t)vqid;
int ret;
- /* Do not forward messages to a detached core */
- if (kproc->rproc->state == RPROC_DETACHED)
- return;
-
/* send the index of the triggered virtqueue in the mailbox payload */
ret = mbox_send_message(kproc->mbox, (void *)msg);
if (ret < 0)
@@ -576,11 +568,9 @@ static int k3_dsp_reserved_mem_init(struct k3_dsp_rproc *kproc)
return -EINVAL;
rmem = of_reserved_mem_lookup(rmem_np);
- if (!rmem) {
- of_node_put(rmem_np);
- return -EINVAL;
- }
of_node_put(rmem_np);
+ if (!rmem)
+ return -EINVAL;
kproc->rmem[i].bus_addr = rmem->base;
/* 64-bit address regions currently not supported */
diff --git a/drivers/remoteproc/ti_k3_m4_remoteproc.c b/drivers/remoteproc/ti_k3_m4_remoteproc.c
index 09f0484a90e1..6cd50b16a8e8 100644
--- a/drivers/remoteproc/ti_k3_m4_remoteproc.c
+++ b/drivers/remoteproc/ti_k3_m4_remoteproc.c
@@ -228,7 +228,7 @@ static int k3_m4_rproc_unprepare(struct rproc *rproc)
int ret;
/* If the core is going to be detached do not assert the module reset */
- if (rproc->state == RPROC_ATTACHED)
+ if (rproc->state == RPROC_DETACHED)
return 0;
ret = kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci,
@@ -433,11 +433,9 @@ static int k3_m4_reserved_mem_init(struct k3_m4_rproc *kproc)
return -EINVAL;
rmem = of_reserved_mem_lookup(rmem_np);
- if (!rmem) {
- of_node_put(rmem_np);
- return -EINVAL;
- }
of_node_put(rmem_np);
+ if (!rmem)
+ return -EINVAL;
kproc->rmem[i].bus_addr = rmem->base;
/* 64-bit address regions currently not supported */
diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c
index 747ee467da88..941bb130c85c 100644
--- a/drivers/remoteproc/ti_k3_r5_remoteproc.c
+++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c
@@ -194,10 +194,6 @@ static void k3_r5_rproc_mbox_callback(struct mbox_client *client, void *data)
const char *name = kproc->rproc->name;
u32 msg = omap_mbox_message(data);
- /* Do not forward message from a detached core */
- if (kproc->rproc->state == RPROC_DETACHED)
- return;
-
dev_dbg(dev, "mbox msg: 0x%x\n", msg);
switch (msg) {
@@ -233,10 +229,6 @@ static void k3_r5_rproc_kick(struct rproc *rproc, int vqid)
mbox_msg_t msg = (mbox_msg_t)vqid;
int ret;
- /* Do not forward message to a detached core */
- if (kproc->rproc->state == RPROC_DETACHED)
- return;
-
/* send the index of the triggered virtqueue in the mailbox payload */
ret = mbox_send_message(kproc->mbox, (void *)msg);
if (ret < 0)
@@ -448,13 +440,36 @@ static int k3_r5_rproc_prepare(struct rproc *rproc)
{
struct k3_r5_rproc *kproc = rproc->priv;
struct k3_r5_cluster *cluster = kproc->cluster;
- struct k3_r5_core *core = kproc->core;
+ struct k3_r5_core *core = kproc->core, *core0, *core1;
struct device *dev = kproc->dev;
u32 ctrl = 0, cfg = 0, stat = 0;
u64 boot_vec = 0;
bool mem_init_dis;
int ret;
+ /*
+ * R5 cores require to be powered on sequentially, core0 should be in
+ * higher power state than core1 in a cluster. So, wait for core0 to
+ * power up before proceeding to core1 and put timeout of 2sec. This
+ * waiting mechanism is necessary because rproc_auto_boot_callback() for
+ * core1 can be called before core0 due to thread execution order.
+ *
+ * By placing the wait mechanism here in .prepare() ops, this condition
+ * is enforced for rproc boot requests from sysfs as well.
+ */
+ core0 = list_first_entry(&cluster->cores, struct k3_r5_core, elem);
+ core1 = list_last_entry(&cluster->cores, struct k3_r5_core, elem);
+ if (cluster->mode == CLUSTER_MODE_SPLIT && core == core1 &&
+ !core0->released_from_reset) {
+ ret = wait_event_interruptible_timeout(cluster->core_transition,
+ core0->released_from_reset,
+ msecs_to_jiffies(2000));
+ if (ret <= 0) {
+ dev_err(dev, "can not power up core1 before core0");
+ return -EPERM;
+ }
+ }
+
ret = ti_sci_proc_get_status(core->tsp, &boot_vec, &cfg, &ctrl, &stat);
if (ret < 0)
return ret;
@@ -471,6 +486,14 @@ static int k3_r5_rproc_prepare(struct rproc *rproc)
}
/*
+ * Notify all threads in the wait queue when core0 state has changed so
+ * that threads waiting for this condition can be executed.
+ */
+ core->released_from_reset = true;
+ if (core == core0)
+ wake_up_interruptible(&cluster->core_transition);
+
+ /*
* Newer IP revisions like on J7200 SoCs support h/w auto-initialization
* of TCMs, so there is no need to perform the s/w memzero. This bit is
* configurable through System Firmware, the default value does perform
@@ -515,10 +538,30 @@ static int k3_r5_rproc_unprepare(struct rproc *rproc)
{
struct k3_r5_rproc *kproc = rproc->priv;
struct k3_r5_cluster *cluster = kproc->cluster;
- struct k3_r5_core *core = kproc->core;
+ struct k3_r5_core *core = kproc->core, *core0, *core1;
struct device *dev = kproc->dev;
int ret;
+ /*
+ * Ensure power-down of cores is sequential in split mode. Core1 must
+ * power down before Core0 to maintain the expected state. By placing
+ * the wait mechanism here in .unprepare() ops, this condition is
+ * enforced for rproc stop or shutdown requests from sysfs and device
+ * removal as well.
+ */
+ core0 = list_first_entry(&cluster->cores, struct k3_r5_core, elem);
+ core1 = list_last_entry(&cluster->cores, struct k3_r5_core, elem);
+ if (cluster->mode == CLUSTER_MODE_SPLIT && core == core0 &&
+ core1->released_from_reset) {
+ ret = wait_event_interruptible_timeout(cluster->core_transition,
+ !core1->released_from_reset,
+ msecs_to_jiffies(2000));
+ if (ret <= 0) {
+ dev_err(dev, "can not power down core0 before core1");
+ return -EPERM;
+ }
+ }
+
/* Re-use LockStep-mode reset logic for Single-CPU mode */
ret = (cluster->mode == CLUSTER_MODE_LOCKSTEP ||
cluster->mode == CLUSTER_MODE_SINGLECPU) ?
@@ -526,6 +569,14 @@ static int k3_r5_rproc_unprepare(struct rproc *rproc)
if (ret)
dev_err(dev, "unable to disable cores, ret = %d\n", ret);
+ /*
+ * Notify all threads in the wait queue when core1 state has changed so
+ * that threads waiting for this condition can be executed.
+ */
+ core->released_from_reset = false;
+ if (core == core1)
+ wake_up_interruptible(&cluster->core_transition);
+
return ret;
}
@@ -551,7 +602,7 @@ static int k3_r5_rproc_start(struct rproc *rproc)
struct k3_r5_rproc *kproc = rproc->priv;
struct k3_r5_cluster *cluster = kproc->cluster;
struct device *dev = kproc->dev;
- struct k3_r5_core *core0, *core;
+ struct k3_r5_core *core;
u32 boot_addr;
int ret;
@@ -573,21 +624,9 @@ static int k3_r5_rproc_start(struct rproc *rproc)
goto unroll_core_run;
}
} else {
- /* do not allow core 1 to start before core 0 */
- core0 = list_first_entry(&cluster->cores, struct k3_r5_core,
- elem);
- if (core != core0 && core0->rproc->state == RPROC_OFFLINE) {
- dev_err(dev, "%s: can not start core 1 before core 0\n",
- __func__);
- return -EPERM;
- }
-
ret = k3_r5_core_run(core);
if (ret)
return ret;
-
- core->released_from_reset = true;
- wake_up_interruptible(&cluster->core_transition);
}
return 0;
@@ -628,8 +667,7 @@ static int k3_r5_rproc_stop(struct rproc *rproc)
{
struct k3_r5_rproc *kproc = rproc->priv;
struct k3_r5_cluster *cluster = kproc->cluster;
- struct device *dev = kproc->dev;
- struct k3_r5_core *core1, *core = kproc->core;
+ struct k3_r5_core *core = kproc->core;
int ret;
/* halt all applicable cores */
@@ -642,16 +680,6 @@ static int k3_r5_rproc_stop(struct rproc *rproc)
}
}
} else {
- /* do not allow core 0 to stop before core 1 */
- core1 = list_last_entry(&cluster->cores, struct k3_r5_core,
- elem);
- if (core != core1 && core1->rproc->state != RPROC_OFFLINE) {
- dev_err(dev, "%s: can not stop core 0 before core 1\n",
- __func__);
- ret = -EPERM;
- goto out;
- }
-
ret = k3_r5_core_halt(core);
if (ret)
goto out;
@@ -955,6 +983,13 @@ out:
return ret;
}
+static void k3_r5_mem_release(void *data)
+{
+ struct device *dev = data;
+
+ of_reserved_mem_device_release(dev);
+}
+
static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
{
struct device *dev = kproc->dev;
@@ -985,28 +1020,25 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
return ret;
}
+ ret = devm_add_action_or_reset(dev, k3_r5_mem_release, dev);
+ if (ret)
+ return ret;
+
num_rmems--;
- kproc->rmem = kcalloc(num_rmems, sizeof(*kproc->rmem), GFP_KERNEL);
- if (!kproc->rmem) {
- ret = -ENOMEM;
- goto release_rmem;
- }
+ kproc->rmem = devm_kcalloc(dev, num_rmems, sizeof(*kproc->rmem), GFP_KERNEL);
+ if (!kproc->rmem)
+ return -ENOMEM;
/* 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) {
- ret = -EINVAL;
- goto unmap_rmem;
- }
+ if (!rmem_np)
+ return -EINVAL;
rmem = of_reserved_mem_lookup(rmem_np);
- if (!rmem) {
- of_node_put(rmem_np);
- ret = -EINVAL;
- goto unmap_rmem;
- }
of_node_put(rmem_np);
+ if (!rmem)
+ return -EINVAL;
kproc->rmem[i].bus_addr = rmem->base;
/*
@@ -1021,12 +1053,11 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
*/
kproc->rmem[i].dev_addr = (u32)rmem->base;
kproc->rmem[i].size = rmem->size;
- kproc->rmem[i].cpu_addr = ioremap_wc(rmem->base, rmem->size);
+ kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size);
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);
- ret = -ENOMEM;
- goto unmap_rmem;
+ return -ENOMEM;
}
dev_dbg(dev, "reserved memory%d: bus addr %pa size 0x%zx va %pK da 0x%x\n",
@@ -1037,25 +1068,6 @@ static int k3_r5_reserved_mem_init(struct k3_r5_rproc *kproc)
kproc->num_rmems = num_rmems;
return 0;
-
-unmap_rmem:
- for (i--; i >= 0; i--)
- iounmap(kproc->rmem[i].cpu_addr);
- kfree(kproc->rmem);
-release_rmem:
- of_reserved_mem_device_release(dev);
- return ret;
-}
-
-static void k3_r5_reserved_mem_exit(struct k3_r5_rproc *kproc)
-{
- int i;
-
- for (i = 0; i < kproc->num_rmems; i++)
- iounmap(kproc->rmem[i].cpu_addr);
- kfree(kproc->rmem);
-
- of_reserved_mem_device_release(kproc->dev);
}
/*
@@ -1282,10 +1294,10 @@ init_rmem:
goto out;
}
- ret = rproc_add(rproc);
+ ret = devm_rproc_add(dev, rproc);
if (ret) {
- dev_err(dev, "rproc_add failed, ret = %d\n", ret);
- goto err_add;
+ dev_err_probe(dev, ret, "rproc_add failed\n");
+ goto out;
}
/* create only one rproc in lockstep, single-cpu or
@@ -1295,26 +1307,6 @@ init_rmem:
cluster->mode == CLUSTER_MODE_SINGLECPU ||
cluster->mode == CLUSTER_MODE_SINGLECORE)
break;
-
- /*
- * R5 cores require to be powered on sequentially, core0
- * should be in higher power state than core1 in a cluster
- * So, wait for current core to power up before proceeding
- * to next core and put timeout of 2sec for each core.
- *
- * This waiting mechanism is necessary because
- * rproc_auto_boot_callback() for core1 can be called before
- * core0 due to thread execution order.
- */
- ret = wait_event_interruptible_timeout(cluster->core_transition,
- core->released_from_reset,
- msecs_to_jiffies(2000));
- if (ret <= 0) {
- dev_err(dev,
- "Timed out waiting for %s core to power up!\n",
- rproc->name);
- goto err_powerup;
- }
}
return 0;
@@ -1329,10 +1321,6 @@ err_split:
}
}
-err_powerup:
- rproc_del(rproc);
-err_add:
- k3_r5_reserved_mem_exit(kproc);
out:
/* undo core0 upon any failures on core1 in split-mode */
if (cluster->mode == CLUSTER_MODE_SPLIT && core == core1) {
@@ -1375,10 +1363,6 @@ static void k3_r5_cluster_rproc_exit(void *data)
}
mbox_free_channel(kproc->mbox);
-
- rproc_del(rproc);
-
- k3_r5_reserved_mem_exit(kproc);
}
}
diff --git a/drivers/remoteproc/xlnx_r5_remoteproc.c b/drivers/remoteproc/xlnx_r5_remoteproc.c
index 5aeedeaf3c41..c165422d0651 100644
--- a/drivers/remoteproc/xlnx_r5_remoteproc.c
+++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
@@ -906,6 +906,8 @@ static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
rproc_coredump_set_elf_info(r5_rproc, ELFCLASS32, EM_ARM);
+ r5_rproc->recovery_disabled = true;
+ r5_rproc->has_iommu = false;
r5_rproc->auto_boot = false;
r5_core = r5_rproc->priv;
r5_core->dev = cdev;