diff options
author | Pi-Hsun Shih <pihsun@chromium.org> | 2019-11-12 19:03:26 +0800 |
---|---|---|
committer | Bjorn Andersson <bjorn.andersson@linaro.org> | 2020-01-20 10:29:56 -0800 |
commit | 7017996951fde84698ddfe7fd47f92bd9d9eb85d (patch) | |
tree | ed20cf19e91e293cae1912bcce6186b34f164f23 /drivers/remoteproc | |
parent | 63c13d61eafe4606f1c16c54da40c4eee78e9edf (diff) | |
download | linux-7017996951fde84698ddfe7fd47f92bd9d9eb85d.tar.gz linux-7017996951fde84698ddfe7fd47f92bd9d9eb85d.tar.bz2 linux-7017996951fde84698ddfe7fd47f92bd9d9eb85d.zip |
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/Kconfig | 1 | ||||
-rw-r--r-- | drivers/remoteproc/mtk_common.h | 2 | ||||
-rw-r--r-- | drivers/remoteproc/mtk_scp.c | 61 | ||||
-rw-r--r-- | drivers/remoteproc/mtk_scp_ipi.c | 1 |
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; |