Add VCP ipi-mbox init driver.

Signed-off-by: Xiangzhi Tang <[email protected]>
---
 drivers/remoteproc/Kconfig                |  2 +
 drivers/remoteproc/mtk_vcp_rproc.c        | 98 +++++++++++++++++++++++
 drivers/remoteproc/mtk_vcp_rproc.h        |  6 ++
 include/linux/remoteproc/mtk_vcp_public.h | 55 +++++++++++++
 4 files changed, 161 insertions(+)

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 93827f6fd3c5..54b416db0c0b 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -70,6 +70,8 @@ config MTK_VCP_RPROC
        tristate "MediaTek VCP support"
        depends on ARCH_MEDIATEK || COMPILE_TEST
        depends on ARCH_DMA_ADDR_T_64BIT
+       select MTK_VCP_IPC
+       select MTK_VCP_MBOX
        help
          Say y here to support MediaTek's Video Companion Processor (VCP) via
          the remote processor framework.
diff --git a/drivers/remoteproc/mtk_vcp_rproc.c 
b/drivers/remoteproc/mtk_vcp_rproc.c
index bcb5f3786cf7..6e0fecef72ce 100644
--- a/drivers/remoteproc/mtk_vcp_rproc.c
+++ b/drivers/remoteproc/mtk_vcp_rproc.c
@@ -5,6 +5,7 @@
 
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/iopoll.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
@@ -54,6 +55,18 @@ void vcp_put(struct mtk_vcp_device *vcp)
 }
 EXPORT_SYMBOL_GPL(vcp_put);
 
+/**
+ * vcp_get_ipidev() - get a vcp ipi device struct to reference vcp ipi.
+ *
+ * @vcp: mtk_vcp_device structure from vcp_get().
+ *
+ **/
+struct mtk_ipi_device *vcp_get_ipidev(struct mtk_vcp_device *vcp)
+{
+       return vcp->ipi_dev;
+}
+EXPORT_SYMBOL_GPL(vcp_get_ipidev);
+
 static int mtk_vcp_start(struct rproc *rproc)
 {
        struct mtk_vcp_device *vcp = (struct mtk_vcp_device *)rproc->priv;
@@ -93,6 +106,34 @@ static const struct rproc_ops mtk_vcp_ops = {
        .stop           = mtk_vcp_stop,
 };
 
+static int vcp_ipi_mbox_init(struct mtk_vcp_device *vcp)
+{
+       struct mtk_vcp_ipc *vcp_ipc;
+       struct platform_device *pdev;
+       int ret;
+
+       pdev = platform_device_register_data(vcp->dev, "mtk-vcp-ipc",
+                                            PLATFORM_DEVID_NONE,
+                                            vcp->platdata->ipc_data,
+                                            sizeof(struct mtk_mbox_table));
+       if (IS_ERR(pdev))
+               return dev_err_probe(vcp->dev, PTR_ERR(pdev), "ipc_data 
register failed\n");
+
+       ret = read_poll_timeout_atomic(dev_get_drvdata,
+                                      vcp_ipc, vcp_ipc,
+                                      USEC_PER_MSEC,
+                                      VCP_IPI_DEV_READY_TIMEOUT * 
USEC_PER_MSEC,
+                                      false, &pdev->dev);
+       if (ret)
+               return dev_err_probe(vcp->dev, -EPROBE_DEFER, "get vcp_ipc 
drvdata failed\n");
+
+       ret = mtk_vcp_ipc_device_register(vcp->ipi_dev, VCP_IPI_COUNT, vcp_ipc);
+       if (ret)
+               dev_err_probe(vcp->dev, ret, "ipi_dev register failed, ret 
%d\n", ret);
+
+       return ret;
+}
+
 static int vcp_multi_core_init(struct platform_device *pdev,
                               struct mtk_vcp_of_cluster *vcp_cluster,
                               enum vcp_core_id core_id)
@@ -138,7 +179,9 @@ static struct mtk_vcp_device *vcp_rproc_init(struct 
platform_device *pdev,
        vcp->dev = dev;
        vcp->ops = &vcp_of_data->ops;
        vcp->platdata = &vcp_of_data->platdata;
+       vcp->ipi_ops = vcp_of_data->platdata.ipi_ops;
        vcp->vcp_cluster = vcp_cluster;
+       vcp->ipi_dev = &vcp_cluster->vcp_ipidev;
 
        rproc->auto_boot = vcp_of_data->platdata.auto_boot;
        rproc->sysfs_read_only = vcp_of_data->platdata.sysfs_read_only;
@@ -166,6 +209,10 @@ static struct mtk_vcp_device *vcp_rproc_init(struct 
platform_device *pdev,
        if (ret)
                return ERR_PTR(dev_err_probe(dev, ret, "vcp_wdt_irq_init 
failed\n"));
 
+       ret = vcp_ipi_mbox_init(vcp);
+       if (ret)
+               return ERR_PTR(dev_err_probe(dev, ret, "vcp_ipi_mbox_init 
failed\n"));
+
        pm_runtime_get_sync(dev);
 
        return vcp;
@@ -284,6 +331,55 @@ static struct mtk_vcp_reserved_mem_table 
mt8196_memory_tb[NUMS_MEM_ID] = {
        { .memory_id = MMQOS_MEM_ID,        .size = 0x1000 },
 };
 
+static struct mtk_mbox_table mt8196_ipc_tb = {
+       .send_table = {
+               { .msg_size = 18, .ipi_id =  0, .mbox_id = 0 },
+
+               { .msg_size =  8, .ipi_id = 15, .mbox_id = 1 },
+               { .msg_size = 18, .ipi_id = 16, .mbox_id = 1 },
+               { .msg_size =  2, .ipi_id =  9, .mbox_id = 1 },
+
+               { .msg_size = 18, .ipi_id = 11, .mbox_id = 2 },
+               { .msg_size =  2, .ipi_id =  2, .mbox_id = 2 },
+               { .msg_size =  3, .ipi_id =  3, .mbox_id = 2 },
+               { .msg_size =  2, .ipi_id = 32, .mbox_id = 2 },
+
+               { .msg_size =  2, .ipi_id = 33, .mbox_id = 3 },
+               { .msg_size =  2, .ipi_id = 13, .mbox_id = 3 },
+               { .msg_size =  2, .ipi_id = 35, .mbox_id = 3 },
+
+               { .msg_size =  2, .ipi_id = 20, .mbox_id = 4 },
+               { .msg_size =  3, .ipi_id = 21, .mbox_id = 4 },
+               { .msg_size =  2, .ipi_id = 23, .mbox_id = 4 }
+       },
+       .recv_table = {
+               { .recv_opt = 0, .msg_size = 18, .ipi_id =  1, .mbox_id = 0 },
+
+               { .recv_opt = 1, .msg_size =  8, .ipi_id = 15, .mbox_id = 1 },
+               { .recv_opt = 0, .msg_size = 18, .ipi_id = 17, .mbox_id = 1 },
+               { .recv_opt = 0, .msg_size =  2, .ipi_id = 10, .mbox_id = 1 },
+
+               { .recv_opt = 0, .msg_size = 18, .ipi_id = 12, .mbox_id = 2 },
+               { .recv_opt = 0, .msg_size =  1, .ipi_id =  5, .mbox_id = 2 },
+               { .recv_opt = 1, .msg_size =  1, .ipi_id =  2, .mbox_id = 2 },
+
+               { .recv_opt = 0, .msg_size =  2, .ipi_id = 34, .mbox_id = 3 },
+               { .recv_opt = 0, .msg_size =  2, .ipi_id = 14, .mbox_id = 3 },
+
+               { .recv_opt = 0, .msg_size =  1, .ipi_id = 26, .mbox_id = 4 },
+               { .recv_opt = 1, .msg_size =  1, .ipi_id = 20, .mbox_id = 4 }
+       },
+       .recv_count = 11,
+       .send_count = 14,
+};
+
+static struct mtk_vcp_ipi_ops mt8196_vcp_ipi_ops = {
+       .ipi_send = mtk_vcp_ipc_send,
+       .ipi_send_compl = mtk_vcp_ipc_send_compl,
+       .ipi_register = mtk_vcp_mbox_ipc_register,
+       .ipi_unregister = mtk_vcp_mbox_ipc_unregister,
+};
+
 static const struct mtk_vcp_of_data mt8196_of_data = {
        .ops = {
                .vcp_get_mem_phys = vcp_get_reserve_mem_phys,
@@ -296,6 +392,8 @@ static const struct mtk_vcp_of_data mt8196_of_data = {
                .auto_boot = true,
                .sysfs_read_only = true,
                .rtos_static_iova = 0x180600000,
+               .ipc_data = &mt8196_ipc_tb,
+               .ipi_ops = &mt8196_vcp_ipi_ops,
                .feature_tb = mt8196_feature_tb,
                .memory_tb = mt8196_memory_tb,
                .fw_name = "mediatek/mt8196/vcp.img",
diff --git a/drivers/remoteproc/mtk_vcp_rproc.h 
b/drivers/remoteproc/mtk_vcp_rproc.h
index 11ce0f6d562b..ff3e67fc2611 100644
--- a/drivers/remoteproc/mtk_vcp_rproc.h
+++ b/drivers/remoteproc/mtk_vcp_rproc.h
@@ -21,6 +21,7 @@
  * @sram_offset: core sram memory layout
  * @share_mem_iova: shared memory iova base
  * @share_mem_size: shared memory size
+ * @vcp_ipidev: struct mtk_ipi_device
  * @vcp_memory_tb: vcp memory allocated table
  */
 struct mtk_vcp_of_cluster {
@@ -34,6 +35,7 @@ struct mtk_vcp_of_cluster {
        u32 sram_offset[VCP_CORE_TOTAL];
        dma_addr_t share_mem_iova;
        size_t share_mem_size;
+       struct mtk_ipi_device vcp_ipidev;
        struct vcp_reserve_mblock vcp_memory_tb[NUMS_MEM_ID];
 };
 
@@ -43,6 +45,8 @@ struct mtk_vcp_of_cluster {
  * @auto_boot: rproc auto_boot flag
  * @sysfs_read_only: rproc sysfs_read_only flag
  * @rtos_static_iova: vcp dram binary static map iova
+ * @mtk_mbox_table: mtk_mbox_table structure
+ * @mtk_vcp_ipi_ops: vcp ipi api ops structure
  * @feature_tb: vcp feature table structure
  * @memory_tb: vcp memory table structure
  * @fw_name: vcp image name and path
@@ -51,6 +55,8 @@ struct mtk_vcp_platdata {
        bool auto_boot;
        bool sysfs_read_only;
        dma_addr_t rtos_static_iova;
+       struct mtk_mbox_table *ipc_data;
+       struct mtk_vcp_ipi_ops *ipi_ops;
        struct mtk_vcp_feature_table *feature_tb;
        struct mtk_vcp_reserved_mem_table *memory_tb;
        char *fw_name;
diff --git a/include/linux/remoteproc/mtk_vcp_public.h 
b/include/linux/remoteproc/mtk_vcp_public.h
index 3bbc2055f9f8..58ba4b8bb023 100644
--- a/include/linux/remoteproc/mtk_vcp_public.h
+++ b/include/linux/remoteproc/mtk_vcp_public.h
@@ -7,8 +7,18 @@
 #define __MTK_VCP_PUBLIC_H__
 
 #include <linux/platform_device.h>
+#include <linux/firmware/mediatek/mtk-vcp-ipc.h>
 #include <linux/remoteproc.h>
 
+#define VCP_SYNC_TIMEOUT_MS             (50)
+
+enum vcp_notify_event {
+       VCP_EVENT_READY = 0,
+       VCP_EVENT_STOP,
+       VCP_EVENT_SUSPEND,
+       VCP_EVENT_RESUME,
+};
+
 enum vcp_reserve_mem_id {
        VCP_RTOS_MEM_ID,
        VDEC_MEM_ID,
@@ -36,15 +46,59 @@ enum vcp_feature_id {
        NUM_FEATURE_ID,
 };
 
+enum {
+       IPI_OUT_VDEC_1                 =  0,
+       IPI_IN_VDEC_1                  =  1,
+       IPI_OUT_C_SLEEP_0              =  2,
+       IPI_OUT_TEST_0                 =  3,
+       IPI_IN_VCP_READY_0             =  5,
+       IPI_OUT_MMDVFS_VCP             =  9,
+       IPI_IN_MMDVFS_VCP              = 10,
+       IPI_OUT_MMQOS                  = 11,
+       IPI_IN_MMQOS                   = 12,
+       IPI_OUT_MMDEBUG                = 13,
+       IPI_IN_MMDEBUG                 = 14,
+       IPI_OUT_C_VCP_HWVOTER_DEBUG    = 15,
+       IPI_OUT_VENC_0                 = 16,
+       IPI_IN_VENC_0                  = 17,
+       IPI_OUT_C_SLEEP_1              = 20,
+       IPI_OUT_TEST_1                 = 21,
+       IPI_OUT_LOGGER_CTRL_0          = 22,
+       IPI_OUT_VCPCTL_1               = 23,
+       IPI_IN_LOGGER_CTRL_0           = 25,
+       IPI_IN_VCP_READY_1             = 26,
+       IPI_OUT_LOGGER_CTRL_1          = 30,
+       IPI_IN_LOGGER_CTRL_1           = 31,
+       IPI_OUT_VCPCTL_0               = 32,
+       IPI_OUT_MMDVFS_MMUP            = 33,
+       IPI_IN_MMDVFS_MMUP             = 34,
+       IPI_OUT_VDISP                  = 35,
+       VCP_IPI_COUNT,
+       VCP_IPI_NS_SERVICE             = 0xff,
+       VCP_IPI_NS_SERVICE_COUNT       = 0x100,
+};
+
 struct mtk_vcp_device {
        struct platform_device *pdev;
        struct device *dev;
        struct rproc *rproc;
+       struct mtk_ipi_device *ipi_dev;
        struct mtk_vcp_of_cluster *vcp_cluster;
+       const struct mtk_vcp_ipi_ops *ipi_ops;
        const struct mtk_vcp_ops *ops;
        const struct mtk_vcp_platdata *platdata;
 };
 
+struct mtk_vcp_ipi_ops {
+       int (*ipi_send)(struct mtk_ipi_device *ipidev, u32 ipi_id,
+                       void *data, u32 len);
+       int (*ipi_send_compl)(struct mtk_ipi_device *ipidev, u32 ipi_id,
+                             void *data, u32 len, u32 timeout_ms);
+       int (*ipi_register)(struct mtk_ipi_device *ipidev, int ipi_id,
+                           mbox_pin_cb_t cb, void *prdata, void *msg);
+       int (*ipi_unregister)(struct mtk_ipi_device *ipidev, int ipi_id);
+};
+
 struct mtk_vcp_ops {
        phys_addr_t (*vcp_get_mem_phys)(struct mtk_vcp_device *vcp,
                                        enum vcp_reserve_mem_id id);
@@ -59,6 +113,7 @@ struct mtk_vcp_ops {
 
 struct mtk_vcp_device *vcp_get(struct platform_device *pdev);
 void vcp_put(struct mtk_vcp_device *vcp);
+struct mtk_ipi_device *vcp_get_ipidev(struct mtk_vcp_device *vcp);
 
 /*
  * These inline functions are intended for user drivers that are loaded
-- 
2.46.0


Reply via email to