blob: 1e80686547dbcacdf2818fbf72682e036b50d2f3 [file] [log] [blame]
/* Copyright (c) 2022 Intel Corporation
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
#include <drivers/ipm.h>
#include "tests.h"
#define IPM_DEV device_get_binding("ipm_cavs_host")
/* Two values impossible to transmit in a cAVS ID */
#define ID_INBOUND 0xfffffff0
#define ID_INVALID 0xffffffff
static K_SEM_DEFINE(ipm_sem, 0, 1);
static const uint32_t msg[] = { 29, 15, 58, 71, 99 };
static uint32_t received_id = ID_INVALID;
static volatile uint32_t *received_data;
static void ipm_msg(const struct device *ipmdev, void *user_data,
uint32_t id, volatile void *data)
{
zassert_equal(ipmdev, IPM_DEV, "wrong device");
zassert_equal(user_data, NULL, "wrong user_data pointer");
zassert_equal(received_id, ID_INBOUND, "unexpected message");
received_id = id;
received_data = data;
k_sem_give(&ipm_sem);
}
static void msg_transact(bool do_wait)
{
/* Send an IPCCMD_RETURN_MSG, this will send us a return
* message with msg[0] as the ID (on cAVS 1.8+, otherwise
* zero).
*/
received_id = ID_INBOUND;
ipm_send(IPM_DEV, do_wait, IPCCMD_RETURN_MSG, msg, sizeof(msg));
/* Wait for the return message */
k_sem_take(&ipm_sem, K_FOREVER);
zassert_equal(received_id,
IS_ENABLED(IPM_CAVS_HOST_REGWORD) ? msg[0] : 0,
"wrong return message ID");
received_id = ID_INVALID;
/* Now whitebox the message protocol: copy the message buffer
* (on the host side!) from the outbox to the inbox. That
* will write into our "already received" inbox buffer memory.
* We do this using the underlying cavs_ipc API, which works
* only because we know it works. Note that on cAVS 1.8+, the
* actual in-use amount of the message will be one word
* shorter (because the first word is sent as IPC ext_data),
* but it won't be inspected below.
*/
for (int i = 0; i < ARRAY_SIZE(msg); i++) {
cavs_ipc_send_message_sync(CAVS_HOST_DEV, IPCCMD_WINCOPY,
(i << 16) | i, K_FOREVER);
}
/* Validate data */
for (int i = 0; i < ARRAY_SIZE(msg); i++) {
zassert_equal(msg[i], received_data[i], "wrong message data");
}
}
/* This is a little whiteboxey. It relies on the knowledge that an
* IPM message is nothing but a IPC message with the "id" parameter
* passed as data (and, on cAVS 1.8+ only, the first word of the
* message buffer passed as ext_data).
*/
void test_ipm_cavs_host(void)
{
/* Restore IPM driver state (we've been mucking with cavs_ipc tests) */
cavs_ipc_set_message_handler(CAVS_HOST_DEV, ipm_handler, (void *)IPM_DEV);
cavs_ipc_set_done_handler(CAVS_HOST_DEV, NULL, NULL);
ipm_register_callback(IPM_DEV, ipm_msg, NULL);
/* Do it twice just for coverage on the wait parameter */
msg_transact(true);
msg_transact(false);
}