1 /*
2  * Copyright (c) 2024, Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/drivers/mbox.h>
10 
11 int dummy_value;
12 
13 #if defined(CONFIG_SOC_NRF54L05) || defined(CONFIG_SOC_NRF54L10) || \
14 	defined(CONFIG_SOC_NRF54L15) || defined(CONFIG_SOC_NRF54H20)
15 #define EXPECTED_MTU_VALUE				(0)
16 #define DATA_TRANSFER_MODE_SUPPORTED	(0)
17 #define REMOTE_BUSY_SUPPORTED			(0)
18 #else
19 #define EXPECTED_MTU_VALUE				(4)
20 #define DATA_TRANSFER_MODE_SUPPORTED	(1)
21 #define REMOTE_BUSY_SUPPORTED			(1)
22 #endif
23 
dummy_callback(const struct device * dev,mbox_channel_id_t channel_id,void * user_data,struct mbox_msg * data)24 static void dummy_callback(const struct device *dev, mbox_channel_id_t channel_id,
25 		     void *user_data, struct mbox_msg *data)
26 {
27 	ARG_UNUSED(dev);
28 	ARG_UNUSED(channel_id);
29 	ARG_UNUSED(user_data);
30 	ARG_UNUSED(data);
31 	/* Nothing here */
32 }
33 
dummy_callback_2(const struct device * dev,mbox_channel_id_t channel_id,void * user_data,struct mbox_msg * data)34 static void dummy_callback_2(const struct device *dev, mbox_channel_id_t channel_id,
35 		     void *user_data, struct mbox_msg *data)
36 {
37 	ARG_UNUSED(dev);
38 	ARG_UNUSED(channel_id);
39 	ARG_UNUSED(data);
40 
41 	int *temp = (int *) user_data;
42 	(*temp)++;
43 }
44 
45 /**
46  * @brief mbox_is_ready_dt() positive test
47  *
48  * Confirm that mbox_is_ready_dt() returns True
49  * on valid local and remote mbox channels.
50  *
51  */
ZTEST(mbox_error_cases,test_01a_mbox_is_ready_positive)52 ZTEST(mbox_error_cases, test_01a_mbox_is_ready_positive)
53 {
54 	const struct mbox_dt_spec rx_channel =
55 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), local_valid);
56 	const struct mbox_dt_spec tx_channel =
57 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), remote_valid);
58 	bool ret;
59 
60 	ret = mbox_is_ready_dt(&tx_channel);
61 	zassert_true(
62 		ret,
63 		"mbox_is_ready_dt(tx_channel) should return True,"
64 		" got unexpected value of %d",
65 		ret
66 	);
67 
68 	ret = mbox_is_ready_dt(&rx_channel);
69 	zassert_true(
70 		ret,
71 		"mbox_is_ready_dt(rx_channel) should return True,"
72 		" got unexpected value of %d",
73 		ret
74 	);
75 }
76 
77 /**
78  * @brief mbox_is_ready_dt() on incorrect channels
79  *
80  * Confirm that mbox_is_ready_dt() returns True
81  * on invalid local and remote mbox channel.
82  * (Device is ready, channel is not checked.)
83  *
84  */
ZTEST(mbox_error_cases,test_01b_mbox_is_ready_negative)85 ZTEST(mbox_error_cases, test_01b_mbox_is_ready_negative)
86 {
87 	const struct mbox_dt_spec rx_channel =
88 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), local_incorrect);
89 	const struct mbox_dt_spec tx_channel =
90 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), remote_incorrect);
91 	bool ret;
92 
93 	ret = mbox_is_ready_dt(&tx_channel);
94 	zassert_true(
95 		ret,
96 		"mbox_is_ready_dt(tx_invalid_channel) should return True,"
97 		" got unexpected value of %d",
98 		ret
99 	);
100 
101 	ret = mbox_is_ready_dt(&rx_channel);
102 	zassert_true(
103 		ret,
104 		"mbox_is_ready_dt(rx_invalid_channel) should return True,"
105 		" got unexpected value of %d", ret
106 	);
107 }
108 
109 /**
110  * @brief mbox_send_dt() on invalid TX channel shall fail
111  *
112  * Confirm that mbox_send_dt() returns
113  * -EINVAL when TX channel is invalid.
114  *
115  */
ZTEST(mbox_error_cases,test_02a_mbox_send_on_invalid_tx_channel)116 ZTEST(mbox_error_cases, test_02a_mbox_send_on_invalid_tx_channel)
117 {
118 	const struct mbox_dt_spec tx_channel =
119 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), remote_incorrect);
120 	int ret;
121 
122 	ret = mbox_send_dt(&tx_channel, NULL);
123 	zassert_true(
124 		(ret == -EINVAL),
125 		"mbox_send_dt(incorrect_tx_channel) shall return -EINVAL (-22)"
126 		" got unexpected %d",
127 		ret
128 	);
129 }
130 
131 /**
132  * @brief mbox_send_dt() on RX channel shall fail
133  *
134  * Confirm that mbox_send_dt() returns
135  * -ENOSYS when user tries to send on RX channel.
136  *
137  */
ZTEST(mbox_error_cases,test_02b_mbox_send_on_rx_channel)138 ZTEST(mbox_error_cases, test_02b_mbox_send_on_rx_channel)
139 {
140 	const struct mbox_dt_spec rx_channel =
141 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), local_valid);
142 	int ret;
143 
144 	ret = mbox_send_dt(&rx_channel, NULL);
145 	zassert_true(
146 		(ret == -ENOSYS),
147 		"mbox_send_dt(rx_channel) shall return -ENOSYS (-88)"
148 		" got unexpected %d",
149 		ret
150 	);
151 }
152 
153 /**
154  * @brief mbox_send_dt() with nonzero data field
155  *
156  * Confirm that mbox_send_dt() returns
157  * -EMSGSIZE when driver does NOT support DATA transfer.
158  *
159  */
ZTEST(mbox_error_cases,test_02c_mbox_send_message_with_data)160 ZTEST(mbox_error_cases, test_02c_mbox_send_message_with_data)
161 {
162 	const struct mbox_dt_spec tx_channel =
163 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), remote_valid);
164 	struct mbox_msg data_msg = {0};
165 	int ret;
166 
167 	if (DATA_TRANSFER_MODE_SUPPORTED) {
168 		/* Skip this test because data transfer is supported. */
169 		ztest_test_skip();
170 	}
171 
172 	data_msg.data = &dummy_value;
173 	data_msg.size = 4;
174 
175 	ret = mbox_send_dt(&tx_channel, &data_msg);
176 	zassert_true(
177 		(ret == -EMSGSIZE),
178 		"mbox_send_dt(rx_channel, data) shall return -EMSGSIZE (-122)"
179 		" got unexpected %d",
180 		ret
181 	);
182 }
183 
184 /**
185  * @brief mbox_send_dt() remote busy
186  *
187  * Confirm that mbox_send_dt() returns
188  * -EBUSY when remote hasn’t yet read the last data sent.
189  *
190  */
ZTEST(mbox_error_cases,test_02d_mbox_send_message_remote_busy)191 ZTEST(mbox_error_cases, test_02d_mbox_send_message_remote_busy)
192 {
193 	const struct mbox_dt_spec tx_channel =
194 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), remote_valid);
195 	int ret;
196 
197 	if (!REMOTE_BUSY_SUPPORTED)	{
198 		/* Skip this test because driver is not
199 		 * capable of detecting that remote is busy.
200 		 */
201 		ztest_test_skip();
202 	}
203 
204 	ret = mbox_send_dt(&tx_channel, NULL);
205 	zassert_true(
206 		(ret == 0),
207 		"mbox_send_dt(rx_channel) shall return 0"
208 		" got unexpected %d",
209 		ret
210 	);
211 
212 	ret = mbox_send_dt(&tx_channel, NULL);
213 	zassert_true(
214 		(ret == -EBUSY),
215 		"mbox_send_dt(rx_channel) shall return -EBUSY (-16)"
216 		" got unexpected %d",
217 		ret
218 	);
219 }
220 
221 /**
222  * @brief mbox_register_callback_dt() on TX channel shall fail
223  *
224  * Confirm that mbox_register_callback_dt() returns
225  * -ENOSYS when user tries to register callback on TX mbox channel.
226  *
227  */
ZTEST(mbox_error_cases,test_03a_mbox_register_callback_on_remote_channel)228 ZTEST(mbox_error_cases, test_03a_mbox_register_callback_on_remote_channel)
229 {
230 	const struct mbox_dt_spec tx_channel =
231 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), remote_valid);
232 	int ret;
233 
234 	ret = mbox_register_callback_dt(&tx_channel, dummy_callback, NULL);
235 	zassert_true(
236 		(ret == -ENOSYS),
237 		"mbox_register_callback(remote_channel) shall return -ENOSYS (-88)"
238 		" got unexpected %d",
239 		ret
240 	);
241 }
242 
243 /**
244  * @brief mbox_register_callback_dt() on incorrect channel shall fail
245  *
246  * Confirm that mbox_register_callback_dt() returns
247  * -EINVAL when user tries to register callback on incorrect mbox channel.
248  *
249  */
ZTEST(mbox_error_cases,test_03b_mbox_register_callback_on_invalid_channel)250 ZTEST(mbox_error_cases, test_03b_mbox_register_callback_on_invalid_channel)
251 {
252 	const struct mbox_dt_spec rx_channel =
253 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), local_incorrect);
254 	int ret;
255 
256 	ret = mbox_register_callback_dt(&rx_channel, dummy_callback, NULL);
257 	zassert_true(
258 		(ret == -EINVAL),
259 		"mbox_register_callback(incorrect_channel) shall return -EINVAL (-22)"
260 		" got unexpected %d",
261 		ret
262 	);
263 }
264 
265 /**
266  * @brief mbox_register_callback_dt() multiple use on same channel
267  *
268  * Confirm that mbox_register_callback_dt() returns
269  * 0 when user tries to register callback
270  * on already configured mbox channel.
271  *
272  */
ZTEST(mbox_error_cases,test_03c_mbox_register_callback_twice_on_same_channel)273 ZTEST(mbox_error_cases, test_03c_mbox_register_callback_twice_on_same_channel)
274 {
275 	const struct mbox_dt_spec rx_channel =
276 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), local_valid);
277 	int ret;
278 
279 	ret = mbox_register_callback_dt(&rx_channel, dummy_callback, NULL);
280 	zassert_true(
281 		(ret == 0),
282 		"mbox_register_callback(valid_channel) shall return 0"
283 		" got unexpected %d",
284 		ret
285 	);
286 
287 	ret = mbox_register_callback_dt(&rx_channel, dummy_callback_2, &dummy_value);
288 	zassert_true(
289 		(ret == 0),
290 		"mbox_register_callback(valid_channel) shall return 0"
291 		" got unexpected %d",
292 		ret
293 	);
294 }
295 
296 /**
297  * @brief mbox_mtu_get_dt() on RX channel shall fail
298  *
299  * Confirm that mbox_mtu_get_dt() returns
300  * -ENOSYS for RX mbox channel.
301  *
302  */
ZTEST(mbox_error_cases,test_04a_mbox_mtu_get_on_rx_channel)303 ZTEST(mbox_error_cases, test_04a_mbox_mtu_get_on_rx_channel)
304 {
305 	const struct mbox_dt_spec rx_channel =
306 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), local_valid);
307 	int ret;
308 
309 	ret = mbox_mtu_get_dt(&rx_channel);
310 	zassert_true(
311 		(ret == -ENOSYS),
312 		"mbox_mtu_get_dt(rx_channel) shall return -ENOSYS (-88)"
313 		" got unexpected %d",
314 		ret
315 	);
316 }
317 
318 /**
319  * @brief mbox_mtu_get_dt() on TX channel functional test
320  *
321  * Confirm that mbox_mtu_get_dt() returns
322  * expected value for TX mbox channel.
323  * (No matter if channel is valid or incorrect.)
324  *
325  */
ZTEST(mbox_error_cases,test_04b_mbox_mtu_get_on_tx_channel)326 ZTEST(mbox_error_cases, test_04b_mbox_mtu_get_on_tx_channel)
327 {
328 	const struct mbox_dt_spec tx_channel =
329 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), remote_valid);
330 	const struct mbox_dt_spec tx_channel_incorrect =
331 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), remote_incorrect);
332 	int ret;
333 
334 	ret = mbox_mtu_get_dt(&tx_channel);
335 	zassert_true(
336 		(ret == EXPECTED_MTU_VALUE),
337 		"mbox_mtu_get_dt(tx_channel) shall return %d"
338 		" got unexpected %d",
339 		EXPECTED_MTU_VALUE,
340 		ret
341 	);
342 
343 	ret = mbox_mtu_get_dt(&tx_channel_incorrect);
344 	zassert_true(
345 		(ret == EXPECTED_MTU_VALUE),
346 		"mbox_mtu_get_dt(tx_channel_incorrect) shall return %d"
347 		" got unexpected %d",
348 		EXPECTED_MTU_VALUE,
349 		ret
350 	);
351 }
352 
353 /**
354  * @brief mbox_set_enabled_dt() - Enable TX channel shall fail
355  *
356  * Confirm that mbox_set_enabled_dt() returns
357  * -ENOSYS for TX mbox channel.
358  *
359  */
ZTEST(mbox_error_cases,test_05a_mbox_set_enabled_on_tx_channel)360 ZTEST(mbox_error_cases, test_05a_mbox_set_enabled_on_tx_channel)
361 {
362 	const struct mbox_dt_spec tx_channel =
363 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), remote_valid);
364 	int ret;
365 
366 	ret = mbox_set_enabled_dt(&tx_channel, true);
367 	zassert_true(
368 		(ret == -ENOSYS),
369 		"mbox_set_enabled_dt(tx_channel, true) shall return -ENOSYS (-88)"
370 		" got unexpected %d",
371 		ret
372 	);
373 }
374 
375 /**
376  * @brief mbox_set_enabled_dt() - Enable incorrect channel shall fail
377  *
378  * Confirm that mbox_set_enabled_dt() returns
379  * -EINVAL for incorrect RX mbox channel.
380  *
381  */
ZTEST(mbox_error_cases,test_05b_mbox_set_enabled_on_incorrect_rx_channel)382 ZTEST(mbox_error_cases, test_05b_mbox_set_enabled_on_incorrect_rx_channel)
383 {
384 	const struct mbox_dt_spec rx_channel =
385 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), local_incorrect);
386 	int ret;
387 
388 	ret = mbox_set_enabled_dt(&rx_channel, true);
389 	zassert_true(
390 		(ret == -EINVAL),
391 		"mbox_set_enabled_dt(incorrect_channel, true) shall return -EINVAL (-22)"
392 		" got unexpected %d",
393 		ret
394 	);
395 }
396 
397 /**
398  * @brief mbox_set_enabled_dt() - Enable already enabled channel shall fail
399  *
400  * Confirm that mbox_set_enabled_dt() returns
401  * -EALREADY when user tries to enable already enabled RX mbox channel.
402  *
403  */
ZTEST(mbox_error_cases,test_05c_mbox_set_enabled_on_already_enabled_rx_channel)404 ZTEST(mbox_error_cases, test_05c_mbox_set_enabled_on_already_enabled_rx_channel)
405 {
406 	const struct mbox_dt_spec rx_channel =
407 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), local_valid);
408 	int ret;
409 
410 	/* The user must take care of installing a proper callback
411 	 * on the channel before enabling it.
412 	 */
413 	ret = mbox_register_callback_dt(&rx_channel, dummy_callback, NULL);
414 	zassert_true(
415 		(ret == 0),
416 		"mbox_register_callback(tx_channel) shall return 0"
417 		" got unexpected %d",
418 		ret
419 	);
420 
421 	ret = mbox_set_enabled_dt(&rx_channel, true);
422 	zassert_true(
423 		(ret == 0),
424 		"mbox_set_enabled_dt(tx_channel, true) shall return 0"
425 		" got unexpected %d",
426 		ret
427 	);
428 
429 	ret = mbox_set_enabled_dt(&rx_channel, true);
430 	zassert_true(
431 		(ret == -EALREADY),
432 		"mbox_set_enabled_dt(enabled_tx_channel, true) shall return -EALREADY (-120)"
433 		" got unexpected %d",
434 		ret
435 	);
436 
437 	/* Cleanup - disable mbox channel */
438 	ret = mbox_set_enabled_dt(&rx_channel, false);
439 	zassert_true(
440 		(ret == 0),
441 		"mbox_set_enabled_dt(enabled_tx_channel, false) shall return 0"
442 		" got unexpected %d",
443 		ret
444 	);
445 }
446 
447 /**
448  * @brief mbox_set_enabled_dt() - Dsiable already disabled channel shall fail
449  *
450  * Confirm that mbox_set_enabled_dt() returns
451  * -EALREADY when user tries to disable already disabled RX mbox channel.
452  *
453  */
ZTEST(mbox_error_cases,test_05d_mbox_set_disable_on_already_disabled_rx_channel)454 ZTEST(mbox_error_cases, test_05d_mbox_set_disable_on_already_disabled_rx_channel)
455 {
456 	const struct mbox_dt_spec rx_channel =
457 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), local_valid);
458 	int ret;
459 
460 	/* The user must take care of installing a proper callback
461 	 * on the channel before enabling it.
462 	 */
463 	ret = mbox_register_callback_dt(&rx_channel, dummy_callback, NULL);
464 	zassert_true(
465 		(ret == 0),
466 		"mbox_register_callback(tx_channel) shall return 0"
467 		" got unexpected %d",
468 		ret
469 	);
470 
471 	ret = mbox_set_enabled_dt(&rx_channel, true);
472 	zassert_true(
473 		(ret == 0),
474 		"mbox_set_enabled_dt(tx_channel, true) shall return 0"
475 		" got unexpected %d",
476 		ret
477 	);
478 
479 	ret = mbox_set_enabled_dt(&rx_channel, false);
480 	zassert_true(
481 		(ret == 0),
482 		"mbox_set_enabled_dt(enabled_tx_channel, false) shall return 0"
483 		" got unexpected %d",
484 		ret
485 	);
486 
487 	ret = mbox_set_enabled_dt(&rx_channel, false);
488 	zassert_true(
489 		(ret == -EALREADY),
490 		"mbox_set_enabled_dt(disabled_tx_channel, false) shall return -EALREADY (-120)"
491 		" got unexpected %d",
492 		ret
493 	);
494 }
495 
496 /**
497  * @brief mbox_max_channels_get_dt() functional test
498  *
499  * Confirm that mbox_max_channels_get_dt() returns
500  * >0 Maximum possible number of supported channels on success
501  * (No matter if channel is valid or incorrect.)
502  *
503  */
ZTEST(mbox_error_cases,test_06_mbox_max_channels_get_functional)504 ZTEST(mbox_error_cases, test_06_mbox_max_channels_get_functional)
505 {
506 	const struct mbox_dt_spec tx_channel =
507 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), remote_valid);
508 	const struct mbox_dt_spec tx_channel_incorrect =
509 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), remote_incorrect);
510 	const struct mbox_dt_spec rx_channel =
511 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), local_valid);
512 	const struct mbox_dt_spec rx_channel_incorrect =
513 		MBOX_DT_SPEC_GET(DT_PATH(mbox_consumer), local_incorrect);
514 	int ret1, ret2;
515 
516 	ret1 = mbox_max_channels_get_dt(&tx_channel);
517 	TC_PRINT("mbox_max_channels_get_dt(tx_channel): %d\n", ret1);
518 	zassert_true(
519 		(ret1 > 0),
520 		"mbox_max_channels_get_dt(tx_channel) shall return value greater than 0"
521 		" got unexpected %d",
522 		ret1
523 	);
524 
525 	ret2 = mbox_max_channels_get_dt(&tx_channel_incorrect);
526 	TC_PRINT("mbox_max_channels_get_dt(tx_channel_incorrect): %d\n", ret2);
527 	zassert_true(
528 		(ret2 > 0),
529 		"mbox_max_channels_get_dt(tx_channel_incorrect) shall return value greater than 0"
530 		" got unexpected %d",
531 		ret2
532 	);
533 
534 	zassert_true(
535 		(ret1 == ret2),
536 		"mbox_max_channels_get_dt() shall return same value disregarding channel No."
537 		" got unexpected %d and %d",
538 		ret1,
539 		ret2
540 	);
541 
542 	ret1 = mbox_max_channels_get_dt(&rx_channel);
543 	TC_PRINT("mbox_max_channels_get_dt(rx_channel): %d\n", ret1);
544 	zassert_true(
545 		(ret1 > 0),
546 		"mbox_max_channels_get_dt(rx_channel) shall return value greater than 0"
547 		" got unexpected %d",
548 		ret1
549 	);
550 
551 	ret2 = mbox_max_channels_get_dt(&rx_channel_incorrect);
552 	TC_PRINT("mbox_max_channels_get_dt(rx_channel_incorrect): %d\n", ret2);
553 	zassert_true(
554 		(ret2 > 0),
555 		"mbox_max_channels_get_dt(rx_channel_incorrect) shall return value greater than 0"
556 		" got unexpected %d",
557 		ret2
558 	);
559 
560 	zassert_true(
561 		(ret1 == ret2),
562 		"mbox_max_channels_get_dt() shall return same value disregarding channel No."
563 		" got unexpected %d and %d",
564 		ret1,
565 		ret2
566 	);
567 }
568 
suite_setup(void)569 static void *suite_setup(void)
570 {
571 	TC_PRINT("Test executed on %s\n", CONFIG_BOARD_TARGET);
572 	TC_PRINT("===================================================================\n");
573 
574 	return NULL;
575 }
576 
577 ZTEST_SUITE(mbox_error_cases, NULL, suite_setup, NULL, NULL, NULL);
578