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 <stdlib.h>
7 #include "tests.h"
8 
9 intel_adsp_ipc_handler_t ipm_handler;
10 
clock_msg(const struct device * dev,void * arg,uint32_t data,uint32_t ext_data)11 static bool clock_msg(const struct device *dev, void *arg,
12 		      uint32_t data, uint32_t ext_data)
13 {
14 	*(uint32_t *)arg = data;
15 	return true;
16 }
17 
ZTEST(intel_adsp,test_clock_calibrate)18 ZTEST(intel_adsp, test_clock_calibrate)
19 {
20 	static volatile uint32_t host_dt;
21 	uint32_t cyc0, cyc1, hz, diff;
22 
23 	/* Prime the host script's timestamp */
24 	cyc0 = k_cycle_get_32();
25 	intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_TIMESTAMP, 0);
26 
27 	k_msleep(1000);
28 	host_dt = 0;
29 	intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, clock_msg, (void *)&host_dt);
30 
31 	/* Now do it again, but with a handler to catch the result */
32 	cyc1 = k_cycle_get_32();
33 	intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, IPCCMD_TIMESTAMP, 0);
34 	AWAIT(host_dt != 0);
35 	intel_adsp_ipc_set_message_handler(INTEL_ADSP_IPC_HOST_DEV, NULL, NULL);
36 
37 	hz = 1000000ULL * (cyc1 - cyc0) / host_dt;
38 	printk("CLOCK: %lld Hz\n", (1000000ULL * (cyc1 - cyc0)) / host_dt);
39 
40 	/* Make sure we're within 1% of spec */
41 	diff = abs(hz - CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC);
42 	zassert_true((hz / MIN(1, diff)) > 100, "clock rate wrong");
43 }
44 
45 #if XCHAL_HAVE_VECBASE
ZTEST(intel_adsp,test_vecbase_lock)46 ZTEST(intel_adsp, test_vecbase_lock)
47 {
48 	uintptr_t vecbase;
49 
50 	/* Unfortunately there is not symbol to check if the target
51 	 * supports locking VECBASE. The best we can do is checking if
52 	 * the first is not set and skip the test.
53 	 */
54 	__asm__ volatile("rsr.vecbase %0" : "=r"(vecbase));
55 	if ((vecbase & 0x1) == 0) {
56 		ztest_test_skip();
57 	}
58 
59 	/* VECBASE register should have been locked during the cpu
60 	 * start up. Trying to change its location should fail.
61 	 */
62 	__asm__ volatile("wsr.vecbase %0; rsync" : : "r"(0x0));
63 	__asm__ volatile("rsr.vecbase %0" : "=r"(vecbase));
64 
65 	zassert_not_equal(vecbase, 0x0, "VECBASE was changed");
66 }
67 #endif
68 
intel_adsp_setup(void)69 static void *intel_adsp_setup(void)
70 {
71 	struct intel_adsp_ipc_data *devdata = INTEL_ADSP_IPC_HOST_DEV->data;
72 
73 	ipm_handler = devdata->handle_message;
74 
75 	return NULL;
76 }
77 
intel_adsp_teardown(void * data)78 static void intel_adsp_teardown(void *data)
79 {
80 	/* Wait a bit so the python script on host is ready to receive
81 	 * IPC messages. An IPC message could be used instead of a timer,
82 	 * but expecting IPC to be working on a test suite that is going
83 	 * to test IPC may not be indicated.
84 	 */
85 	k_msleep(1000);
86 }
87 
88 ZTEST_SUITE(intel_adsp, NULL, intel_adsp_setup, NULL, NULL,
89 		intel_adsp_teardown);
90 
91 ZTEST_SUITE(intel_adsp_boot, NULL, intel_adsp_setup, NULL, NULL, NULL);
92