/* Copyright (c) 2022 Intel Corporation * SPDX-License-Identifier: Apache-2.0 */ #include #include #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 intel_adsp_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++) { intel_adsp_ipc_send_message_sync(INTEL_ADSP_IPC_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). */ ZTEST(intel_adsp, test_ipm_cavs_host) { /* Restore IPM driver state (we've been mucking with intel_adsp_ipc tests) */ intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, ipm_handler, (void *)IPM_DEV); intel_adsp_ipc_set_done_handler(INTEL_ADSP_IPC_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); }