From: Xiangzhi Tang <xiangzhi.tang@mediatek.com>
To: Bjorn Andersson <andersson@kernel.org>,
Mathieu Poirier <mathieu.poirier@linaro.org>,
Rob Herring <robh@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
"Matthias Brugger" <matthias.bgg@gmail.com>,
AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com>,
Xiangzhi Tang <Xiangzhi.Tang@mediatek.com>
Cc: <linux-remoteproc@vger.kernel.org>, <devicetree@vger.kernel.org>,
<linux-kernel@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-mediatek@lists.infradead.org>,
<Project_Global_Chrome_Upstream_Group@mediatek.com>,
Hailong Fan <Hailong.Fan@mediatek.com>,
Huayu Zong <huayu.Zong@mediatek.com>,
"Xiangzhi Tang" <xiangzhi.tang@mediatek.com>
Subject: [PATCH v3 5/6] remoteproc: mediatek: Add VCP ipi communication sync mechanism
Date: Fri, 20 Mar 2026 11:18:07 +0800 [thread overview]
Message-ID: <20260320032014.13608-6-xiangzhi.tang@mediatek.com> (raw)
In-Reply-To: <20260320032014.13608-1-xiangzhi.tang@mediatek.com>
1.Add vcp ready ipi register driver.
2.Add vcp ready notify work mechanism.
3.Add vcp feature resgiter mechanism.
Signed-off-by: Xiangzhi Tang <xiangzhi.tang@mediatek.com>
---
drivers/remoteproc/mtk_vcp_common.c | 279 ++++++++++++++++++++++
drivers/remoteproc/mtk_vcp_common.h | 56 +++++
drivers/remoteproc/mtk_vcp_rproc.c | 62 ++++-
drivers/remoteproc/mtk_vcp_rproc.h | 18 ++
include/linux/remoteproc/mtk_vcp_public.h | 12 +
5 files changed, 425 insertions(+), 2 deletions(-)
diff --git a/drivers/remoteproc/mtk_vcp_common.c b/drivers/remoteproc/mtk_vcp_common.c
index 97ea8099912d..f3b506034e95 100644
--- a/drivers/remoteproc/mtk_vcp_common.c
+++ b/drivers/remoteproc/mtk_vcp_common.c
@@ -24,6 +24,9 @@
#include "mtk_vcp_common.h"
#include "mtk_vcp_rproc.h"
+static BLOCKING_NOTIFIER_HEAD(mmup_notifier_list);
+static BLOCKING_NOTIFIER_HEAD(vcp_notifier_list);
+
phys_addr_t vcp_get_reserve_mem_phys(struct mtk_vcp_device *vcp,
enum vcp_reserve_mem_id id)
{
@@ -153,6 +156,40 @@ int vcp_reserve_memory_init(struct mtk_vcp_device *vcp)
return 0;
}
+static bool vcp_is_core_ready(struct mtk_vcp_device *vcp,
+ enum vcp_core_id core_id)
+{
+ switch (core_id) {
+ case VCP_ID:
+ return vcp->vcp_cluster->vcp_ready[VCP_ID];
+ case MMUP_ID:
+ return vcp->vcp_cluster->vcp_ready[MMUP_ID];
+ case VCP_CORE_TOTAL:
+ default:
+ return vcp->vcp_cluster->vcp_ready[VCP_ID] &
+ vcp->vcp_cluster->vcp_ready[MMUP_ID];
+ }
+}
+
+static enum vcp_core_id get_core_by_feature(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id)
+{
+ for (u32 i = 0; i < NUM_FEATURE_ID; i++) {
+ if (vcp->platdata->feature_tb[i].feature_id == id)
+ return vcp->platdata->feature_tb[i].core_id;
+ }
+
+ return 0;
+}
+
+bool is_vcp_ready(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id)
+{
+ enum vcp_core_id core_id = get_core_by_feature(vcp, id);
+
+ return vcp_is_core_ready(vcp, core_id);
+}
+
int wait_core_hart_shutdown(struct mtk_vcp_device *vcp,
enum vcp_core_id core_id)
{
@@ -215,9 +252,120 @@ int wait_core_hart_shutdown(struct mtk_vcp_device *vcp,
return ret;
}
+void vcp_A_register_notify(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id,
+ struct notifier_block *nb)
+{
+ enum vcp_core_id core_id = get_core_by_feature(vcp, id);
+
+ switch (core_id) {
+ case VCP_ID:
+ blocking_notifier_chain_register(&vcp_notifier_list, nb);
+ if (vcp_is_core_ready(vcp, VCP_ID))
+ nb->notifier_call(nb, VCP_EVENT_READY, NULL);
+ break;
+ case MMUP_ID:
+ blocking_notifier_chain_register(&mmup_notifier_list, nb);
+ if (vcp_is_core_ready(vcp, MMUP_ID))
+ nb->notifier_call(nb, VCP_EVENT_READY, NULL);
+ break;
+ default:
+ dev_err(vcp->dev, "%s(), No Support core id\n", __func__);
+ break;
+ }
+}
+
+void vcp_A_unregister_notify(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id,
+ struct notifier_block *nb)
+{
+ enum vcp_core_id core_id = get_core_by_feature(vcp, id);
+
+ switch (core_id) {
+ case VCP_ID:
+ blocking_notifier_chain_unregister(&vcp_notifier_list, nb);
+ break;
+ case MMUP_ID:
+ blocking_notifier_chain_unregister(&mmup_notifier_list, nb);
+ break;
+ default:
+ dev_err(vcp->dev, "%s(), No Support core id\n", __func__);
+ break;
+ }
+}
+
+void vcp_extern_notify(enum vcp_core_id core_id,
+ enum vcp_notify_event notify_status)
+{
+ switch (core_id) {
+ case VCP_ID:
+ blocking_notifier_call_chain(&vcp_notifier_list, notify_status, NULL);
+ break;
+ case MMUP_ID:
+ blocking_notifier_call_chain(&mmup_notifier_list, notify_status, NULL);
+ break;
+ default:
+ break;
+ }
+}
+
+static void vcp_A_notify_ws(struct work_struct *ws)
+{
+ struct vcp_work_struct *sws =
+ container_of(ws, struct vcp_work_struct, work);
+ struct mtk_vcp_device *vcp = platform_get_drvdata(to_platform_device(sws->dev));
+ enum vcp_core_id core_id = sws->flags;
+
+ if (core_id < VCP_CORE_TOTAL) {
+ mutex_lock(&vcp->vcp_cluster->vcp_ready_mutex);
+ vcp->vcp_cluster->vcp_ready[core_id] = true;
+ mutex_unlock(&vcp->vcp_cluster->vcp_ready_mutex);
+
+ vcp_extern_notify(core_id, VCP_EVENT_READY);
+
+ /*clear reset status and unlock wake lock*/
+ dev_info(sws->dev, "%s core id %u ready\n", __func__, core_id);
+ } else {
+ dev_err(sws->dev, "%s wrong core id %u\n", __func__, core_id);
+ }
+}
+
+static void vcp_A_set_ready(struct mtk_vcp_device *vcp,
+ enum vcp_core_id core_id)
+{
+ if (core_id < VCP_CORE_TOTAL) {
+ vcp->vcp_cluster->vcp_ready_notify_wk[core_id].flags = core_id;
+ queue_work(vcp->vcp_cluster->vcp_workqueue,
+ &vcp->vcp_cluster->vcp_ready_notify_wk[core_id].work);
+ }
+}
+
+int vcp_A_ready_ipi_handler(u32 id, void *prdata, void *data, u32 len)
+{
+ struct mtk_vcp_device *vcp = (struct mtk_vcp_device *)prdata;
+
+ switch (id) {
+ case IPI_IN_VCP_READY_0:
+ if (!vcp_is_core_ready(vcp, VCP_ID))
+ vcp_A_set_ready(vcp, VCP_ID);
+ break;
+ case IPI_IN_VCP_READY_1:
+ if (!vcp_is_core_ready(vcp, MMUP_ID))
+ vcp_A_set_ready(vcp, MMUP_ID);
+ break;
+ default:
+ dev_err(vcp->dev, "%s(), No Support ipi id\n", __func__);
+ break;
+ }
+
+ return 0;
+}
+
int reset_vcp(struct mtk_vcp_device *vcp)
{
struct arm_smccc_res res;
+ bool mmup_status, vcp_status;
+ int ret;
if (vcp->vcp_cluster->core_nums > MMUP_ID) {
writel((u32)VCP_PACK_IOVA(vcp->vcp_cluster->share_mem_iova),
@@ -228,6 +376,16 @@ int reset_vcp(struct mtk_vcp_device *vcp)
arm_smccc_smc(MTK_SIP_TINYSYS_VCP_CONTROL,
MTK_TINYSYS_MMUP_KERNEL_OP_RESET_RELEASE,
1, 0, 0, 0, 0, 0, &res);
+
+ ret = read_poll_timeout(vcp_is_core_ready,
+ mmup_status, mmup_status,
+ USEC_PER_MSEC,
+ VCP_READY_TIMEOUT_MS * USEC_PER_MSEC,
+ false, vcp, MMUP_ID);
+ if (ret) {
+ dev_err(vcp->dev, "MMUP_ID bootup timeout. Stop vcp booting\n");
+ return ret;
+ }
}
writel((u32)VCP_PACK_IOVA(vcp->vcp_cluster->share_mem_iova),
@@ -239,6 +397,127 @@ int reset_vcp(struct mtk_vcp_device *vcp)
MTK_TINYSYS_VCP_KERNEL_OP_RESET_RELEASE,
1, 0, 0, 0, 0, 0, &res);
+ ret = read_poll_timeout(vcp_is_core_ready,
+ vcp_status, vcp_status,
+ USEC_PER_MSEC,
+ VCP_READY_TIMEOUT_MS * USEC_PER_MSEC,
+ false, vcp, VCP_ID);
+ if (ret) {
+ dev_err(vcp->dev, "VCP_ID bootup timeout. Stop vcp booting\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static int vcp_enable_pm_clk(struct mtk_vcp_device *vcp, enum vcp_feature_id id)
+{
+ struct vcp_slp_ctrl slp_data;
+ bool suspend_status;
+ int ret;
+
+ if (vcp->vcp_cluster->feature_enable[id]) {
+ dev_err(vcp->dev, "%s feature(id=%d) already enabled\n",
+ __func__, id);
+ return -EINVAL;
+ }
+
+ if (id != RTOS_FEATURE_ID) {
+ slp_data.cmd = SLP_WAKE_LOCK;
+ slp_data.feature = id;
+ ret = vcp->ipi_ops->ipi_send_compl(vcp->ipi_dev, IPI_OUT_C_SLEEP_0,
+ &slp_data, PIN_OUT_C_SIZE_SLEEP_0, 500);
+ if (ret < 0) {
+ dev_err(vcp->dev, "%s ipc_send_compl failed. ret %d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int vcp_disable_pm_clk(struct mtk_vcp_device *vcp, enum vcp_feature_id id)
+{
+ struct vcp_slp_ctrl slp_data;
+ bool suspend_status;
+ int ret;
+
+ if (!vcp->vcp_cluster->feature_enable[id]) {
+ dev_err(vcp->dev, "%s feature(id=%d) already disabled\n",
+ __func__, id);
+ return -EINVAL;
+ }
+
+ if (id != RTOS_FEATURE_ID) {
+ slp_data.cmd = SLP_WAKE_UNLOCK;
+ slp_data.feature = id;
+ ret = vcp->ipi_ops->ipi_send_compl(vcp->ipi_dev, IPI_OUT_C_SLEEP_0,
+ &slp_data, PIN_OUT_C_SIZE_SLEEP_0, 500);
+ if (ret < 0) {
+ dev_err(vcp->dev, "%s ipc_send_compl failed. ret %d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int vcp_A_register_feature(struct mtk_vcp_device *vcp, enum vcp_feature_id id)
+{
+ int ret;
+
+ if (id >= NUM_FEATURE_ID) {
+ dev_err(vcp->dev, "%s unsupported feature id %d\n",
+ __func__, id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&vcp->vcp_cluster->vcp_feature_mutex);
+ ret = vcp_enable_pm_clk(vcp, id);
+ if (ret)
+ dev_err(vcp->dev, "%s feature(id=%d) register failed\n",
+ __func__, id);
+ else
+ vcp->vcp_cluster->feature_enable[id] = true;
+ mutex_unlock(&vcp->vcp_cluster->vcp_feature_mutex);
+
+ return ret;
+}
+
+int vcp_A_deregister_feature(struct mtk_vcp_device *vcp, enum vcp_feature_id id)
+{
+ int ret;
+
+ if (id >= NUM_FEATURE_ID) {
+ dev_err(vcp->dev, "%s unsupported feature id %d\n", __func__, id);
+ return -EINVAL;
+ }
+
+ mutex_lock(&vcp->vcp_cluster->vcp_feature_mutex);
+ ret = vcp_disable_pm_clk(vcp, id);
+ if (ret)
+ dev_err(vcp->dev, "%s feature(id=%d) deregister failed\n",
+ __func__, id);
+ else
+ vcp->vcp_cluster->feature_enable[id] = false;
+ mutex_unlock(&vcp->vcp_cluster->vcp_feature_mutex);
+
+ return ret;
+}
+
+int vcp_notify_work_init(struct mtk_vcp_device *vcp)
+{
+ vcp->vcp_cluster->vcp_workqueue = create_singlethread_workqueue("VCP_WQ");
+ if (!vcp->vcp_cluster->vcp_workqueue)
+ return dev_err_probe(vcp->dev, -EINVAL, "vcp_workqueue create fail\n");
+
+ for (u32 core_id = 0; core_id < VCP_CORE_TOTAL; core_id++) {
+ vcp->vcp_cluster->vcp_ready_notify_wk[core_id].dev = vcp->dev;
+ INIT_WORK(&vcp->vcp_cluster->vcp_ready_notify_wk[core_id].work, vcp_A_notify_ws);
+ }
+
return 0;
}
diff --git a/drivers/remoteproc/mtk_vcp_common.h b/drivers/remoteproc/mtk_vcp_common.h
index d048757c955a..8b19fcb78a79 100644
--- a/drivers/remoteproc/mtk_vcp_common.h
+++ b/drivers/remoteproc/mtk_vcp_common.h
@@ -13,10 +13,13 @@
#include <linux/remoteproc/mtk_vcp_public.h>
/* VCP timeout definition */
+#define VCP_READY_TIMEOUT_MS 3000
+#define VCP_IPI_DEV_READY_TIMEOUT 1000
#define CORE_HART_SHUTDOWN_TIMEOUT_MS 10
/* VCP platform definition */
#define DMA_MAX_MASK_BIT 33
+#define PIN_OUT_C_SIZE_SLEEP_0 2
/* VCP load image definition */
#define VCM_IMAGE_MAGIC (0x58881688)
@@ -90,6 +93,14 @@ enum vcp_core_id {
VCP_CORE_TOTAL,
};
+enum vcp_slp_cmd {
+ SLP_WAKE_LOCK = 0,
+ SLP_WAKE_UNLOCK,
+ SLP_STATUS_DBG,
+ SLP_SUSPEND,
+ SLP_RESUME,
+};
+
enum mtk_tinysys_vcp_kernel_op {
MTK_TINYSYS_VCP_KERNEL_OP_RESET_SET = 0,
MTK_TINYSYS_VCP_KERNEL_OP_RESET_RELEASE,
@@ -154,6 +165,32 @@ struct vcp_reserve_mblock {
size_t size;
};
+/**
+ * struct vcp_slp_ctrl - sleep ctrl data sync with AP and VCP
+ *
+ * @feature: Feature id
+ * @cmd: sleep cmd flag.
+ */
+struct vcp_slp_ctrl {
+ u32 feature;
+ u32 cmd;
+};
+
+/**
+ * struct vcp_work_struct - vcp notify work structure.
+ *
+ * @work: struct work_struct member
+ * @dev: struct device member
+ * @u32 flags: vcp notify work flag
+ * @id: vcp core id
+ */
+struct vcp_work_struct {
+ struct work_struct work;
+ struct device *dev;
+ u32 flags;
+ u32 id;
+};
+
/**
* struct vcp_region_info_st - config vcp image info sync to vcp bootloader.
*
@@ -201,6 +238,20 @@ struct vcp_region_info_st {
u32 coredump_dram_offset;
};
+int vcp_A_ready_ipi_handler(u32 id, void *prdata,
+ void *data, u32 len);
+bool is_vcp_ready(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id);
+int vcp_notify_work_init(struct mtk_vcp_device *vcp);
+void vcp_extern_notify(enum vcp_core_id core_id,
+ enum vcp_notify_event notify_status);
+void vcp_A_register_notify(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id,
+ struct notifier_block *nb);
+void vcp_A_unregister_notify(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id,
+ struct notifier_block *nb);
+
int vcp_reserve_memory_init(struct mtk_vcp_device *vcp);
phys_addr_t vcp_get_reserve_mem_phys(struct mtk_vcp_device *vcp, enum vcp_reserve_mem_id id);
dma_addr_t vcp_get_reserve_mem_iova(struct mtk_vcp_device *vcp, enum vcp_reserve_mem_id id);
@@ -213,5 +264,10 @@ int mtk_vcp_load(struct rproc *rproc, const struct firmware *fw);
int vcp_wdt_irq_init(struct mtk_vcp_device *vcp);
+int vcp_A_register_feature(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id);
+int vcp_A_deregister_feature(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id);
+
int wait_core_hart_shutdown(struct mtk_vcp_device *vcp, enum vcp_core_id core_id);
#endif
diff --git a/drivers/remoteproc/mtk_vcp_rproc.c b/drivers/remoteproc/mtk_vcp_rproc.c
index 6e0fecef72ce..833a0dc69d9c 100644
--- a/drivers/remoteproc/mtk_vcp_rproc.c
+++ b/drivers/remoteproc/mtk_vcp_rproc.c
@@ -71,6 +71,30 @@ static int mtk_vcp_start(struct rproc *rproc)
{
struct mtk_vcp_device *vcp = (struct mtk_vcp_device *)rproc->priv;
struct arm_smccc_res res;
+ int ret;
+
+ ret = vcp->ipi_ops->ipi_register(vcp->ipi_dev, IPI_OUT_C_SLEEP_0,
+ NULL, NULL, &vcp->vcp_cluster->slp_ipi_ack_data);
+ if (ret) {
+ dev_err(vcp->dev, "Failed to register IPI_OUT_C_SLEEP_0\n");
+ goto slp_ipi_unregister;
+ }
+
+ ret = vcp->ipi_ops->ipi_register(vcp->ipi_dev, IPI_IN_VCP_READY_0,
+ (void *)vcp_A_ready_ipi_handler,
+ vcp, &vcp->vcp_cluster->msg_vcp_ready0);
+ if (ret) {
+ dev_err(vcp->dev, "Failed to register IPI_IN_VCP_READY_0\n");
+ goto vcp0_ready_ipi_unregister;
+ }
+
+ ret = vcp->ipi_ops->ipi_register(vcp->ipi_dev, IPI_IN_VCP_READY_1,
+ (void *)vcp_A_ready_ipi_handler,
+ vcp, &vcp->vcp_cluster->msg_vcp_ready1);
+ if (ret) {
+ dev_err(vcp->dev, "Failed to register IPI_IN_VCP_READY_1\n");
+ goto vcp1_ready_ipi_unregister;
+ }
/* core 0 */
arm_smccc_smc(MTK_SIP_TINYSYS_VCP_CONTROL,
@@ -83,10 +107,22 @@ static int mtk_vcp_start(struct rproc *rproc)
1, 0, 0, 0, 0, 0, &res);
ret = reset_vcp(vcp);
- if (ret)
+ if (ret) {
dev_err(vcp->dev, "bootup fail\n");
- else
+ } else {
dev_info(vcp->dev, "bootup successfully\n");
+ if (vcp_A_register_feature(vcp, RTOS_FEATURE_ID) < 0)
+ vcp_A_deregister_feature(vcp, RTOS_FEATURE_ID);
+ }
+
+ return ret;
+
+vcp1_ready_ipi_unregister:
+ vcp->ipi_ops->ipi_unregister(vcp->ipi_dev, IPI_IN_VCP_READY_1);
+vcp0_ready_ipi_unregister:
+ vcp->ipi_ops->ipi_unregister(vcp->ipi_dev, IPI_IN_VCP_READY_0);
+slp_ipi_unregister:
+ vcp->ipi_ops->ipi_unregister(vcp->ipi_dev, IPI_OUT_C_SLEEP_0);
return ret;
}
@@ -97,6 +133,9 @@ static int mtk_vcp_stop(struct rproc *rproc)
vcp_A_deregister_feature(vcp, RTOS_FEATURE_ID);
+ vcp_extern_notify(VCP_ID, VCP_EVENT_STOP);
+ vcp_extern_notify(MMUP_ID, VCP_EVENT_STOP);
+
return 0;
}
@@ -185,6 +224,8 @@ static struct mtk_vcp_device *vcp_rproc_init(struct platform_device *pdev,
rproc->auto_boot = vcp_of_data->platdata.auto_boot;
rproc->sysfs_read_only = vcp_of_data->platdata.sysfs_read_only;
+ mutex_init(&vcp->vcp_cluster->vcp_feature_mutex);
+ mutex_init(&vcp->vcp_cluster->vcp_ready_mutex);
platform_set_drvdata(pdev, vcp);
ret = vcp_reserve_memory_init(vcp);
@@ -213,6 +254,10 @@ static struct mtk_vcp_device *vcp_rproc_init(struct platform_device *pdev,
if (ret)
return ERR_PTR(dev_err_probe(dev, ret, "vcp_ipi_mbox_init failed\n"));
+ ret = vcp_notify_work_init(vcp);
+ if (ret)
+ return ERR_PTR(dev_err_probe(dev, ret, "vcp_notify_work_init failed\n"));
+
pm_runtime_get_sync(dev);
return vcp;
@@ -287,6 +332,8 @@ static void vcp_device_remove(struct platform_device *pdev)
{
struct mtk_vcp_device *vcp = platform_get_drvdata(pdev);
+ flush_workqueue(vcp->vcp_cluster->vcp_workqueue);
+ destroy_workqueue(vcp->vcp_cluster->vcp_workqueue);
pm_runtime_disable(&pdev->dev);
rproc_del(vcp->rproc);
@@ -297,6 +344,12 @@ static void vcp_device_shutdown(struct platform_device *pdev)
struct mtk_vcp_device *vcp = platform_get_drvdata(pdev);
int ret;
+ vcp->vcp_cluster->vcp_ready[VCP_ID] = false;
+ vcp->vcp_cluster->vcp_ready[MMUP_ID] = false;
+
+ vcp_extern_notify(VCP_ID, VCP_EVENT_STOP);
+ vcp_extern_notify(MMUP_ID, VCP_EVENT_STOP);
+
writel(GIPC_VCP_HART0_SHUT, vcp->vcp_cluster->cfg_core + R_GIPC_IN_SET);
ret = wait_core_hart_shutdown(vcp, VCP_ID);
if (ret)
@@ -382,6 +435,11 @@ static struct mtk_vcp_ipi_ops mt8196_vcp_ipi_ops = {
static const struct mtk_vcp_of_data mt8196_of_data = {
.ops = {
+ .vcp_is_ready = is_vcp_ready,
+ .vcp_register_feature = vcp_A_register_feature,
+ .vcp_deregister_feature = vcp_A_deregister_feature,
+ .vcp_register_notify = vcp_A_register_notify,
+ .vcp_unregister_notify = vcp_A_unregister_notify,
.vcp_get_mem_phys = vcp_get_reserve_mem_phys,
.vcp_get_mem_iova = vcp_get_reserve_mem_iova,
.vcp_get_mem_virt = vcp_get_reserve_mem_virt,
diff --git a/drivers/remoteproc/mtk_vcp_rproc.h b/drivers/remoteproc/mtk_vcp_rproc.h
index ff3e67fc2611..600715b77124 100644
--- a/drivers/remoteproc/mtk_vcp_rproc.h
+++ b/drivers/remoteproc/mtk_vcp_rproc.h
@@ -19,10 +19,19 @@
* @core_nums: total core numbers get from dtb
* @twohart: core weo hart support flag
* @sram_offset: core sram memory layout
+ * @msg_vcp_ready0: core0 ready ipi msg data
+ * @msg_vcp_ready1: core1 ready ipi msg data
+ * @slp_ipi_ack_data: sleep ipi msg data
+ * @feature_enable: feature status count data
+ * @vcp_ready: vcp core status flag
* @share_mem_iova: shared memory iova base
* @share_mem_size: shared memory size
+ * @vcp_feature_mutex: vcp feature register mutex structure
+ * @vcp_ready_mutex: vcp core ready mutex structure
* @vcp_ipidev: struct mtk_ipi_device
+ * @vcp_workqueue: ready workqueue_struct
* @vcp_memory_tb: vcp memory allocated table
+ * @vcp_ready_notify_wk: vcp_work_struct structure
*/
struct mtk_vcp_of_cluster {
void __iomem *sram_base;
@@ -33,10 +42,19 @@ struct mtk_vcp_of_cluster {
u32 core_nums;
u32 twohart[VCP_CORE_TOTAL];
u32 sram_offset[VCP_CORE_TOTAL];
+ u32 msg_vcp_ready0;
+ u32 msg_vcp_ready1;
+ u32 slp_ipi_ack_data;
+ bool feature_enable[NUM_FEATURE_ID];
+ bool vcp_ready[VCP_CORE_TOTAL];
dma_addr_t share_mem_iova;
size_t share_mem_size;
+ struct mutex vcp_feature_mutex;
+ struct mutex vcp_ready_mutex;
struct mtk_ipi_device vcp_ipidev;
+ struct workqueue_struct *vcp_workqueue;
struct vcp_reserve_mblock vcp_memory_tb[NUMS_MEM_ID];
+ struct vcp_work_struct vcp_ready_notify_wk[VCP_CORE_TOTAL];
};
/**
diff --git a/include/linux/remoteproc/mtk_vcp_public.h b/include/linux/remoteproc/mtk_vcp_public.h
index 58ba4b8bb023..b9e1d86685fd 100644
--- a/include/linux/remoteproc/mtk_vcp_public.h
+++ b/include/linux/remoteproc/mtk_vcp_public.h
@@ -100,6 +100,18 @@ struct mtk_vcp_ipi_ops {
};
struct mtk_vcp_ops {
+ bool (*vcp_is_ready)(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id);
+ int (*vcp_register_feature)(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id);
+ int (*vcp_deregister_feature)(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id);
+ void (*vcp_register_notify)(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id,
+ struct notifier_block *nb);
+ void (*vcp_unregister_notify)(struct mtk_vcp_device *vcp,
+ enum vcp_feature_id id,
+ struct notifier_block *nb);
phys_addr_t (*vcp_get_mem_phys)(struct mtk_vcp_device *vcp,
enum vcp_reserve_mem_id id);
dma_addr_t (*vcp_get_mem_iova)(struct mtk_vcp_device *vcp,
--
2.46.0
next prev parent reply other threads:[~2026-03-20 3:21 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-20 3:18 [PATCH v3 0/6] ASoC: mediatek: Add VCP driver on Mediatek MT8196 SoC Xiangzhi Tang
2026-03-20 3:18 ` [PATCH v3 1/6] dt-bindings: remoteproc: Add VCP support for mt8196 Xiangzhi Tang
2026-03-20 5:25 ` Rob Herring (Arm)
2026-03-20 9:01 ` Krzysztof Kozlowski
2026-03-20 3:18 ` [PATCH v3 2/6] remoteproc: Mediatek: Add VCP remoteproc driver Xiangzhi Tang
2026-03-20 9:15 ` Krzysztof Kozlowski
2026-03-20 3:18 ` [PATCH v3 3/6] firmware: mediatek: Add VCP IPC protocol interfaces driver Xiangzhi Tang
2026-08-13 22:10 ` sashiko-bot
2026-03-20 3:18 ` [PATCH v3 4/6] remoteproc: mediatek: Add VCP ipi-mbox init driver Xiangzhi Tang
2026-03-20 3:18 ` Xiangzhi Tang [this message]
2026-03-20 3:18 ` [PATCH v3 6/6] remoterpoc: mediatek: vcp: Add vcp suspned and resume feature Xiangzhi Tang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260320032014.13608-6-xiangzhi.tang@mediatek.com \
--to=xiangzhi.tang@mediatek.com \
--cc=Hailong.Fan@mediatek.com \
--cc=Project_Global_Chrome_Upstream_Group@mediatek.com \
--cc=andersson@kernel.org \
--cc=angelogioacchino.delregno@collabora.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=huayu.Zong@mediatek.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=linux-remoteproc@vger.kernel.org \
--cc=mathieu.poirier@linaro.org \
--cc=matthias.bgg@gmail.com \
--cc=robh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.