1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @brief File containing ztests for nrf70 buslib library
9  */
10 
11 #include <zephyr/shell/shell.h>
12 #include <zephyr/logging/log.h>
13 #include <zephyr/ztest.h>
14 #include <zephyr/drivers/wifi/nrf_wifi/bus/rpu_hw_if.h>
15 #include <zephyr/drivers/wifi/nrf_wifi/bus/qspi_if.h>
16 
17 LOG_MODULE_REGISTER(nrf70_bustest, CONFIG_WIFI_NRF70_BUSLIB_LOG_LEVEL);
18 
19 #define DATARAM_ADDR 0x0C0000
20 static struct qspi_dev *dev;
21 
wifi_on(void * state)22 static int wifi_on(void *state)
23 {
24 	int ret;
25 
26 	ARG_UNUSED(state);
27 
28 	dev = qspi_dev();
29 
30 	ret = rpu_init();
31 	if (ret) {
32 		LOG_ERR("%s: RPU init failed with error %d", __func__, ret);
33 		return -1;
34 	}
35 
36 	ret = dev->init(qspi_defconfig());
37 	if (ret) {
38 		LOG_ERR("%s: QSPI device init failed", __func__);
39 		return -1;
40 	}
41 
42 	ret = rpu_enable();
43 	if (ret) {
44 		LOG_ERR("%s: RPU enable failed with error %d", __func__, ret);
45 		return -1;
46 	}
47 	k_sleep(K_MSEC(10));
48 	LOG_INF("Wi-Fi ON done");
49 	return 0;
50 }
51 
wifi_off(void * state)52 static void wifi_off(void *state)
53 {
54 	ARG_UNUSED(state);
55 
56 	int ret;
57 
58 	ret = rpu_disable();
59 	if (ret) {
60 		LOG_ERR("%s: RPU disable failed with error %d", __func__, ret);
61 	}
62 
63 	ret = dev->deinit();
64 	if (ret) {
65 		LOG_ERR("%s: QSPI device de-init failed", __func__);
66 	}
67 	k_sleep(K_MSEC(10));
68 	LOG_INF("Wi-Fi OFF done");
69 }
70 
71 
memtest(uint32_t addr,char * memblock_name)72 static int memtest(uint32_t addr, char *memblock_name)
73 {
74 	const uint32_t pattern = 0x12345678;
75 	uint32_t offset = 1;
76 	uint32_t *buff, *rxbuff;
77 	int i;
78 
79 	int err_count;
80 	int32_t rem_words = CONFIG_NRF70BUS_MEMTEST_LENGTH;
81 	uint32_t test_chunk, chunk_no = 0;
82 	int ret = -1;
83 
84 	buff = k_malloc(CONFIG_NRF70BUS_MEMTEST_LENGTH * 4);
85 	if (buff == NULL) {
86 		LOG_ERR("Failed to allocate memory for buff");
87 		return -1;
88 	}
89 
90 	rxbuff = k_malloc(CONFIG_NRF70BUS_MEMTEST_LENGTH * 4);
91 	if (rxbuff == NULL) {
92 		LOG_ERR("Failed to allocate memory for rxbuff");
93 		k_free(buff);
94 		return -1;
95 	}
96 
97 	while (rem_words > 0) {
98 		test_chunk = (rem_words < CONFIG_NRF70BUS_MEMTEST_LENGTH) ?
99 					  rem_words : CONFIG_NRF70BUS_MEMTEST_LENGTH;
100 
101 		for (i = 0; i < test_chunk; i++) {
102 			buff[i] = pattern +
103 					  (i + chunk_no * CONFIG_NRF70BUS_MEMTEST_LENGTH) * offset;
104 		}
105 
106 		addr = addr + chunk_no * CONFIG_NRF70BUS_MEMTEST_LENGTH;
107 
108 		if (rpu_write(addr, buff, test_chunk * 4) ||
109 		    rpu_read(addr, rxbuff, test_chunk * 4)) {
110 			goto err;
111 		}
112 
113 		err_count = 0;
114 		for (i = 0; i < test_chunk; i++) {
115 			if (buff[i] != rxbuff[i]) {
116 				err_count++;
117 				LOG_ERR("%s: failed (%d), Expected 0x%x, Read 0x%x",
118 						__func__, i, buff[i], rxbuff[i]);
119 				if (err_count > 4)
120 					goto err;
121 			}
122 		}
123 		if (err_count) {
124 			goto err;
125 		}
126 		rem_words -= CONFIG_NRF70BUS_MEMTEST_LENGTH;
127 		chunk_no++;
128 	}
129 	ret = 0;
130 err:
131 	k_free(rxbuff);
132 	k_free(buff);
133 	return ret;
134 }
135 
test_sysbus(void)136 static int test_sysbus(void)
137 {
138 	int val, i;
139 	/* List of some SYS bus addresses and default values to test bus read
140 	 *  integrity
141 	 */
142 	const uint32_t addr[] = {0x714, 0x71c, 0x720,
143 							0x728, 0x734, 0x738};
144 	const uint32_t val_arr[] = {
145 		0x000003f3, 0x0110f13f, 0x000003f3,
146 		0x0003073f, 0x0003073f, 0x03013f8f};
147 
148 	for (i = 0; i < ARRAY_SIZE(addr); i++) {
149 		rpu_read(addr[i], &val, 4);
150 		if (val != val_arr[i]) {
151 			LOG_ERR("%s: SYSBUS R/W failed (%d) : read = 0x%x, expected = 0x%x",
152 						 __func__, i, val, val_arr[i]);
153 			return -1;
154 		}
155 	}
156 	return 0;
157 }
158 
test_peripbus(void)159 static int test_peripbus(void)
160 {
161 	uint32_t val;
162 	int i;
163 	/* Some Perip bus addresses that we can write/read to validate bus access*/
164 	const uint32_t addr[] = {0x62820, 0x62830, 0x62840, 0x62850, 0x62860, 0x62870};
165 
166 	for (i = 0; i < ARRAY_SIZE(addr); i++) {
167 		val = 0xA5A5A5A5; /* Test pattern */
168 		rpu_write(addr[i], &val, 4);
169 		val = 0;
170 		rpu_read(addr[i], &val, 4);
171 		/* Perip bus is 24-bit and hence LS 8 bits read are invalid, so discard them
172 		 * in the check
173 		 */
174 		if (val >> 8 != 0xA5A5A5) {
175 			LOG_ERR("%s: PERIP BUS R/W failed (%d): read = 0x%x",
176 						__func__, i, val >> 8);
177 			return -1;
178 		}
179 	}
180 	return 0;
181 }
182 
183 ZTEST_SUITE(bustest_suite, NULL, (void *)wifi_on, NULL, NULL, wifi_off);
184 
ZTEST(bustest_suite,test_sysbus)185 ZTEST(bustest_suite, test_sysbus)
186 {
187 	zassert_equal(0, test_sysbus(), "SYSBUS read validation failed!!!");
188 }
189 
ZTEST(bustest_suite,test_peripbus)190 ZTEST(bustest_suite, test_peripbus)
191 {
192 	zassert_equal(0, test_peripbus(), "PERIP BUS read/write validation failed!!!");
193 }
194 
ZTEST(bustest_suite,test_dataram)195 ZTEST(bustest_suite, test_dataram)
196 {
197 	zassert_equal(0, memtest(DATARAM_ADDR, "DATA RAM"), "DATA RAM memtest failed!!!");
198 }
199