Skip to content

Commit 96221b4

Browse files
committed
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 <tomasz.m.leman@intel.com>
1 parent a7a2128 commit 96221b4

File tree

1 file changed

+37
-24
lines changed

1 file changed

+37
-24
lines changed

src/ipc/ipc-zephyr.c

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
#include <autoconf.h>
1313

1414
#include <zephyr/kernel.h>
15+
#include <zephyr/ipc/ipc_service.h>
16+
#include <zephyr/ipc/backends/intel_adsp_host_ipc.h>
1517

16-
#include <intel_adsp_ipc.h>
1718
#include <sof/ipc/common.h>
1819

1920
#include <sof/ipc/schedule.h>
@@ -58,34 +59,39 @@ LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL);
5859
* When IPC message is read fills ipc_cmd_hdr.
5960
*/
6061
static uint32_t g_last_data, g_last_ext_data;
62+
static struct ipc_ept sof_ipc_ept;
63+
static struct ipc_ept_cfg sof_ipc_ept_cfg;
64+
65+
BUILD_ASSERT(sizeof(struct ipc_cmd_hdr) == sizeof(uint32_t) * 2,
66+
"ipc_cmd_hdr must be exactly two 32-bit words");
6167

6268
/**
63-
* @brief cAVS IPC Message Handler Callback function.
69+
* @brief SOF IPC receive callback for Zephyr IPC service.
6470
*
65-
* See @ref (*intel_adsp_ipc_handler_t) for function signature description.
66-
* @return false so BUSY on the other side will not be cleared immediately but
67-
* will remain set until message would have been processed by scheduled task, i.e.
68-
* until ipc_platform_complete_cmd() call.
71+
* This callback is invoked by the Zephyr IPC service backend when a compact 2-word IPC message
72+
* arrives from the host. It stores the raw header words in g_last_data/g_last_ext_data and
73+
* schedules the SOF IPC task to process the command via ipc_platform_do_cmd().
6974
*/
70-
static bool message_handler(const struct device *dev, void *arg, uint32_t data, uint32_t ext_data)
75+
static void sof_ipc_receive_cb(const void *data, size_t len, void *priv)
7176
{
72-
struct ipc *ipc = (struct ipc *)arg;
73-
77+
struct ipc *ipc = (struct ipc *)priv;
78+
const uint32_t *msg = data;
7479
k_spinlock_key_t key;
7580

81+
__ASSERT(len == sizeof(uint32_t) * 2, "Unexpected IPC message length: %zu", len);
82+
__ASSERT(data, "IPC data pointer is NULL");
83+
7684
key = k_spin_lock(&ipc->lock);
7785

78-
g_last_data = data;
79-
g_last_ext_data = ext_data;
86+
g_last_data = msg[0];
87+
g_last_ext_data = msg[1];
8088

8189
#if CONFIG_DEBUG_IPC_COUNTERS
8290
increment_ipc_received_counter();
8391
#endif
8492
ipc_schedule_process(ipc);
8593

8694
k_spin_unlock(&ipc->lock, key);
87-
88-
return false;
8995
}
9096

9197
#ifdef CONFIG_PM_DEVICE
@@ -159,9 +165,6 @@ static int ipc_device_resume_handler(const struct device *dev, void *arg)
159165
ipc->task_mask = 0;
160166
ipc->pm_prepare_D3 = false;
161167

162-
/* attach handlers */
163-
intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, message_handler, ipc);
164-
165168
/* schedule task */
166169
#if CONFIG_TWB_IPC_TASK
167170
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)
254257
void ipc_platform_complete_cmd(struct ipc *ipc)
255258
{
256259
ARG_UNUSED(ipc);
257-
intel_adsp_ipc_complete(INTEL_ADSP_IPC_HOST_DEV);
260+
int ret = ipc_service_release_rx_buffer(&sof_ipc_ept, NULL);
261+
262+
__ASSERT(ret == 0, "ipc_service_release_rx_buffer() failed: %d", ret);
258263

259264
#if CONFIG_DEBUG_IPC_COUNTERS
260265
increment_ipc_processed_counter();
@@ -263,30 +268,31 @@ void ipc_platform_complete_cmd(struct ipc *ipc)
263268

264269
int ipc_platform_send_msg(const struct ipc_msg *msg)
265270
{
266-
if (!intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV))
271+
if (ipc_service_get_tx_buffer_size(&sof_ipc_ept) == 0)
267272
return -EBUSY;
268273

269274
/* prepare the message and copy to mailbox */
270275
struct ipc_cmd_hdr *hdr = ipc_prepare_to_send(msg);
271276

272-
return intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, hdr->pri, hdr->ext);
277+
return ipc_service_send(&sof_ipc_ept, hdr, sizeof(*hdr));
273278
}
274279

275280
void ipc_platform_send_msg_direct(const struct ipc_msg *msg)
276281
{
277282
/* prepare the message and copy to mailbox */
278283
struct ipc_cmd_hdr *hdr = ipc_prepare_to_send(msg);
279-
280-
intel_adsp_ipc_send_message_emergency(INTEL_ADSP_IPC_HOST_DEV, hdr->pri, hdr->ext);
284+
(void)ipc_service_send_critical(&sof_ipc_ept, hdr, sizeof(*hdr));
281285
}
282286

283287
int ipc_platform_poll_is_host_ready(void)
284288
{
285-
return intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV);
289+
return ipc_service_get_tx_buffer_size(&sof_ipc_ept) > 0;
286290
}
287291

288292
int platform_ipc_init(struct ipc *ipc)
289293
{
294+
int ret;
295+
290296
ipc_set_drvdata(ipc, NULL);
291297

292298
/* schedule task */
@@ -300,8 +306,15 @@ int platform_ipc_init(struct ipc *ipc)
300306
#endif
301307
/* configure interrupt - work is done internally by Zephyr API */
302308

303-
/* attach handlers */
304-
intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, message_handler, ipc);
309+
sof_ipc_ept_cfg.name = "sof_ipc";
310+
sof_ipc_ept_cfg.prio = 0;
311+
sof_ipc_ept_cfg.cb.received = sof_ipc_receive_cb;
312+
sof_ipc_ept_cfg.priv = ipc;
313+
314+
ret = ipc_service_register_endpoint(INTEL_ADSP_IPC_HOST_DEV,
315+
&sof_ipc_ept, &sof_ipc_ept_cfg);
316+
if (ret < 0)
317+
return ret;
305318
#ifdef CONFIG_PM
306319
intel_adsp_ipc_set_suspend_handler(INTEL_ADSP_IPC_HOST_DEV,
307320
ipc_device_suspend_handler, ipc);

0 commit comments

Comments
 (0)