blob: 49d440c53fff22eb150fa39a76a9d3db82c3690d [file] [log] [blame]
/* Copyright (c) 2022 Intel Corporation
* SPDX-License-Identifier: Apache-2.0
*/
#include <kernel.h>
#include <ztest.h>
#include <cavs_ipc.h>
#include "tests.h"
static volatile bool done_flag, msg_flag;
#define RETURN_MSG_SYNC_VAL 0x12345
#define RETURN_MSG_ASYNC_VAL 0x54321
static bool ipc_message(const struct device *dev, void *arg,
uint32_t data, uint32_t ext_data)
{
zassert_is_null(arg, "wrong message arg");
zassert_equal(data, ext_data, "unequal message data/ext_data");
zassert_true(data == RETURN_MSG_SYNC_VAL ||
data == RETURN_MSG_ASYNC_VAL, "unexpected msg data");
msg_flag = true;
return data == RETURN_MSG_SYNC_VAL;
}
static void ipc_done(const struct device *dev, void *arg)
{
zassert_is_null(arg, "wrong done arg");
zassert_false(done_flag, "done called unexpectedly");
done_flag = true;
}
void test_host_ipc(void)
{
bool ret;
cavs_ipc_set_message_handler(CAVS_HOST_DEV, ipc_message, NULL);
cavs_ipc_set_done_handler(CAVS_HOST_DEV, ipc_done, NULL);
/* Just send a message and wait for it to complete */
printk("Simple message send...\n");
done_flag = false;
ret = cavs_ipc_send_message(CAVS_HOST_DEV, IPCCMD_SIGNAL_DONE, 0);
zassert_true(ret, "send failed");
zassert_true(WAIT_FOR(cavs_ipc_is_complete(CAVS_HOST_DEV), 10000, k_msleep(1)), NULL);
zassert_true(WAIT_FOR(done_flag, 10000, k_msleep(1)), NULL);
/* Request the host to return a message which we will complete
* immediately.
*/
printk("Return message request...\n");
done_flag = false;
msg_flag = false;
ret = cavs_ipc_send_message(CAVS_HOST_DEV, IPCCMD_RETURN_MSG,
RETURN_MSG_SYNC_VAL);
zassert_true(ret, "send failed");
zassert_true(WAIT_FOR(done_flag, 10000, k_msleep(1)), NULL);
zassert_true(WAIT_FOR(cavs_ipc_is_complete(CAVS_HOST_DEV), 10000, k_msleep(1)), NULL);
zassert_true(WAIT_FOR(msg_flag, 10000, k_msleep(1)), NULL);
/* Do exactly the same thing again to check for state bugs
* (e.g. failing to signal done on one side or the other)
*/
printk("Return message request 2...\n");
done_flag = false;
msg_flag = false;
ret = cavs_ipc_send_message(CAVS_HOST_DEV, IPCCMD_RETURN_MSG,
RETURN_MSG_SYNC_VAL);
zassert_true(ret, "send failed");
zassert_true(WAIT_FOR(done_flag, 10000, k_msleep(1)), NULL);
zassert_true(WAIT_FOR(cavs_ipc_is_complete(CAVS_HOST_DEV), 10000, k_msleep(1)), NULL);
zassert_true(WAIT_FOR(msg_flag, 10000, k_msleep(1)), NULL);
/* Same, but we'll complete it asynchronously (1.8+ only) */
if (!IS_ENABLED(CONFIG_SOC_SERIES_INTEL_CAVS_V15)) {
printk("Return message request, async...\n");
done_flag = false;
msg_flag = false;
ret = cavs_ipc_send_message(CAVS_HOST_DEV, IPCCMD_RETURN_MSG,
RETURN_MSG_ASYNC_VAL);
zassert_true(ret, "send failed");
zassert_true(WAIT_FOR(done_flag, 10000, k_msleep(1)), NULL);
zassert_true(WAIT_FOR(cavs_ipc_is_complete(CAVS_HOST_DEV), 10000, k_msleep(1)),
NULL);
zassert_true(WAIT_FOR(msg_flag, 10000, k_msleep(1)), NULL);
cavs_ipc_complete(CAVS_HOST_DEV);
}
/* Now make a synchronous call with (on the host) a delayed
* completion and make sure the interrupt fires and wakes us
* up. (On 1.5 a delay isn't possible and this will complete
* immediately).
*/
printk("Synchronous message send...\n");
done_flag = false;
ret = cavs_ipc_send_message_sync(CAVS_HOST_DEV, IPCCMD_ASYNC_DONE_DELAY,
0, K_FOREVER);
zassert_true(ret, "send failed");
zassert_true(done_flag, "done interrupt failed to fire");
zassert_true(cavs_ipc_is_complete(CAVS_HOST_DEV), "sync message incomplete");
/* Clean up. Further tests might want to use IPC */
cavs_ipc_set_message_handler(CAVS_HOST_DEV, NULL, NULL);
cavs_ipc_set_done_handler(CAVS_HOST_DEV, NULL, NULL);
}