1 /*
2  * Copyright (c) 2017 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_REGISTER(spi_loopback);
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/sys/printk.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <assert.h>
16 #include <zephyr/ztest.h>
17 
18 #include <zephyr/drivers/spi.h>
19 
20 #define SPI_FAST_DEV	DT_COMPAT_GET_ANY_STATUS_OKAY(test_spi_loopback_fast)
21 #define SPI_SLOW_DEV	DT_COMPAT_GET_ANY_STATUS_OKAY(test_spi_loopback_slow)
22 
23 #if CONFIG_SPI_LOOPBACK_MODE_LOOP
24 #define MODE_LOOP SPI_MODE_LOOP
25 #else
26 #define MODE_LOOP 0
27 #endif
28 
29 #ifdef CONFIG_SPI_LOOPBACK_16BITS_FRAMES
30 #define FRAME_SIZE (16)
31 #define FRAME_SIZE_STR ", frame size = 16"
32 #else
33 #define FRAME_SIZE (8)
34 #define FRAME_SIZE_STR ", frame size = 8"
35 #endif /* CONFIG_SPI_LOOPBACK_16BITS_FRAMES */
36 
37 #ifdef CONFIG_DMA
38 
39 #ifdef CONFIG_NOCACHE_MEMORY
40 #define DMA_ENABLED_STR ", DMA enabled"
41 #else /* CONFIG_NOCACHE_MEMORY */
42 #define DMA_ENABLED_STR ", DMA enabled (without CONFIG_NOCACHE_MEMORY)"
43 #endif
44 
45 #else /* CONFIG_DMA */
46 
47 #define DMA_ENABLED_STR
48 #endif /* CONFIG_DMA */
49 
50 #define SPI_OP(frame_size) SPI_OP_MODE_MASTER | SPI_MODE_CPOL | MODE_LOOP | \
51 	       SPI_MODE_CPHA | SPI_WORD_SET(frame_size) | SPI_LINES_SINGLE
52 
53 static struct spi_dt_spec spi_fast = SPI_DT_SPEC_GET(SPI_FAST_DEV, SPI_OP(FRAME_SIZE), 0);
54 static struct spi_dt_spec spi_slow = SPI_DT_SPEC_GET(SPI_SLOW_DEV, SPI_OP(FRAME_SIZE), 0);
55 
56 /* to run this test, connect MOSI pin to the MISO of the SPI */
57 
58 #define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
59 #define BUF_SIZE 18
60 #define BUF2_SIZE 36
61 
62 #if CONFIG_NOCACHE_MEMORY
63 #define __NOCACHE	__attribute__((__section__(".nocache")))
64 #elif defined(CONFIG_DT_DEFINED_NOCACHE)
65 #define __NOCACHE	__attribute__((__section__(CONFIG_DT_DEFINED_NOCACHE_NAME)))
66 #else /* CONFIG_NOCACHE_MEMORY */
67 #define __NOCACHE
68 #endif /* CONFIG_NOCACHE_MEMORY */
69 
70 static const char tx_data[BUF_SIZE] = "0123456789abcdef-\0";
71 static __aligned(32) char buffer_tx[BUF_SIZE] __used __NOCACHE;
72 static __aligned(32) char buffer_rx[BUF_SIZE] __used __NOCACHE;
73 static const char tx2_data[BUF2_SIZE] = "Thequickbrownfoxjumpsoverthelazydog\0";
74 static __aligned(32) char buffer2_tx[BUF2_SIZE] __used __NOCACHE;
75 static __aligned(32) char buffer2_rx[BUF2_SIZE] __used __NOCACHE;
76 
77 /*
78  * We need 5x(buffer size) + 1 to print a comma-separated list of each
79  * byte in hex, plus a null.
80  */
81 static uint8_t buffer_print_tx[BUF_SIZE * 5 + 1];
82 static uint8_t buffer_print_rx[BUF_SIZE * 5 + 1];
83 
84 static uint8_t buffer_print_tx2[BUF2_SIZE * 5 + 1];
85 static uint8_t buffer_print_rx2[BUF2_SIZE * 5 + 1];
86 
to_display_format(const uint8_t * src,size_t size,char * dst)87 static void to_display_format(const uint8_t *src, size_t size, char *dst)
88 {
89 	size_t i;
90 
91 	for (i = 0; i < size; i++) {
92 		sprintf(dst + 5 * i, "0x%02x,", src[i]);
93 	}
94 }
95 
96 /* test transferring different buffers on the same dma channels */
spi_complete_multiple(struct spi_dt_spec * spec)97 static int spi_complete_multiple(struct spi_dt_spec *spec)
98 {
99 	struct spi_buf tx_bufs[2];
100 	const struct spi_buf_set tx = {
101 		.buffers = tx_bufs,
102 		.count = ARRAY_SIZE(tx_bufs)
103 	};
104 
105 	tx_bufs[0].buf = buffer_tx;
106 	tx_bufs[0].len = BUF_SIZE;
107 
108 	tx_bufs[1].buf = buffer2_tx;
109 	tx_bufs[1].len = BUF2_SIZE;
110 
111 
112 	struct spi_buf rx_bufs[2];
113 	const struct spi_buf_set rx = {
114 		.buffers = rx_bufs,
115 		.count = ARRAY_SIZE(rx_bufs)
116 	};
117 
118 	rx_bufs[0].buf = buffer_rx;
119 	rx_bufs[0].len = BUF_SIZE;
120 
121 	rx_bufs[1].buf = buffer2_rx;
122 	rx_bufs[1].len = BUF2_SIZE;
123 
124 	int ret;
125 
126 	LOG_INF("Start complete multiple");
127 
128 	ret = spi_transceive_dt(spec, &tx, &rx);
129 	if (ret) {
130 		LOG_ERR("Code %d", ret);
131 		zassert_false(ret, "SPI transceive failed");
132 		return ret;
133 	}
134 
135 	if (memcmp(buffer_tx, buffer_rx, BUF_SIZE)) {
136 		to_display_format(buffer_tx, BUF_SIZE, buffer_print_tx);
137 		to_display_format(buffer_rx, BUF_SIZE, buffer_print_rx);
138 		LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
139 		LOG_ERR("                           vs: %s", buffer_print_rx);
140 		zassert_false(1, "Buffer contents are different");
141 		return -1;
142 	}
143 
144 	if (memcmp(buffer2_tx, buffer2_rx, BUF2_SIZE)) {
145 		to_display_format(buffer2_tx, BUF2_SIZE, buffer_print_tx2);
146 		to_display_format(buffer2_rx, BUF2_SIZE, buffer_print_rx2);
147 		LOG_ERR("Buffer 2 contents are different: %s", buffer_print_tx2);
148 		LOG_ERR("                             vs: %s", buffer_print_rx2);
149 		zassert_false(1, "Buffer 2 contents are different");
150 		return -1;
151 	}
152 
153 	LOG_INF("Passed");
154 
155 	return 0;
156 }
157 
spi_complete_loop(struct spi_dt_spec * spec)158 static int spi_complete_loop(struct spi_dt_spec *spec)
159 {
160 	const struct spi_buf tx_bufs[] = {
161 		{
162 			.buf = buffer_tx,
163 			.len = BUF_SIZE,
164 		},
165 	};
166 	const struct spi_buf rx_bufs[] = {
167 		{
168 			.buf = buffer_rx,
169 			.len = BUF_SIZE,
170 		},
171 	};
172 	const struct spi_buf_set tx = {
173 		.buffers = tx_bufs,
174 		.count = ARRAY_SIZE(tx_bufs)
175 	};
176 	const struct spi_buf_set rx = {
177 		.buffers = rx_bufs,
178 		.count = ARRAY_SIZE(rx_bufs)
179 	};
180 
181 	int ret;
182 
183 	LOG_INF("Start complete loop");
184 
185 	ret = spi_transceive_dt(spec, &tx, &rx);
186 	if (ret) {
187 		LOG_ERR("Code %d", ret);
188 		zassert_false(ret, "SPI transceive failed");
189 		return ret;
190 	}
191 
192 	if (memcmp(buffer_tx, buffer_rx, BUF_SIZE)) {
193 		to_display_format(buffer_tx, BUF_SIZE, buffer_print_tx);
194 		to_display_format(buffer_rx, BUF_SIZE, buffer_print_rx);
195 		LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
196 		LOG_ERR("                           vs: %s", buffer_print_rx);
197 		zassert_false(1, "Buffer contents are different");
198 		return -1;
199 	}
200 
201 	LOG_INF("Passed");
202 
203 	return 0;
204 }
205 
spi_null_tx_buf(struct spi_dt_spec * spec)206 static int spi_null_tx_buf(struct spi_dt_spec *spec)
207 {
208 	static const uint8_t EXPECTED_NOP_RETURN_BUF[BUF_SIZE] = { 0 };
209 
210 	(void)memset(buffer_rx, 0x77, BUF_SIZE);
211 
212 	const struct spi_buf tx_bufs[] = {
213 		/* According to documentation, when sending NULL tx buf -
214 		 *  NOP frames should be sent on MOSI line
215 		 */
216 		{
217 			.buf = NULL,
218 			.len = BUF_SIZE,
219 		},
220 	};
221 	const struct spi_buf rx_bufs[] = {
222 		{
223 			.buf = buffer_rx,
224 			.len = BUF_SIZE,
225 		},
226 	};
227 	const struct spi_buf_set tx = {
228 		.buffers = tx_bufs,
229 		.count = ARRAY_SIZE(tx_bufs)
230 	};
231 	const struct spi_buf_set rx = {
232 		.buffers = rx_bufs,
233 		.count = ARRAY_SIZE(rx_bufs)
234 	};
235 
236 	int ret;
237 
238 	LOG_INF("Start null tx");
239 
240 	ret = spi_transceive_dt(spec, &tx, &rx);
241 	if (ret) {
242 		LOG_ERR("Code %d", ret);
243 		zassert_false(ret, "SPI transceive failed");
244 		return ret;
245 	}
246 
247 
248 	if (memcmp(buffer_rx, EXPECTED_NOP_RETURN_BUF, BUF_SIZE)) {
249 		to_display_format(buffer_rx, BUF_SIZE, buffer_print_rx);
250 		LOG_ERR("Rx Buffer should contain NOP frames but got: %s",
251 			buffer_print_rx);
252 		zassert_false(1, "Buffer not as expected");
253 		return -1;
254 	}
255 
256 	LOG_INF("Passed");
257 
258 	return 0;
259 }
260 
spi_rx_half_start(struct spi_dt_spec * spec)261 static int spi_rx_half_start(struct spi_dt_spec *spec)
262 {
263 	const struct spi_buf tx_bufs[] = {
264 		{
265 			.buf = buffer_tx,
266 			.len = BUF_SIZE,
267 		},
268 	};
269 	const struct spi_buf rx_bufs[] = {
270 		{
271 			.buf = buffer_rx,
272 			.len = 8,
273 		},
274 	};
275 	const struct spi_buf_set tx = {
276 		.buffers = tx_bufs,
277 		.count = ARRAY_SIZE(tx_bufs)
278 	};
279 	const struct spi_buf_set rx = {
280 		.buffers = rx_bufs,
281 		.count = ARRAY_SIZE(rx_bufs)
282 	};
283 	int ret;
284 
285 	LOG_INF("Start half start");
286 
287 	(void)memset(buffer_rx, 0, BUF_SIZE);
288 
289 	ret = spi_transceive_dt(spec, &tx, &rx);
290 	if (ret) {
291 		LOG_ERR("Code %d", ret);
292 		zassert_false(ret, "SPI transceive failed");
293 		return -1;
294 	}
295 
296 	if (memcmp(buffer_tx, buffer_rx, 8)) {
297 		to_display_format(buffer_tx, 8, buffer_print_tx);
298 		to_display_format(buffer_rx, 8, buffer_print_rx);
299 		LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
300 		LOG_ERR("                           vs: %s", buffer_print_rx);
301 		zassert_false(1, "Buffer contents are different");
302 		return -1;
303 	}
304 
305 	LOG_INF("Passed");
306 
307 	return 0;
308 }
309 
spi_rx_half_end(struct spi_dt_spec * spec)310 static int spi_rx_half_end(struct spi_dt_spec *spec)
311 {
312 	const struct spi_buf tx_bufs[] = {
313 		{
314 			.buf = buffer_tx,
315 			.len = BUF_SIZE,
316 		},
317 	};
318 	const struct spi_buf rx_bufs[] = {
319 		{
320 			.buf = NULL,
321 			.len = 8,
322 		},
323 		{
324 			.buf = buffer_rx,
325 			.len = 8,
326 		},
327 	};
328 	const struct spi_buf_set tx = {
329 		.buffers = tx_bufs,
330 		.count = ARRAY_SIZE(tx_bufs)
331 	};
332 	const struct spi_buf_set rx = {
333 		.buffers = rx_bufs,
334 		.count = ARRAY_SIZE(rx_bufs)
335 	};
336 	int ret;
337 
338 	if (IS_ENABLED(CONFIG_SPI_STM32_DMA)) {
339 		LOG_INF("Skip half end");
340 		return 0;
341 	}
342 
343 	LOG_INF("Start half end");
344 
345 	(void)memset(buffer_rx, 0, BUF_SIZE);
346 
347 	ret = spi_transceive_dt(spec, &tx, &rx);
348 	if (ret) {
349 		LOG_ERR("Code %d", ret);
350 		zassert_false(ret, "SPI transceive failed");
351 		return -1;
352 	}
353 
354 	if (memcmp(buffer_tx + 8, buffer_rx, 8)) {
355 		to_display_format(buffer_tx + 8, 8, buffer_print_tx);
356 		to_display_format(buffer_rx, 8, buffer_print_rx);
357 		LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
358 		LOG_ERR("                           vs: %s", buffer_print_rx);
359 		zassert_false(1, "Buffer contents are different");
360 		return -1;
361 	}
362 
363 	LOG_INF("Passed");
364 
365 	return 0;
366 }
367 
spi_rx_every_4(struct spi_dt_spec * spec)368 static int spi_rx_every_4(struct spi_dt_spec *spec)
369 {
370 	const struct spi_buf tx_bufs[] = {
371 		{
372 			.buf = buffer_tx,
373 			.len = BUF_SIZE,
374 		},
375 	};
376 	const struct spi_buf rx_bufs[] = {
377 		{
378 			.buf = NULL,
379 			.len = 4,
380 		},
381 		{
382 			.buf = buffer_rx,
383 			.len = 4,
384 		},
385 		{
386 			.buf = NULL,
387 			.len = 4,
388 		},
389 		{
390 			.buf = buffer_rx + 4,
391 			.len = 4,
392 		},
393 	};
394 	const struct spi_buf_set tx = {
395 		.buffers = tx_bufs,
396 		.count = ARRAY_SIZE(tx_bufs)
397 	};
398 	const struct spi_buf_set rx = {
399 		.buffers = rx_bufs,
400 		.count = ARRAY_SIZE(rx_bufs)
401 	};
402 	int ret;
403 
404 	if (IS_ENABLED(CONFIG_SPI_STM32_DMA)) {
405 		LOG_INF("Skip every 4");
406 		return 0;
407 	}
408 
409 	if (IS_ENABLED(CONFIG_DSPI_MCUX_EDMA)) {
410 		LOG_INF("Skip every 4");
411 		return 0;
412 	}
413 
414 	LOG_INF("Start every 4");
415 
416 	(void)memset(buffer_rx, 0, BUF_SIZE);
417 
418 	ret = spi_transceive_dt(spec, &tx, &rx);
419 	if (ret) {
420 		LOG_ERR("Code %d", ret);
421 		zassert_false(ret, "SPI transceive failed");
422 		return -1;
423 	}
424 
425 	if (memcmp(buffer_tx + 4, buffer_rx, 4)) {
426 		to_display_format(buffer_tx + 4, 4, buffer_print_tx);
427 		to_display_format(buffer_rx, 4, buffer_print_rx);
428 		LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
429 		LOG_ERR("                           vs: %s", buffer_print_rx);
430 		zassert_false(1, "Buffer contents are different");
431 		return -1;
432 	} else if (memcmp(buffer_tx + 12, buffer_rx + 4, 4)) {
433 		to_display_format(buffer_tx + 12, 4, buffer_print_tx);
434 		to_display_format(buffer_rx + 4, 4, buffer_print_rx);
435 		LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
436 		LOG_ERR("                           vs: %s", buffer_print_rx);
437 		zassert_false(1, "Buffer contents are different");
438 		return -1;
439 	}
440 
441 	LOG_INF("Passed");
442 
443 	return 0;
444 }
445 
spi_rx_bigger_than_tx(struct spi_dt_spec * spec)446 static int spi_rx_bigger_than_tx(struct spi_dt_spec *spec)
447 {
448 	const uint32_t tx_buf_size = 8;
449 
450 	BUILD_ASSERT(tx_buf_size < BUF_SIZE,
451 		"Transmit buffer is expected to be smaller than the receive buffer");
452 
453 	const struct spi_buf tx_bufs[] = {
454 		{
455 			.buf = buffer_tx,
456 			.len = tx_buf_size,
457 		},
458 	};
459 	const struct spi_buf rx_bufs[] = {
460 		{
461 			.buf = buffer_rx,
462 			.len = BUF_SIZE,
463 		}
464 	};
465 	const struct spi_buf_set tx = {
466 		.buffers = tx_bufs,
467 		.count = ARRAY_SIZE(tx_bufs)
468 	};
469 	const struct spi_buf_set rx = {
470 		.buffers = rx_bufs,
471 		.count = ARRAY_SIZE(rx_bufs)
472 	};
473 	int ret;
474 
475 	if (IS_ENABLED(CONFIG_SPI_STM32_DMA)) {
476 		LOG_INF("Skip rx bigger than tx");
477 		return 0;
478 	}
479 
480 	LOG_INF("Start rx bigger than tx");
481 
482 	(void)memset(buffer_rx, 0xff, BUF_SIZE);
483 
484 	ret = spi_transceive_dt(spec, &tx, &rx);
485 	if (ret) {
486 		LOG_ERR("Code %d", ret);
487 		zassert_false(ret, "SPI transceive failed");
488 		return -1;
489 	}
490 
491 	if (memcmp(buffer_tx, buffer_rx, tx_buf_size)) {
492 		to_display_format(buffer_tx, tx_buf_size, buffer_print_tx);
493 		to_display_format(buffer_rx, tx_buf_size, buffer_print_rx);
494 		LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
495 		LOG_ERR("                           vs: %s", buffer_print_rx);
496 		zassert_false(1, "Buffer contents are different");
497 		return -1;
498 	}
499 
500 	const uint8_t all_zeroes_buf[BUF_SIZE] = {0};
501 
502 	if (memcmp(all_zeroes_buf, buffer_rx + tx_buf_size, BUF_SIZE - tx_buf_size)) {
503 		to_display_format(
504 			buffer_rx + tx_buf_size,  BUF_SIZE - tx_buf_size, buffer_print_tx);
505 
506 		to_display_format(
507 			all_zeroes_buf, BUF_SIZE - tx_buf_size, buffer_print_rx);
508 
509 		LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
510 		LOG_ERR("                           vs: %s", buffer_print_rx);
511 		zassert_false(1, "Buffer contents are different");
512 		return -1;
513 	}
514 
515 	LOG_INF("Passed");
516 
517 	return 0;
518 }
519 
520 #if (CONFIG_SPI_ASYNC)
521 static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER(async_sig);
522 static struct k_poll_event async_evt =
523 	K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
524 				 K_POLL_MODE_NOTIFY_ONLY,
525 				 &async_sig);
526 static K_SEM_DEFINE(caller, 0, 1);
527 K_THREAD_STACK_DEFINE(spi_async_stack, STACK_SIZE);
528 static int result = 1;
529 
spi_async_call_cb(void * p1,void * p2,void * p3)530 static void spi_async_call_cb(void *p1,
531 			      void *p2,
532 			      void *p3)
533 {
534 	ARG_UNUSED(p1);
535 	ARG_UNUSED(p2);
536 	ARG_UNUSED(p3);
537 
538 	struct k_poll_event *evt = p1;
539 	struct k_sem *caller_sem = p2;
540 	int ret;
541 
542 	LOG_DBG("Polling...");
543 
544 	while (1) {
545 		ret = k_poll(evt, 1, K_MSEC(2000));
546 		zassert_false(ret, "one or more events are not ready");
547 
548 		result = evt->signal->result;
549 		k_sem_give(caller_sem);
550 
551 		/* Reinitializing for next call */
552 		evt->signal->signaled = 0U;
553 		evt->state = K_POLL_STATE_NOT_READY;
554 	}
555 }
556 
spi_async_call(struct spi_dt_spec * spec)557 static int spi_async_call(struct spi_dt_spec *spec)
558 {
559 	const struct spi_buf tx_bufs[] = {
560 		{
561 			.buf = buffer_tx,
562 			.len = BUF_SIZE,
563 		},
564 		{
565 			.buf = buffer2_tx,
566 			.len = BUF2_SIZE,
567 		},
568 	};
569 	const struct spi_buf rx_bufs[] = {
570 		{
571 			.buf = buffer_rx,
572 			.len = BUF_SIZE,
573 		},
574 		{
575 			.buf = buffer2_rx,
576 			.len = BUF2_SIZE,
577 		},
578 	};
579 	const struct spi_buf_set tx = {
580 		.buffers = tx_bufs,
581 		.count = ARRAY_SIZE(tx_bufs)
582 	};
583 	const struct spi_buf_set rx = {
584 		.buffers = rx_bufs,
585 		.count = ARRAY_SIZE(rx_bufs)
586 	};
587 	int ret;
588 
589 	LOG_INF("Start async call");
590 	memset(buffer_rx, 0, sizeof(buffer_rx));
591 	memset(buffer2_rx, 0, sizeof(buffer2_rx));
592 
593 	ret = spi_transceive_signal(spec->bus, &spec->config, &tx, &rx, &async_sig);
594 	if (ret == -ENOTSUP) {
595 		LOG_DBG("Not supported");
596 		return 0;
597 	}
598 
599 	if (ret) {
600 		LOG_ERR("Code %d", ret);
601 		zassert_false(ret, "SPI transceive failed");
602 		return -1;
603 	}
604 
605 	k_sem_take(&caller, K_FOREVER);
606 
607 	if (result) {
608 		LOG_ERR("Call code %d", ret);
609 		zassert_false(result, "SPI transceive failed");
610 		return -1;
611 	}
612 
613 	if (memcmp(buffer_tx, buffer_rx, BUF_SIZE)) {
614 		to_display_format(buffer_tx, BUF_SIZE, buffer_print_tx);
615 		to_display_format(buffer_rx, BUF_SIZE, buffer_print_rx);
616 		LOG_ERR("Buffer contents are different: %s", buffer_print_tx);
617 		LOG_ERR("                           vs: %s", buffer_print_rx);
618 		zassert_false(1, "Buffer contents are different");
619 		return -1;
620 	}
621 
622 	if (memcmp(buffer2_tx, buffer2_rx, BUF2_SIZE)) {
623 		to_display_format(buffer2_tx, BUF2_SIZE, buffer_print_tx2);
624 		to_display_format(buffer2_rx, BUF2_SIZE, buffer_print_rx2);
625 		LOG_ERR("Buffer 2 contents are different: %s", buffer_print_tx2);
626 		LOG_ERR("                             vs: %s", buffer_print_rx2);
627 		zassert_false(1, "Buffer 2 contents are different");
628 		return -1;
629 	}
630 
631 	LOG_INF("Passed");
632 
633 	return 0;
634 }
635 #endif
636 
spi_resource_lock_test(struct spi_dt_spec * lock_spec,struct spi_dt_spec * try_spec)637 static int spi_resource_lock_test(struct spi_dt_spec *lock_spec,
638 				  struct spi_dt_spec *try_spec)
639 {
640 	lock_spec->config.operation |= SPI_LOCK_ON;
641 
642 	if (spi_complete_loop(lock_spec)) {
643 		return -1;
644 	}
645 
646 	if (spi_release_dt(lock_spec)) {
647 		LOG_ERR("Deadlock now?");
648 		zassert_false(1, "SPI release failed");
649 		return -1;
650 	}
651 
652 	if (spi_complete_loop(try_spec)) {
653 		return -1;
654 	}
655 
656 	return 0;
657 }
658 
ZTEST(spi_loopback,test_spi_loopback)659 ZTEST(spi_loopback, test_spi_loopback)
660 {
661 #if (CONFIG_SPI_ASYNC)
662 	struct k_thread async_thread;
663 	k_tid_t async_thread_id;
664 #endif
665 
666 	LOG_INF("SPI test on buffers TX/RX %p/%p" FRAME_SIZE_STR DMA_ENABLED_STR,
667 			buffer_tx,
668 			buffer_rx);
669 
670 #if (CONFIG_SPI_ASYNC)
671 	async_thread_id = k_thread_create(&async_thread,
672 					  spi_async_stack, STACK_SIZE,
673 					  spi_async_call_cb,
674 					  &async_evt, &caller, NULL,
675 					  K_PRIO_COOP(7), 0, K_NO_WAIT);
676 #endif
677 	zassert_true(spi_is_ready_dt(&spi_slow), "Slow spi lookback device is not ready");
678 
679 	LOG_INF("SPI test slow config");
680 
681 	if (spi_complete_multiple(&spi_slow) ||
682 	    spi_complete_loop(&spi_slow) ||
683 	    spi_null_tx_buf(&spi_slow) ||
684 	    spi_rx_half_start(&spi_slow) ||
685 	    spi_rx_half_end(&spi_slow) ||
686 	    spi_rx_every_4(&spi_slow) ||
687 	    spi_rx_bigger_than_tx(&spi_slow)
688 #if (CONFIG_SPI_ASYNC)
689 	    || spi_async_call(&spi_slow)
690 #endif
691 	    ) {
692 		goto end;
693 	}
694 
695 	zassert_true(spi_is_ready_dt(&spi_fast), "Fast spi lookback device is not ready");
696 
697 	LOG_INF("SPI test fast config");
698 
699 	if (spi_complete_multiple(&spi_fast) ||
700 	    spi_complete_loop(&spi_fast) ||
701 	    spi_null_tx_buf(&spi_fast) ||
702 	    spi_rx_half_start(&spi_fast) ||
703 	    spi_rx_half_end(&spi_fast) ||
704 	    spi_rx_every_4(&spi_fast) ||
705 	    spi_rx_bigger_than_tx(&spi_fast)
706 #if (CONFIG_SPI_ASYNC)
707 	    || spi_async_call(&spi_fast)
708 #endif
709 	    ) {
710 		goto end;
711 	}
712 
713 	if (spi_resource_lock_test(&spi_slow, &spi_fast)) {
714 		goto end;
715 	}
716 
717 	LOG_INF("All tx/rx passed");
718 end:
719 #if (CONFIG_SPI_ASYNC)
720 	k_thread_abort(async_thread_id);
721 #else
722 	;
723 #endif
724 }
725 
spi_loopback_setup(void)726 static void *spi_loopback_setup(void)
727 {
728 	memset(buffer_tx, 0, sizeof(buffer_tx));
729 	memcpy(buffer_tx, tx_data, sizeof(tx_data));
730 	memset(buffer2_tx, 0, sizeof(buffer2_tx));
731 	memcpy(buffer2_tx, tx2_data, sizeof(tx2_data));
732 	return NULL;
733 }
734 
735 ZTEST_SUITE(spi_loopback, NULL, spi_loopback_setup, NULL, NULL, NULL);
736