Commit 70179969 authored by Pi-Hsun Shih's avatar Pi-Hsun Shih Committed by Bjorn Andersson

rpmsg: add rpmsg support for mt8183 SCP.

Add a simple rpmsg support for mt8183 SCP, that use IPI / IPC directly.
Signed-off-by: default avatarPi-Hsun Shih <pihsun@chromium.org>
Link: https://lore.kernel.org/r/20191112110330.179649-4-pihsun@chromium.orgSigned-off-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
parent 63c13d61
......@@ -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.
......
......@@ -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;
};
/**
......
......@@ -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++)
......
......@@ -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;
......
......@@ -15,6 +15,15 @@ config RPMSG_CHAR
in /dev. They make it possible for user-space programs to send and
receive rpmsg packets.
config RPMSG_MTK_SCP
tristate "MediaTek SCP"
depends on MTK_SCP
select RPMSG
help
Say y here to enable support providing communication channels to
remote processors in MediaTek platforms.
This use IPI and IPC to communicate with remote processors.
config RPMSG_QCOM_GLINK_NATIVE
tristate
select RPMSG
......
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_RPMSG) += rpmsg_core.o
obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o
obj-$(CONFIG_RPMSG_MTK_SCP) += mtk_rpmsg.o
obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o
obj-$(CONFIG_RPMSG_QCOM_GLINK_NATIVE) += qcom_glink_native.o
obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o
......
This diff is collapsed.
......@@ -41,7 +41,8 @@ enum scp_ipi_id {
SCP_IPI_ISP_FRAME,
SCP_IPI_FD_CMD,
SCP_IPI_CROS_HOST_CMD,
SCP_IPI_MAX,
SCP_IPI_NS_SERVICE = 0xFF,
SCP_IPI_MAX = 0x100,
};
struct mtk_scp *scp_get(struct platform_device *pdev);
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2019 Google LLC.
*/
#ifndef __LINUX_RPMSG_MTK_RPMSG_H
#define __LINUX_RPMSG_MTK_RPMSG_H
#include <linux/platform_device.h>
#include <linux/remoteproc.h>
typedef void (*ipi_handler_t)(void *data, unsigned int len, void *priv);
/*
* struct mtk_rpmsg_info - IPI functions tied to the rpmsg device.
* @register_ipi: register IPI handler for an IPI id.
* @unregister_ipi: unregister IPI handler for a registered IPI id.
* @send_ipi: send IPI to an IPI id. wait is the timeout (in msecs) to wait
* until response, or 0 if there's no timeout.
* @ns_ipi_id: the IPI id used for name service, or -1 if name service isn't
* supported.
*/
struct mtk_rpmsg_info {
int (*register_ipi)(struct platform_device *pdev, u32 id,
ipi_handler_t handler, void *priv);
void (*unregister_ipi)(struct platform_device *pdev, u32 id);
int (*send_ipi)(struct platform_device *pdev, u32 id,
void *buf, unsigned int len, unsigned int wait);
int ns_ipi_id;
};
struct rproc_subdev *
mtk_rpmsg_create_rproc_subdev(struct platform_device *pdev,
struct mtk_rpmsg_info *info);
void mtk_rpmsg_destroy_rproc_subdev(struct rproc_subdev *subdev);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment