summaryrefslogtreecommitdiff
path: root/drivers/remoteproc
diff options
context:
space:
mode:
authorPi-Hsun Shih <pihsun@chromium.org>2019-11-12 19:03:26 +0800
committerBjorn Andersson <bjorn.andersson@linaro.org>2020-01-20 10:29:56 -0800
commit7017996951fde84698ddfe7fd47f92bd9d9eb85d (patch)
treeed20cf19e91e293cae1912bcce6186b34f164f23 /drivers/remoteproc
parent63c13d61eafe4606f1c16c54da40c4eee78e9edf (diff)
rpmsg: add rpmsg support for mt8183 SCP.
Add a simple rpmsg support for mt8183 SCP, that use IPI / IPC directly. Signed-off-by: Pi-Hsun Shih <pihsun@chromium.org> Link: https://lore.kernel.org/r/20191112110330.179649-4-pihsun@chromium.org Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Diffstat (limited to 'drivers/remoteproc')
-rw-r--r--drivers/remoteproc/Kconfig1
-rw-r--r--drivers/remoteproc/mtk_common.h2
-rw-r--r--drivers/remoteproc/mtk_scp.c61
-rw-r--r--drivers/remoteproc/mtk_scp_ipi.c1
4 files changed, 61 insertions, 4 deletions
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 85d594df12e3..de3862c15fcc 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -26,6 +26,7 @@ config IMX_REMOTEPROC
config MTK_SCP
tristate "Mediatek SCP support"
depends on ARCH_MEDIATEK
+ select RPMSG_MTK_SCP
help
Say y here to support Mediatek's System Companion Processor (SCP) via
the remote processor framework.
diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
index 4afcec19c34c..deb20096146a 100644
--- a/drivers/remoteproc/mtk_common.h
+++ b/drivers/remoteproc/mtk_common.h
@@ -70,6 +70,8 @@ struct mtk_scp {
void __iomem *cpu_addr;
phys_addr_t phys_addr;
size_t dram_size;
+
+ struct rproc_subdev *rpmsg_subdev;
};
/**
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index dc5babb3af59..7ccdf64ff3ea 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/remoteproc.h>
#include <linux/remoteproc/mtk_scp.h>
+#include <linux/rpmsg/mtk_rpmsg.h>
#include "mtk_common.h"
#include "remoteproc_internal.h"
@@ -464,6 +465,54 @@ static void scp_unmap_memory_region(struct mtk_scp *scp)
of_reserved_mem_device_release(scp->dev);
}
+static int scp_register_ipi(struct platform_device *pdev, u32 id,
+ ipi_handler_t handler, void *priv)
+{
+ struct mtk_scp *scp = platform_get_drvdata(pdev);
+
+ return scp_ipi_register(scp, id, handler, priv);
+}
+
+static void scp_unregister_ipi(struct platform_device *pdev, u32 id)
+{
+ struct mtk_scp *scp = platform_get_drvdata(pdev);
+
+ scp_ipi_unregister(scp, id);
+}
+
+static int scp_send_ipi(struct platform_device *pdev, u32 id, void *buf,
+ unsigned int len, unsigned int wait)
+{
+ struct mtk_scp *scp = platform_get_drvdata(pdev);
+
+ return scp_ipi_send(scp, id, buf, len, wait);
+}
+
+static struct mtk_rpmsg_info mtk_scp_rpmsg_info = {
+ .send_ipi = scp_send_ipi,
+ .register_ipi = scp_register_ipi,
+ .unregister_ipi = scp_unregister_ipi,
+ .ns_ipi_id = SCP_IPI_NS_SERVICE,
+};
+
+static void scp_add_rpmsg_subdev(struct mtk_scp *scp)
+{
+ scp->rpmsg_subdev =
+ mtk_rpmsg_create_rproc_subdev(to_platform_device(scp->dev),
+ &mtk_scp_rpmsg_info);
+ if (scp->rpmsg_subdev)
+ rproc_add_subdev(scp->rproc, scp->rpmsg_subdev);
+}
+
+static void scp_remove_rpmsg_subdev(struct mtk_scp *scp)
+{
+ if (scp->rpmsg_subdev) {
+ rproc_remove_subdev(scp->rproc, scp->rpmsg_subdev);
+ mtk_rpmsg_destroy_rproc_subdev(scp->rpmsg_subdev);
+ scp->rpmsg_subdev = NULL;
+ }
+}
+
static int scp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -544,22 +593,25 @@ static int scp_probe(struct platform_device *pdev)
init_waitqueue_head(&scp->run.wq);
init_waitqueue_head(&scp->ack_wq);
+ scp_add_rpmsg_subdev(scp);
+
ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0), NULL,
scp_irq_handler, IRQF_ONESHOT,
pdev->name, scp);
if (ret) {
dev_err(dev, "failed to request irq\n");
- goto unregister_ipi;
+ goto remove_subdev;
}
ret = rproc_add(rproc);
if (ret)
- goto unregister_ipi;
+ goto remove_subdev;
- return ret;
+ return 0;
-unregister_ipi:
+remove_subdev:
+ scp_remove_rpmsg_subdev(scp);
scp_ipi_unregister(scp, SCP_IPI_INIT);
release_dev_mem:
scp_unmap_memory_region(scp);
@@ -579,6 +631,7 @@ static int scp_remove(struct platform_device *pdev)
int i;
rproc_del(scp->rproc);
+ scp_remove_rpmsg_subdev(scp);
scp_ipi_unregister(scp, SCP_IPI_INIT);
scp_unmap_memory_region(scp);
for (i = 0; i < SCP_IPI_MAX; i++)
diff --git a/drivers/remoteproc/mtk_scp_ipi.c b/drivers/remoteproc/mtk_scp_ipi.c
index abdb7944368a..3d3d87210ef2 100644
--- a/drivers/remoteproc/mtk_scp_ipi.c
+++ b/drivers/remoteproc/mtk_scp_ipi.c
@@ -162,6 +162,7 @@ int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf, unsigned int len,
int ret;
if (WARN_ON(id <= SCP_IPI_INIT) || WARN_ON(id >= SCP_IPI_MAX) ||
+ WARN_ON(id == SCP_IPI_NS_SERVICE) ||
WARN_ON(len > sizeof(send_obj->share_buf)) || WARN_ON(!buf))
return -EINVAL;