1 /*
2  * Copyright (c) 2023 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/dma.h>
11 #include "iut.h"
12 #if defined(CONFIG_CACHE_MANAGEMENT)
13 #include <zephyr/cache.h>
14 #else
15 #include "sedi_driver_core.h"
16 #endif
17 #include "sedi_driver_rtc.h"
18 
19 #define DT_DRV_COMPAT intel_sedi_dma
20 
21 __pinned_noinit static char __aligned(64) tx_data[4096];
22 __pinned_noinit static char __aligned(64) rx_data[4096];
23 static K_SEM_DEFINE(dma_sem, 0, 1);
24 static int dma_status;
25 
test_done(const struct device * dev,void * user_data,uint32_t channel,int status)26 static void test_done(const struct device *dev, void *user_data, uint32_t channel, int status)
27 {
28 	ARG_UNUSED(dev);
29 	ARG_UNUSED(user_data);
30 
31 	if (status != 0) {
32 		iut_case_print("DMA ch[%d] transfer error, status = %d\n", channel, status);
33 	}
34 	dma_status = status;
35 	k_sem_give(&dma_sem);
36 }
37 
test_dma_m2m(int argc,char ** argv)38 static int test_dma_m2m(int argc, char **argv)
39 {
40 	struct dma_config dma_cfg = {0};
41 	struct dma_block_config dma_block_cfg = {
42 		.block_size = sizeof(tx_data),
43 		.source_address = (uint32_t)&tx_data,
44 		.dest_address = (uint32_t)&rx_data,
45 	};
46 	uint32_t test_len;
47 	uint32_t blen = 8; /* burst length */
48 	const struct device *const dma = DEVICE_DT_GET(DT_DRV_INST(0));
49 	uint64_t us = sedi_rtc_get_us();
50 
51 	TEST_ASSERT_TRUE(dma != NULL);
52 
53 	if (argc) {
54 		blen = (uint32_t)strtoul(argv[0], NULL, 0);
55 	}
56 	iut_case_print("Run with blen=%u\n", blen);
57 
58 	for (uint32_t i = 0; i < sizeof(tx_data); i++) {
59 		tx_data[i] = (char)i;
60 	}
61 #if defined(CONFIG_CACHE_MANAGEMENT)
62 	sys_cache_data_flush_range(tx_data, sizeof(tx_data));
63 #else
64 	sedi_core_inv_clean_dcache_by_addr((uint32_t *)tx_data, sizeof(tx_data));
65 #endif
66 
67 	dma_cfg.channel_direction = MEMORY_TO_MEMORY;
68 	dma_cfg.source_data_size = 1;
69 	dma_cfg.dest_data_size = 1;
70 	dma_cfg.source_burst_length = blen;
71 	dma_cfg.dest_burst_length = blen;
72 	dma_cfg.dma_callback = test_done;
73 	dma_cfg.complete_callback_en = 1;
74 	dma_cfg.error_callback_dis = 1;
75 	dma_cfg.block_count = 1;
76 	dma_cfg.head_block = &dma_block_cfg;
77 
78 	for (test_len = 1; test_len <= sizeof(tx_data); test_len++) {
79 		dma_block_cfg.block_size = test_len;
80 
81 		for (uint32_t chan_id = 0; chan_id < DT_INST_PROP(0, dma_channels); chan_id++) {
82 			memset(rx_data, 0, sizeof(rx_data));
83 
84 #if defined(CONFIG_CACHE_MANAGEMENT)
85 			sys_cache_data_flush_range(rx_data, sizeof(rx_data));
86 #else
87 			sedi_core_inv_clean_dcache_by_addr((uint32_t *)rx_data, sizeof(rx_data));
88 #endif
89 
90 			TEST_ASSERT_TRUE(!dma_config(dma, chan_id, &dma_cfg));
91 			TEST_ASSERT_TRUE(!dma_start(dma, chan_id));
92 
93 			TEST_ASSERT_TRUE(!k_sem_take(&dma_sem, K_MSEC(1000)));
94 			TEST_ASSERT_TRUE(dma_status == 0);
95 			TEST_ASSERT_TRUE(!memcmp(tx_data, rx_data, test_len));
96 			TEST_ASSERT_TRUE(!dma_stop(dma, chan_id));
97 		}
98 	}
99 	us = sedi_rtc_get_us() - us;
100 	iut_case_print("Test Done after %u | %u us\n", (uint32_t)(us >> 32), (uint32_t)us);
101 
102 	return IUT_ERR_OK;
103 }
104 
105 DEFINE_IUT_CASE(dma_m2m, dma, IUT_ATTRI_NONE);
106