From 99898c79ff908009f40d97279c3cfefcf1582485 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Wed, 17 Sep 2025 14:08:30 -0700 Subject: [PATCH] ipc: rework Zephyr IPC interface This reworks the Zephyr IPC interface to utilize the generic IPC service and backend. So we no longer have to maintain a SoC specific IPC driver. Signed-off-by: Daniel Leung --- app/boards/intel_adsp/Kconfig.defconfig | 2 + app/boards/intel_adsp_ace15_mtpm.conf | 3 + app/boards/intel_adsp_ace20_lnl.conf | 3 + app/boards/intel_adsp_ace30_ptl.conf | 3 + app/boards/intel_adsp_ace30_ptl_sim.conf | 4 +- app/boards/intel_adsp_ace30_wcl.conf | 3 + app/boards/intel_adsp_ace30_wcl_sim.conf | 3 + app/boards/intel_adsp_ace40_nvl.conf | 3 + app/boards/intel_adsp_ace40_nvls.conf | 3 + app/boards/intel_adsp_cavs25.conf | 3 + app/boards/intel_adsp_cavs25_tgph.conf | 3 + src/include/sof/ipc/common.h | 8 ++ src/ipc/ipc-zephyr.c | 125 ++++++++++++++++++----- src/platform/intel/ace/lib/watchdog.c | 3 +- 14 files changed, 143 insertions(+), 26 deletions(-) diff --git a/app/boards/intel_adsp/Kconfig.defconfig b/app/boards/intel_adsp/Kconfig.defconfig index a2ba2db15db6..e695bf4289fc 100644 --- a/app/boards/intel_adsp/Kconfig.defconfig +++ b/app/boards/intel_adsp/Kconfig.defconfig @@ -115,7 +115,9 @@ config DAI_INTEL_SSP default y config INTEL_ADSP_IPC + bool default y + depends on IPC_SERVICE_BACKEND_INTEL_ADSP_HOST_IPC config INTEL_ADSP_TIMER default y diff --git a/app/boards/intel_adsp_ace15_mtpm.conf b/app/boards/intel_adsp_ace15_mtpm.conf index 5266f38386d3..2278906cc008 100644 --- a/app/boards/intel_adsp_ace15_mtpm.conf +++ b/app/boards/intel_adsp_ace15_mtpm.conf @@ -85,3 +85,6 @@ CONFIG_LOG_BACKEND_SOF_PROBE=n CONFIG_LOG_OUTPUT_FORMAT_LINUX_TIMESTAMP=y CONFIG_WINSTREAM_CONSOLE=n CONFIG_LOG_FLUSH_SLEEP_US=5000 + +# Use the new IPC message service in Zephyr +CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE=n diff --git a/app/boards/intel_adsp_ace20_lnl.conf b/app/boards/intel_adsp_ace20_lnl.conf index abf6d1537330..fcea38859131 100644 --- a/app/boards/intel_adsp_ace20_lnl.conf +++ b/app/boards/intel_adsp_ace20_lnl.conf @@ -63,3 +63,6 @@ CONFIG_LOG_BACKEND_ADSP=n CONFIG_LOG_OUTPUT_FORMAT_LINUX_TIMESTAMP=y CONFIG_WINSTREAM_CONSOLE=n CONFIG_LOG_FLUSH_SLEEP_US=5000 + +# Use the new IPC message service in Zephyr +CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE=n diff --git a/app/boards/intel_adsp_ace30_ptl.conf b/app/boards/intel_adsp_ace30_ptl.conf index 48a923ab7870..7be338e68fa5 100644 --- a/app/boards/intel_adsp_ace30_ptl.conf +++ b/app/boards/intel_adsp_ace30_ptl.conf @@ -65,3 +65,6 @@ CONFIG_LOG_BACKEND_ADSP=n CONFIG_LOG_FLUSH_SLEEP_US=5000 CONFIG_LOG_OUTPUT_FORMAT_LINUX_TIMESTAMP=y CONFIG_WINSTREAM_CONSOLE=n + +# Use the new IPC message service in Zephyr +CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE=n diff --git a/app/boards/intel_adsp_ace30_ptl_sim.conf b/app/boards/intel_adsp_ace30_ptl_sim.conf index 477450d2d271..e85a10c56f0b 100644 --- a/app/boards/intel_adsp_ace30_ptl_sim.conf +++ b/app/boards/intel_adsp_ace30_ptl_sim.conf @@ -35,7 +35,6 @@ CONFIG_SOF_LOG_LEVEL_INF=n CONFIG_SOF_LOG_LEVEL_OFF=y CONFIG_ZEPHYR_LOG=n -CONFIG_INTEL_ADSP_IPC=y # Temporary disabled options @@ -45,3 +44,6 @@ CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL=y CONFIG_COMP_KPB=n CONFIG_USERSPACE=y + +# Use the new IPC message service in Zephyr +CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE=n diff --git a/app/boards/intel_adsp_ace30_wcl.conf b/app/boards/intel_adsp_ace30_wcl.conf index 74a764883aad..b27eaf87fd8b 100644 --- a/app/boards/intel_adsp_ace30_wcl.conf +++ b/app/boards/intel_adsp_ace30_wcl.conf @@ -58,3 +58,6 @@ CONFIG_LOG_BACKEND_ADSP=n CONFIG_LOG_FLUSH_SLEEP_US=5000 CONFIG_LOG_OUTPUT_FORMAT_LINUX_TIMESTAMP=y CONFIG_WINSTREAM_CONSOLE=n + +# Use the new IPC message service in Zephyr +CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE=n diff --git a/app/boards/intel_adsp_ace30_wcl_sim.conf b/app/boards/intel_adsp_ace30_wcl_sim.conf index 288305be6313..eb0af8dd4197 100644 --- a/app/boards/intel_adsp_ace30_wcl_sim.conf +++ b/app/boards/intel_adsp_ace30_wcl_sim.conf @@ -41,3 +41,6 @@ CONFIG_PM_PREWAKEUP_CONV_MODE_CEIL=y CONFIG_COMP_KPB=n CONFIG_USERSPACE=y + +# Use the new IPC message service in Zephyr +CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE=n diff --git a/app/boards/intel_adsp_ace40_nvl.conf b/app/boards/intel_adsp_ace40_nvl.conf index cfe332cd5075..e3f04d8efcd9 100644 --- a/app/boards/intel_adsp_ace40_nvl.conf +++ b/app/boards/intel_adsp_ace40_nvl.conf @@ -54,3 +54,6 @@ CONFIG_PM_DEVICE_RUNTIME_ASYNC=n # Zephyr / logging CONFIG_LOG_BACKEND_ADSP=n CONFIG_WINSTREAM_CONSOLE=n + +# Use the new IPC message service in Zephyr +CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE=n diff --git a/app/boards/intel_adsp_ace40_nvls.conf b/app/boards/intel_adsp_ace40_nvls.conf index cfe332cd5075..e3f04d8efcd9 100644 --- a/app/boards/intel_adsp_ace40_nvls.conf +++ b/app/boards/intel_adsp_ace40_nvls.conf @@ -54,3 +54,6 @@ CONFIG_PM_DEVICE_RUNTIME_ASYNC=n # Zephyr / logging CONFIG_LOG_BACKEND_ADSP=n CONFIG_WINSTREAM_CONSOLE=n + +# Use the new IPC message service in Zephyr +CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE=n diff --git a/app/boards/intel_adsp_cavs25.conf b/app/boards/intel_adsp_cavs25.conf index 0d39b072324c..c2ed5627854f 100644 --- a/app/boards/intel_adsp_cavs25.conf +++ b/app/boards/intel_adsp_cavs25.conf @@ -56,3 +56,6 @@ CONFIG_LOG_FUNC_NAME_PREFIX_DBG=y CONFIG_LOG_OUTPUT_FORMAT_LINUX_TIMESTAMP=y CONFIG_LOG_TIMESTAMP_64BIT=y CONFIG_WINSTREAM_CONSOLE=n + +# Use the new IPC message service in Zephyr +CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE=n diff --git a/app/boards/intel_adsp_cavs25_tgph.conf b/app/boards/intel_adsp_cavs25_tgph.conf index 2d6ac891cbd0..f3464100b2bb 100644 --- a/app/boards/intel_adsp_cavs25_tgph.conf +++ b/app/boards/intel_adsp_cavs25_tgph.conf @@ -58,3 +58,6 @@ CONFIG_LOG_FUNC_NAME_PREFIX_DBG=y CONFIG_LOG_OUTPUT_FORMAT_LINUX_TIMESTAMP=y CONFIG_LOG_TIMESTAMP_64BIT=y CONFIG_WINSTREAM_CONSOLE=n + +# Use the new IPC message service in Zephyr +CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE=n diff --git a/src/include/sof/ipc/common.h b/src/include/sof/ipc/common.h index e46fc10b9521..61da9f8d3252 100644 --- a/src/include/sof/ipc/common.h +++ b/src/include/sof/ipc/common.h @@ -250,4 +250,12 @@ void ipc_complete_cmd(struct ipc *ipc); /* GDB stub: should enter GDB after completing the IPC processing */ extern bool ipc_enter_gdb; +/** + * \brief Send emergency IPC message. + * + * @param[in] data IPC data to be sent. + * @param[in] ext_data Extended data to be sent. + */ +void ipc_send_message_emergency(uint32_t data, uint32_t ext_data); + #endif /* __SOF_DRIVERS_IPC_H__ */ diff --git a/src/ipc/ipc-zephyr.c b/src/ipc/ipc-zephyr.c index 460089414cf7..24fb1cf8e34e 100644 --- a/src/ipc/ipc-zephyr.c +++ b/src/ipc/ipc-zephyr.c @@ -13,7 +13,6 @@ #include -#include #include #include @@ -45,6 +44,11 @@ #include #include +#ifdef CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE +#include +#endif +#include + SOF_DEFINE_REG_UUID(zipc_task); LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); @@ -59,33 +63,97 @@ LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); */ static uint32_t g_last_data, g_last_ext_data; +struct k_sem *wait_ack_sem; + /** - * @brief cAVS IPC Message Handler Callback function. + * @brief cAVS IPC Message Received Callback function. * - * See @ref (*intel_adsp_ipc_handler_t) for function signature description. - * @return false so BUSY on the other side will not be cleared immediately but + * @return -1 so BUSY on the other side will not be cleared immediately but * will remain set until message would have been processed by scheduled task, i.e. * until ipc_platform_complete_cmd() call. */ -static bool message_handler(const struct device *dev, void *arg, uint32_t data, uint32_t ext_data) +static void ipc_receive_cb(const void *data, size_t cb_type, void *priv) { - struct ipc *ipc = (struct ipc *)arg; + struct intel_adsp_ipc_ept_priv_data *priv_data = priv; + + switch (cb_type) { + case INTEL_ADSP_IPC_CB_MSG: { + const struct intel_adsp_ipc_msg *msg = data; + + struct ipc *ipc = priv_data->priv; - k_spinlock_key_t key; + k_spinlock_key_t key; - key = k_spin_lock(&ipc->lock); + key = k_spin_lock(&ipc->lock); - g_last_data = data; - g_last_ext_data = ext_data; + g_last_data = msg->data; + g_last_ext_data = msg->ext_data; #if CONFIG_DEBUG_IPC_COUNTERS - increment_ipc_received_counter(); + increment_ipc_received_counter(); #endif - ipc_schedule_process(ipc); + ipc_schedule_process(ipc); - k_spin_unlock(&ipc->lock, key); + k_spin_unlock(&ipc->lock, key); - return false; + /* Not done so IPC is still "busy" */ + priv_data->cb_ret = -EBUSY; + + break; + } + case INTEL_ADSP_IPC_CB_DONE: + if (wait_ack_sem) + k_sem_give(wait_ack_sem); + + priv_data->cb_ret = INTEL_ADSP_IPC_CB_RET_OKAY; + break; + default: + priv_data->cb_ret = -EINVAL; + break; + } +} + +static struct ipc_ept ipc_ept; +static struct intel_adsp_ipc_ept_priv_data ipc_ept_priv_data; +static struct ipc_ept_cfg ipc_ept_cfg = { + .name = "sof_ipc", + .cb = { + .received = ipc_receive_cb, + }, + .priv = &ipc_ept_priv_data, +}; + +static void ipc_ept_init(struct ipc *ipc) +{ + const struct device *ipc_dev = INTEL_ADSP_IPC_HOST_DEV; + + ipc_ept_priv_data.priv = ipc; + + ipc_service_register_endpoint(ipc_dev, &ipc_ept, &ipc_ept_cfg); +} + +static void ipc_complete(void) +{ + ipc_service_send(&ipc_ept, NULL, INTEL_ADSP_IPC_SEND_DONE); +} + +static bool ipc_is_complete(void) +{ + return ipc_service_send(&ipc_ept, NULL, INTEL_ADSP_IPC_SEND_IS_COMPLETE) == 0; +} + +static int ipc_send_message(uint32_t data, uint32_t ext_data) +{ + struct intel_adsp_ipc_msg msg = {.data = data, .ext_data = ext_data}; + + return ipc_service_send(&ipc_ept, &msg, INTEL_ADSP_IPC_SEND_MSG); +} + +void ipc_send_message_emergency(uint32_t data, uint32_t ext_data) +{ + struct intel_adsp_ipc_msg msg = {.data = data, .ext_data = ext_data}; + + ipc_service_send(&ipc_ept, &msg, INTEL_ADSP_IPC_SEND_MSG_EMERGENCY); } #ifdef CONFIG_PM_DEVICE @@ -159,8 +227,8 @@ static int ipc_device_resume_handler(const struct device *dev, void *arg) ipc->task_mask = 0; ipc->pm_prepare_D3 = false; - /* attach handlers */ - intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, message_handler, ipc); + /* initialize IPC endpoint */ + ipc_ept_init(ipc); /* schedule task */ #if CONFIG_TWB_IPC_TASK @@ -254,7 +322,7 @@ enum task_state ipc_platform_do_cmd(struct ipc *ipc) void ipc_platform_complete_cmd(struct ipc *ipc) { ARG_UNUSED(ipc); - intel_adsp_ipc_complete(INTEL_ADSP_IPC_HOST_DEV); + ipc_complete(); #if CONFIG_DEBUG_IPC_COUNTERS increment_ipc_processed_counter(); @@ -263,13 +331,13 @@ void ipc_platform_complete_cmd(struct ipc *ipc) int ipc_platform_send_msg(const struct ipc_msg *msg) { - if (!intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV)) + if (!ipc_is_complete()) return -EBUSY; /* prepare the message and copy to mailbox */ struct ipc_cmd_hdr *hdr = ipc_prepare_to_send(msg); - return intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, hdr->pri, hdr->ext); + return ipc_send_message(hdr->pri, hdr->ext); } void ipc_platform_send_msg_direct(const struct ipc_msg *msg) @@ -277,12 +345,12 @@ void ipc_platform_send_msg_direct(const struct ipc_msg *msg) /* prepare the message and copy to mailbox */ struct ipc_cmd_hdr *hdr = ipc_prepare_to_send(msg); - intel_adsp_ipc_send_message_emergency(INTEL_ADSP_IPC_HOST_DEV, hdr->pri, hdr->ext); + ipc_send_message_emergency(hdr->pri, hdr->ext); } int ipc_platform_poll_is_host_ready(void) { - return intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV); + return ipc_is_complete(); } int platform_ipc_init(struct ipc *ipc) @@ -300,8 +368,9 @@ int platform_ipc_init(struct ipc *ipc) #endif /* configure interrupt - work is done internally by Zephyr API */ - /* attach handlers */ - intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, message_handler, ipc); + /* initialize IPC endpoint */ + ipc_ept_init(ipc); + #ifdef CONFIG_PM intel_adsp_ipc_set_suspend_handler(INTEL_ADSP_IPC_HOST_DEV, ipc_device_suspend_handler, ipc); @@ -312,11 +381,13 @@ int platform_ipc_init(struct ipc *ipc) return 0; } +#ifdef CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE static bool ipc_wait_complete(const struct device *dev, void *arg) { k_sem_give(arg); return false; } +#endif void ipc_platform_wait_ack(struct ipc *ipc) { @@ -324,10 +395,18 @@ void ipc_platform_wait_ack(struct ipc *ipc) k_sem_init(&ipc_wait_sem, 0, 1); +#ifdef CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE intel_adsp_ipc_set_done_handler(INTEL_ADSP_IPC_HOST_DEV, ipc_wait_complete, &ipc_wait_sem); +#else + wait_ack_sem = &ipc_wait_sem; +#endif if (k_sem_take(&ipc_wait_sem, Z_TIMEOUT_MS(10)) == -EAGAIN) tr_err(&ipc_tr, "Timeout waiting for host ack!"); +#ifdef CONFIG_INTEL_ADSP_IPC_OLD_INTERFACE intel_adsp_ipc_set_done_handler(INTEL_ADSP_IPC_HOST_DEV, NULL, NULL); +#else + wait_ack_sem = NULL; +#endif } diff --git a/src/platform/intel/ace/lib/watchdog.c b/src/platform/intel/ace/lib/watchdog.c index dcae80da801d..2ee7369df3da 100644 --- a/src/platform/intel/ace/lib/watchdog.c +++ b/src/platform/intel/ace/lib/watchdog.c @@ -34,8 +34,7 @@ static void watchdog_primary_core_action_on_timeout(void) /* Send Watchdog Timeout IPC notification */ ipc4_notification_watchdog_init(¬if, cpu_get_id(), true); - intel_adsp_ipc_send_message_emergency(INTEL_ADSP_IPC_HOST_DEV, - notif.primary.dat, notif.extension.dat); + (void)ipc_send_message_emergency(notif.primary.dat, notif.extension.dat); } static void watchdog_secondary_core_action_on_timeout(void)