1 /* Copyright (c) 2022 Intel Corporation
2 * SPDX-License-Identifier: Apache-2.0
3 */
4 #include <zephyr/kernel.h>
5 #include <zephyr/ztest.h>
6 #include <intel_adsp_ipc.h>
7 #include "tests.h"
8
9 static volatile bool done_flag, msg_flag;
10
11 #define RETURN_MSG_SYNC_VAL 0x12345
12 #define RETURN_MSG_ASYNC_VAL 0x54321
13
ipc_message(const struct device * dev,void * arg,uint32_t data,uint32_t ext_data)14 static bool ipc_message(const struct device *dev, void *arg,
15 uint32_t data, uint32_t ext_data)
16 {
17 zassert_is_null(arg, "wrong message arg");
18 zassert_equal(data, ext_data, "unequal message data/ext_data");
19 zassert_true(data == RETURN_MSG_SYNC_VAL ||
20 data == RETURN_MSG_ASYNC_VAL, "unexpected msg data");
21 msg_flag = true;
22 return data == RETURN_MSG_SYNC_VAL;
23 }
24
ipc_done(const struct device * dev,void * arg)25 static bool ipc_done(const struct device *dev, void *arg)
26 {
27 zassert_is_null(arg, "wrong done arg");
28 zassert_false(done_flag, "done called unexpectedly");
29 done_flag = true;
30 return false;
31 }
32
ZTEST(intel_adsp,test_host_ipc)33 ZTEST(intel_adsp, test_host_ipc)
34 {
35 int ret;
36
37 intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, ipc_message, NULL);
38 intel_adsp_ipc_set_done_handler(INTEL_ADSP_IPC_HOST_DEV, ipc_done, NULL);
39
40 /* Just send a message and wait for it to complete */
41 printk("Simple message send...\n");
42 done_flag = false;
43 ret = intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_SIGNAL_DONE, 0);
44 zassert_true(!ret, "send failed");
45 AWAIT(intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV));
46 AWAIT(done_flag);
47
48 /* Request the host to return a message which we will complete
49 * immediately.
50 */
51 printk("Return message request...\n");
52 done_flag = false;
53 msg_flag = false;
54 ret = intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_RETURN_MSG,
55 RETURN_MSG_SYNC_VAL);
56 zassert_true(!ret, "send failed");
57 AWAIT(done_flag);
58 AWAIT(intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV));
59 AWAIT(msg_flag);
60
61 /* Do exactly the same thing again to check for state bugs
62 * (e.g. failing to signal done on one side or the other)
63 */
64 printk("Return message request 2...\n");
65 done_flag = false;
66 msg_flag = false;
67 ret = intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_RETURN_MSG,
68 RETURN_MSG_SYNC_VAL);
69 zassert_true(!ret, "send failed");
70 AWAIT(done_flag);
71 AWAIT(intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV));
72 AWAIT(msg_flag);
73
74 /* Same, but we'll complete it asynchronously (1.8+ only) */
75 printk("Return message request, async...\n");
76 done_flag = false;
77 msg_flag = false;
78 ret = intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_RETURN_MSG,
79 RETURN_MSG_ASYNC_VAL);
80 zassert_true(!ret, "send failed");
81 AWAIT(done_flag);
82 AWAIT(intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV));
83 AWAIT(msg_flag);
84 intel_adsp_ipc_complete(INTEL_ADSP_IPC_HOST_DEV);
85
86 /* Now make a synchronous call with (on the host) a delayed
87 * completion and make sure the interrupt fires and wakes us
88 * up. (On 1.5 a delay isn't possible and this will complete
89 * immediately).
90 */
91 printk("Synchronous message send...\n");
92 done_flag = false;
93 ret = intel_adsp_ipc_send_message_sync(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_ASYNC_DONE_DELAY,
94 0, K_FOREVER);
95 zassert_true(!ret, "send failed");
96 zassert_true(done_flag, "done interrupt failed to fire");
97 zassert_true(intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV),
98 "sync message incomplete");
99
100 /* Clean up. Further tests might want to use IPC */
101 intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, NULL, NULL);
102 intel_adsp_ipc_set_done_handler(INTEL_ADSP_IPC_HOST_DEV, NULL, NULL);
103 }
104