From a7a212866c9c718d0b0930b8258a1fab0b923a09 Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Tue, 9 Dec 2025 15:56:36 +0100 Subject: [PATCH 1/2] [DNM] west: test PR 100682 PR with changes in IPC backend. Signed-off-by: Tomasz Leman --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 0bd10446385e..0111d2accd7e 100644 --- a/west.yml +++ b/west.yml @@ -43,7 +43,7 @@ manifest: - name: zephyr repo-path: zephyr - revision: 769ba82aa5ec482af0c4649ba075065e901fbe69 + revision: pull/100682/head remote: zephyrproject # Import some projects listed in zephyr/west.yml@revision From 96221b493d17246e82e44c38ff517ffc7b95041c Mon Sep 17 00:00:00 2001 From: Tomasz Leman Date: Tue, 9 Dec 2025 11:41:39 +0100 Subject: [PATCH 2/2] sof: ipc: switch platform IPC to Zephyr service This patch reworks the SOF IPC platform integration to use the generic Zephyr ipc_service instead of the Intel audio DSP specific driver. Before this change SOF was talking directly to the Intel ADSP IPC driver, which made the IPC path tightly coupled to that particular backend. All commands were sent and completed via intel_adsp_ipc_*() functions. The code now sends and receives IPC commands through a Zephyr ipc_service endpoint registered on the Intel ADSP host IPC instance, using sof_ipc_receive_cb() as the receive handler. Incoming messages are processed as before using the existing compact IPC path to process commands. Each IPC command is treated as a compact two-word ipc_cmd_hdr and a BUILD_ASSERT guarantees that the header size remains aligned with the transport format assumptions. This change is part of ongoing work to better integrate SOF with Zephyr and will allow other vendors to more easily integrate their own IPC backends. Signed-off-by: Tomasz Leman --- src/ipc/ipc-zephyr.c | 61 +++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/src/ipc/ipc-zephyr.c b/src/ipc/ipc-zephyr.c index 460089414cf7..52f0494273ba 100644 --- a/src/ipc/ipc-zephyr.c +++ b/src/ipc/ipc-zephyr.c @@ -12,8 +12,9 @@ #include #include +#include +#include -#include #include #include @@ -58,25 +59,32 @@ LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); * When IPC message is read fills ipc_cmd_hdr. */ static uint32_t g_last_data, g_last_ext_data; +static struct ipc_ept sof_ipc_ept; +static struct ipc_ept_cfg sof_ipc_ept_cfg; + +BUILD_ASSERT(sizeof(struct ipc_cmd_hdr) == sizeof(uint32_t) * 2, + "ipc_cmd_hdr must be exactly two 32-bit words"); /** - * @brief cAVS IPC Message Handler Callback function. + * @brief SOF IPC receive callback for Zephyr IPC service. * - * 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 - * will remain set until message would have been processed by scheduled task, i.e. - * until ipc_platform_complete_cmd() call. + * This callback is invoked by the Zephyr IPC service backend when a compact 2-word IPC message + * arrives from the host. It stores the raw header words in g_last_data/g_last_ext_data and + * schedules the SOF IPC task to process the command via ipc_platform_do_cmd(). */ -static bool message_handler(const struct device *dev, void *arg, uint32_t data, uint32_t ext_data) +static void sof_ipc_receive_cb(const void *data, size_t len, void *priv) { - struct ipc *ipc = (struct ipc *)arg; - + struct ipc *ipc = (struct ipc *)priv; + const uint32_t *msg = data; k_spinlock_key_t key; + __ASSERT(len == sizeof(uint32_t) * 2, "Unexpected IPC message length: %zu", len); + __ASSERT(data, "IPC data pointer is NULL"); + key = k_spin_lock(&ipc->lock); - g_last_data = data; - g_last_ext_data = ext_data; + g_last_data = msg[0]; + g_last_ext_data = msg[1]; #if CONFIG_DEBUG_IPC_COUNTERS increment_ipc_received_counter(); @@ -84,8 +92,6 @@ static bool message_handler(const struct device *dev, void *arg, uint32_t data, ipc_schedule_process(ipc); k_spin_unlock(&ipc->lock, key); - - return false; } #ifdef CONFIG_PM_DEVICE @@ -159,9 +165,6 @@ 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); - /* schedule task */ #if CONFIG_TWB_IPC_TASK scheduler_twb_task_init(&ipc->ipc_task, SOF_UUID(zipc_task_uuid), @@ -254,7 +257,9 @@ 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); + int ret = ipc_service_release_rx_buffer(&sof_ipc_ept, NULL); + + __ASSERT(ret == 0, "ipc_service_release_rx_buffer() failed: %d", ret); #if CONFIG_DEBUG_IPC_COUNTERS increment_ipc_processed_counter(); @@ -263,30 +268,31 @@ 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_service_get_tx_buffer_size(&sof_ipc_ept) == 0) 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_service_send(&sof_ipc_ept, hdr, sizeof(*hdr)); } 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); + (void)ipc_service_send_critical(&sof_ipc_ept, hdr, sizeof(*hdr)); } int ipc_platform_poll_is_host_ready(void) { - return intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV); + return ipc_service_get_tx_buffer_size(&sof_ipc_ept) > 0; } int platform_ipc_init(struct ipc *ipc) { + int ret; + ipc_set_drvdata(ipc, NULL); /* schedule task */ @@ -300,8 +306,15 @@ 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); + sof_ipc_ept_cfg.name = "sof_ipc"; + sof_ipc_ept_cfg.prio = 0; + sof_ipc_ept_cfg.cb.received = sof_ipc_receive_cb; + sof_ipc_ept_cfg.priv = ipc; + + ret = ipc_service_register_endpoint(INTEL_ADSP_IPC_HOST_DEV, + &sof_ipc_ept, &sof_ipc_ept_cfg); + if (ret < 0) + return ret; #ifdef CONFIG_PM intel_adsp_ipc_set_suspend_handler(INTEL_ADSP_IPC_HOST_DEV, ipc_device_suspend_handler, ipc);