1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <string.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/spi.h>
11 #include <zephyr/linker/devicetree_regions.h>
12 #include <zephyr/ztest.h>
13 
14 #if CONFIG_TESTED_SPI_MODE == 0
15 #define SPI_MODE (SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_LSB)
16 #elif CONFIG_TESTED_SPI_MODE == 1
17 #define SPI_MODE (SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB | SPI_MODE_CPHA)
18 #elif CONFIG_TESTED_SPI_MODE == 2
19 #define SPI_MODE (SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_LSB | SPI_MODE_CPOL)
20 #elif CONFIG_TESTED_SPI_MODE == 3
21 #define SPI_MODE (SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB | SPI_MODE_CPHA \
22 				| SPI_MODE_CPOL)
23 #endif
24 
25 #define SPIM_OP	 (SPI_OP_MODE_MASTER | SPI_MODE)
26 #define SPIS_OP	 (SPI_OP_MODE_SLAVE | SPI_MODE)
27 
28 static struct spi_dt_spec spim = SPI_DT_SPEC_GET(DT_NODELABEL(dut_spi_dt), SPIM_OP, 0);
29 static const struct device *spis_dev = DEVICE_DT_GET(DT_NODELABEL(dut_spis));
30 static const struct spi_config spis_config = {
31 	.operation = SPIS_OP
32 };
33 
34 static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER(async_sig);
35 static struct k_poll_event async_evt =
36 	K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &async_sig);
37 
38 static struct k_poll_signal async_sig_spim = K_POLL_SIGNAL_INITIALIZER(async_sig_spim);
39 static struct k_poll_event async_evt_spim =
40 	K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &async_sig_spim);
41 
42 #define MEMORY_SECTION(node)                                                                       \
43 	COND_CODE_1(DT_NODE_HAS_PROP(node, memory_regions),                                        \
44 		    (__attribute__((__section__(                                                   \
45 			    LINKER_DT_NODE_REGION_NAME(DT_PHANDLE(node, memory_regions)))))),      \
46 		    ())
47 
48 static uint8_t spim_buffer[32] MEMORY_SECTION(DT_BUS(DT_NODELABEL(dut_spi_dt)));
49 static uint8_t spis_buffer[32] MEMORY_SECTION(DT_NODELABEL(dut_spis));
50 
51 struct test_data {
52 	struct k_work_delayable test_work;
53 	struct k_sem sem;
54 	int spim_alloc_idx;
55 	int spis_alloc_idx;
56 	struct spi_buf_set sets[4];
57 	struct spi_buf_set *mtx_set;
58 	struct spi_buf_set *mrx_set;
59 	struct spi_buf_set *stx_set;
60 	struct spi_buf_set *srx_set;
61 	struct spi_buf bufs[8];
62 	bool async;
63 };
64 
65 static struct test_data tdata;
66 
67 /* Allocate buffer from spim or spis space. */
buf_alloc(size_t len,bool spim)68 static uint8_t *buf_alloc(size_t len, bool spim)
69 {
70 	int *idx = spim ? &tdata.spim_alloc_idx : &tdata.spis_alloc_idx;
71 	uint8_t *buf = spim ? spim_buffer : spis_buffer;
72 	size_t total = spim ? sizeof(spim_buffer) : sizeof(spis_buffer);
73 	uint8_t *rv;
74 
75 	if (*idx + len > total) {
76 		zassert_false(true);
77 
78 		return NULL;
79 	}
80 
81 	rv = &buf[*idx];
82 	*idx += len;
83 
84 	return rv;
85 }
86 
work_handler(struct k_work * work)87 static void work_handler(struct k_work *work)
88 {
89 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
90 	struct test_data *td = CONTAINER_OF(dwork, struct test_data, test_work);
91 	int rv;
92 
93 	if (!td->async) {
94 		rv = spi_transceive_dt(&spim, td->mtx_set, td->mrx_set);
95 		if (rv == 0) {
96 			k_sem_give(&td->sem);
97 		}
98 	} else {
99 		rv = spi_transceive_signal(spim.bus, &spim.config, td->mtx_set, td->mrx_set,
100 				&async_sig_spim);
101 		zassert_equal(rv, 0);
102 
103 		rv = k_poll(&async_evt_spim, 1, K_MSEC(200));
104 		zassert_false(rv, "one or more events are not ready");
105 
106 		rv = async_evt_spim.signal->result;
107 		zassert_equal(rv, 0);
108 
109 		/* Reinitializing for next call */
110 		async_evt_spim.signal->signaled = 0U;
111 		async_evt_spim.state = K_POLL_STATE_NOT_READY;
112 
113 		k_sem_give(&td->sem);
114 	}
115 }
116 
117 /** Copies data from buffers in the set to a single buffer which makes it easier
118  * to compare transmitted and received data.
119  *
120  * @param buf Output buffer.
121  * @param len Buffer length.
122  * @param set Set of buffers.
123  *
124  * @return Number of bytes copied.
125  */
cpy_data(uint8_t * buf,size_t len,struct spi_buf_set * set)126 static int cpy_data(uint8_t *buf, size_t len, struct spi_buf_set *set)
127 {
128 	int idx = 0;
129 
130 	for (size_t i = 0; i < set->count; i++) {
131 		size_t l = set->buffers[i].len;
132 
133 		if (len - idx >= l) {
134 			memcpy(&buf[idx], set->buffers[i].buf, l);
135 			idx += l;
136 		} else {
137 			return -1;
138 		}
139 	}
140 
141 	return idx;
142 }
143 
144 /** Compare two sets.
145  *
146  * @param tx_set TX set.
147  * @param rx_set RX set.
148  * @param same_size True if it is expected to have the same amount of data in both sets.
149  *
150  * @return 0 if data is the same and other value indicate that check failed.
151  */
check_buffers(struct spi_buf_set * tx_set,struct spi_buf_set * rx_set,bool same_size)152 static int check_buffers(struct spi_buf_set *tx_set, struct spi_buf_set *rx_set, bool same_size)
153 {
154 	static uint8_t tx_data[256];
155 	static uint8_t rx_data[256];
156 	int rx_len;
157 	int tx_len;
158 
159 	if (!tx_set || !rx_set) {
160 		return 0;
161 	}
162 
163 	rx_len = cpy_data(rx_data, sizeof(rx_data), rx_set);
164 	tx_len = cpy_data(tx_data, sizeof(tx_data), tx_set);
165 	if (same_size && (rx_len != tx_len)) {
166 		return -1;
167 	}
168 
169 	return memcmp(tx_data, rx_data, rx_len);
170 }
171 
172 /** Calculate expected number of received bytes by the SPI peripheral.
173  *
174  * It is used to check if SPI API call for peripheral SPI device returns correct value.
175  * @param tx_set TX set.
176  * @param rx_set RX set.
177  *
178  * @return Expected amount of received bytes.
179  */
peripheral_rx_len(struct spi_buf_set * tx_set,struct spi_buf_set * rx_set)180 static int peripheral_rx_len(struct spi_buf_set *tx_set, struct spi_buf_set *rx_set)
181 {
182 	size_t tx_len = 0;
183 	size_t rx_len = 0;
184 
185 	if (!tx_set || !rx_set) {
186 		return 0;
187 	}
188 
189 	for (size_t i = 0; i < tx_set->count; i++) {
190 		tx_len += tx_set->buffers[i].len;
191 	}
192 
193 	for (size_t i = 0; i < rx_set->count; i++) {
194 		rx_len += rx_set->buffers[i].len;
195 	}
196 
197 	return MIN(rx_len, tx_len);
198 }
199 
200 /** Generic function which runs the test with sets prepared in the test data structure. */
run_test(bool m_same_size,bool s_same_size,bool async)201 static void run_test(bool m_same_size, bool s_same_size, bool async)
202 {
203 	int rv;
204 	int periph_rv;
205 	int srx_len;
206 
207 	tdata.async = async;
208 	rv = k_work_schedule(&tdata.test_work, K_MSEC(10));
209 	zassert_equal(rv, 1);
210 
211 	if (!async) {
212 		periph_rv = spi_transceive(spis_dev, &spis_config, tdata.stx_set, tdata.srx_set);
213 		if (periph_rv == -ENOTSUP) {
214 			ztest_test_skip();
215 		}
216 	} else {
217 		rv = spi_transceive_signal(spis_dev, &spis_config, tdata.stx_set, tdata.srx_set,
218 					   &async_sig);
219 		if (rv == -ENOTSUP) {
220 			ztest_test_skip();
221 		}
222 		zassert_equal(rv, 0);
223 
224 		/* Transfer not finished yet */
225 		rv = k_sem_take(&tdata.sem, K_NO_WAIT);
226 		zassert_equal(rv, -EBUSY);
227 
228 		rv = k_poll(&async_evt, 1, K_MSEC(200));
229 		zassert_false(rv, "one or more events are not ready");
230 
231 		periph_rv = async_evt.signal->result;
232 
233 		/* Reinitializing for next call */
234 		async_evt.signal->signaled = 0U;
235 		async_evt.state = K_POLL_STATE_NOT_READY;
236 	}
237 
238 	rv = k_sem_take(&tdata.sem, K_MSEC(100));
239 	zassert_equal(rv, 0);
240 
241 	srx_len = peripheral_rx_len(tdata.mtx_set, tdata.srx_set);
242 
243 	zassert_equal(periph_rv, srx_len, "Got: %d but expected:%d", periph_rv, srx_len);
244 
245 	rv = check_buffers(tdata.mtx_set, tdata.srx_set, m_same_size);
246 	zassert_equal(rv, 0);
247 
248 	rv = check_buffers(tdata.stx_set, tdata.mrx_set, s_same_size);
249 	zassert_equal(rv, 0);
250 }
251 
252 /** Basic test where SPI controller and SPI peripheral have RX and TX sets which contains only one
253  *  same size buffer.
254  */
test_basic(bool async)255 static void test_basic(bool async)
256 {
257 	size_t len = 16;
258 
259 	for (int i = 0; i < 4; i++) {
260 		tdata.bufs[i].buf = buf_alloc(len, i < 2);
261 		tdata.bufs[i].len = len;
262 		tdata.sets[i].buffers = &tdata.bufs[i];
263 		tdata.sets[i].count = 1;
264 	}
265 
266 	tdata.mtx_set = &tdata.sets[0];
267 	tdata.mrx_set = &tdata.sets[1];
268 	tdata.stx_set = &tdata.sets[2];
269 	tdata.srx_set = &tdata.sets[3];
270 
271 	run_test(true, true, async);
272 }
273 
ZTEST(spi_controller_peripheral,test_basic)274 ZTEST(spi_controller_peripheral, test_basic)
275 {
276 	test_basic(false);
277 }
278 
ZTEST(spi_controller_peripheral,test_basic_async)279 ZTEST(spi_controller_peripheral, test_basic_async)
280 {
281 	test_basic(true);
282 }
283 
284 /** Basic test with zero length buffers.
285  */
test_basic_zero_len(bool async)286 void test_basic_zero_len(bool async)
287 {
288 	size_t len = 8;
289 
290 	/* SPIM */
291 	tdata.bufs[0].buf = buf_alloc(len, true);
292 	tdata.bufs[0].len = len;
293 	tdata.bufs[1].buf = buf_alloc(len, true);
294 	/* Intentionally len was set to 0 - second buffer "is empty". */
295 	tdata.bufs[1].len = 0;
296 	tdata.sets[0].buffers = &tdata.bufs[0];
297 	tdata.sets[0].count = 2;
298 	tdata.mtx_set = &tdata.sets[0];
299 
300 	tdata.bufs[2].buf = buf_alloc(len, true);
301 	tdata.bufs[2].len = len;
302 	tdata.bufs[3].buf = buf_alloc(len, true);
303 	/* Intentionally len was set to 0 - second buffer "is empty". */
304 	tdata.bufs[3].len = 0;
305 	tdata.sets[1].buffers = &tdata.bufs[2];
306 	tdata.sets[1].count = 2;
307 	tdata.mrx_set = &tdata.sets[1];
308 
309 	/* SPIS */
310 	tdata.bufs[4].buf = buf_alloc(len, false);
311 	tdata.bufs[4].len = len;
312 	tdata.sets[2].buffers = &tdata.bufs[4];
313 	tdata.sets[2].count = 1;
314 	tdata.stx_set = &tdata.sets[2];
315 
316 	tdata.bufs[6].buf = buf_alloc(len, false);
317 	tdata.bufs[6].len = len;
318 	tdata.sets[3].buffers = &tdata.bufs[6];
319 	tdata.sets[3].count = 1;
320 	tdata.srx_set = &tdata.sets[3];
321 
322 	run_test(true, true, async);
323 }
324 
ZTEST(spi_controller_peripheral,test_basic_zero_len)325 ZTEST(spi_controller_peripheral, test_basic_zero_len)
326 {
327 	test_basic_zero_len(false);
328 }
329 
ZTEST(spi_controller_peripheral,test_basic_zero_len_async)330 ZTEST(spi_controller_peripheral, test_basic_zero_len_async)
331 {
332 	test_basic_zero_len(true);
333 }
334 
335 /** Setup a transfer where RX buffer on SPI controller and SPI peripheral are
336  *  shorter than TX buffers. RX buffers shall contain beginning of TX data
337  *  and last TX bytes that did not fit in the RX buffers shall be lost.
338  */
test_short_rx(bool async)339 static void test_short_rx(bool async)
340 {
341 	size_t len = 16;
342 
343 	tdata.bufs[0].buf = buf_alloc(len, true);
344 	tdata.bufs[0].len = len;
345 	tdata.bufs[1].buf = buf_alloc(len, true);
346 	tdata.bufs[1].len = len - 3; /* RX buffer */
347 	tdata.bufs[2].buf = buf_alloc(len, false);
348 	tdata.bufs[2].len = len;
349 	tdata.bufs[3].buf = buf_alloc(len, false);
350 	tdata.bufs[3].len = len - 4; /* RX buffer */
351 
352 	for (int i = 0; i < 4; i++) {
353 		tdata.sets[i].buffers = &tdata.bufs[i];
354 		tdata.sets[i].count = 1;
355 	}
356 
357 	tdata.mtx_set = &tdata.sets[0];
358 	tdata.mrx_set = &tdata.sets[1];
359 	tdata.stx_set = &tdata.sets[2];
360 	tdata.srx_set = &tdata.sets[3];
361 
362 	run_test(false, false, async);
363 }
364 
ZTEST(spi_controller_peripheral,test_short_rx)365 ZTEST(spi_controller_peripheral, test_short_rx)
366 {
367 	test_short_rx(false);
368 }
369 
ZTEST(spi_controller_peripheral,test_short_rx_async)370 ZTEST(spi_controller_peripheral, test_short_rx_async)
371 {
372 	test_short_rx(true);
373 }
374 
375 /** Test where only master transmits. */
test_only_tx(bool async)376 static void test_only_tx(bool async)
377 {
378 	size_t len = 16;
379 
380 	/* MTX buffer */
381 	tdata.bufs[0].buf = buf_alloc(len, true);
382 	tdata.bufs[0].len = len;
383 	tdata.sets[0].buffers = &tdata.bufs[0];
384 	tdata.sets[0].count = 1;
385 	tdata.mtx_set = &tdata.sets[0];
386 	tdata.mrx_set = NULL;
387 
388 	/* STX buffer */
389 	tdata.bufs[1].buf = buf_alloc(len, false);
390 	tdata.bufs[1].len = len;
391 	tdata.sets[1].buffers = &tdata.bufs[1];
392 	tdata.sets[1].count = 1;
393 	tdata.srx_set = &tdata.sets[1];
394 	tdata.stx_set = NULL;
395 
396 	run_test(true, true, async);
397 }
398 
ZTEST(spi_controller_peripheral,test_only_tx)399 ZTEST(spi_controller_peripheral, test_only_tx)
400 {
401 	test_only_tx(false);
402 }
403 
ZTEST(spi_controller_peripheral,test_only_tx_async)404 ZTEST(spi_controller_peripheral, test_only_tx_async)
405 {
406 	test_only_tx(true);
407 }
408 
409 /** Test where only SPI controller transmits and SPI peripheral receives in chunks. */
test_only_tx_in_chunks(bool async)410 static void test_only_tx_in_chunks(bool async)
411 {
412 	size_t len1 = 7;
413 	size_t len2 = 8;
414 
415 	/* MTX buffer */
416 	tdata.bufs[0].buf = buf_alloc(len1 + len2, true);
417 	tdata.bufs[0].len = len1 + len2;
418 	tdata.sets[0].buffers = &tdata.bufs[0];
419 	tdata.sets[0].count = 1;
420 	tdata.mtx_set = &tdata.sets[0];
421 	tdata.mrx_set = NULL;
422 
423 	/* STX buffer */
424 	tdata.bufs[1].buf = buf_alloc(len1, false);
425 	tdata.bufs[1].len = len1;
426 	tdata.bufs[2].buf = buf_alloc(len2, false);
427 	tdata.bufs[2].len = len2;
428 	tdata.sets[1].buffers = &tdata.bufs[1];
429 	tdata.sets[1].count = 2;
430 	tdata.srx_set = &tdata.sets[1];
431 	tdata.stx_set = NULL;
432 
433 	run_test(true, true, async);
434 }
435 
ZTEST(spi_controller_peripheral,test_only_tx_in_chunks)436 ZTEST(spi_controller_peripheral, test_only_tx_in_chunks)
437 {
438 	test_only_tx_in_chunks(false);
439 }
440 
ZTEST(spi_controller_peripheral,test_only_tx_in_chunks_async)441 ZTEST(spi_controller_peripheral, test_only_tx_in_chunks_async)
442 {
443 	test_only_tx_in_chunks(true);
444 }
445 
446 /** Test where only SPI peripheral transmits. */
test_only_rx(bool async)447 static void test_only_rx(bool async)
448 {
449 	size_t len = 16;
450 
451 	/* MTX buffer */
452 	tdata.bufs[0].buf = buf_alloc(len, true);
453 	tdata.bufs[0].len = len;
454 	tdata.sets[0].buffers = &tdata.bufs[0];
455 	tdata.sets[0].count = 1;
456 	tdata.mrx_set = &tdata.sets[0];
457 	tdata.mtx_set = NULL;
458 
459 	/* STX buffer */
460 	tdata.bufs[1].buf = buf_alloc(len, false);
461 	tdata.bufs[1].len = len;
462 	tdata.sets[1].buffers = &tdata.bufs[1];
463 	tdata.sets[1].count = 1;
464 	tdata.stx_set = &tdata.sets[1];
465 	tdata.srx_set = NULL;
466 
467 	run_test(true, true, async);
468 }
469 
ZTEST(spi_controller_peripheral,test_only_rx)470 ZTEST(spi_controller_peripheral, test_only_rx)
471 {
472 	test_only_rx(false);
473 }
474 
ZTEST(spi_controller_peripheral,test_only_rx_async)475 ZTEST(spi_controller_peripheral, test_only_rx_async)
476 {
477 	test_only_rx(true);
478 }
479 
480 /** Test where only SPI peripheral transmits in chunks. */
test_only_rx_in_chunks(bool async)481 static void test_only_rx_in_chunks(bool async)
482 {
483 	size_t len1 = 7;
484 	size_t len2 = 9;
485 
486 	/* MTX buffer */
487 	tdata.bufs[0].buf = buf_alloc(len1 + len2, true);
488 	tdata.bufs[0].len = len1 + len2;
489 	tdata.sets[0].buffers = &tdata.bufs[0];
490 	tdata.sets[0].count = 1;
491 	tdata.mrx_set = &tdata.sets[0];
492 	tdata.mtx_set = NULL;
493 
494 	/* STX buffer */
495 	tdata.bufs[1].buf = buf_alloc(len1, false);
496 	tdata.bufs[1].len = len1;
497 	tdata.bufs[2].buf = buf_alloc(len2, false);
498 	tdata.bufs[2].len = len2;
499 	tdata.sets[1].buffers = &tdata.bufs[1];
500 	tdata.sets[1].count = 2;
501 	tdata.stx_set = &tdata.sets[1];
502 	tdata.srx_set = NULL;
503 
504 	run_test(true, true, async);
505 }
506 
ZTEST(spi_controller_peripheral,test_only_rx_in_chunks)507 ZTEST(spi_controller_peripheral, test_only_rx_in_chunks)
508 {
509 	test_only_rx_in_chunks(false);
510 }
511 
ZTEST(spi_controller_peripheral,test_only_rx_in_chunks_async)512 ZTEST(spi_controller_peripheral, test_only_rx_in_chunks_async)
513 {
514 	test_only_rx_in_chunks(true);
515 }
516 
before(void * not_used)517 static void before(void *not_used)
518 {
519 	ARG_UNUSED(not_used);
520 
521 	memset(&tdata, 0, sizeof(tdata));
522 	for (size_t i = 0; i < sizeof(spim_buffer); i++) {
523 		spim_buffer[i] = (uint8_t)i;
524 	}
525 	for (size_t i = 0; i < sizeof(spis_buffer); i++) {
526 		spis_buffer[i] = (uint8_t)(i + 0x80);
527 	}
528 
529 	k_work_init_delayable(&tdata.test_work, work_handler);
530 	k_sem_init(&tdata.sem, 0, 1);
531 }
532 
suite_setup(void)533 static void *suite_setup(void)
534 {
535 	return NULL;
536 }
537 
538 ZTEST_SUITE(spi_controller_peripheral, NULL, suite_setup, before, NULL, NULL);
539