1 /*
2  * Copyright (c) 2024 Ambiq Micro Inc. <www.ambiq.com>
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include <zephyr/device.h>
7 #include <zephyr/drivers/mspi.h>
8 #include <zephyr/drivers/mspi_emul.h>
9 #include <zephyr/drivers/flash.h>
10 #include <zephyr/ztest.h>
11 
12 #define MSPI_BUS_NODE                 DT_ALIAS(mspi0)
13 
14 #define MSPI_FLASH_TEST_REGION_OFFSET 0x0
15 
16 #define MSPI_FLASH_SECTOR_SIZE        4096
17 
18 #define MSPI_FLASH_TEST_SIZE          3000
19 
20 static const struct device *mspi_devices[] = {
21 	DT_FOREACH_CHILD_STATUS_OKAY_SEP(MSPI_BUS_NODE, DEVICE_DT_GET, (,))
22 };
23 
24 static uint8_t expected[MSPI_FLASH_TEST_SIZE];
25 static uint8_t actual[MSPI_FLASH_TEST_SIZE];
26 
prepare_test_pattern(uint32_t pattern_index,uint8_t * actualf,uint32_t len)27 static void prepare_test_pattern(uint32_t pattern_index, uint8_t *actualf, uint32_t len)
28 {
29 	uint32_t *pui32TxPtr = (uint32_t *)actualf;
30 	uint8_t *pui8TxPtr = (uint8_t *)actualf;
31 
32 	switch (pattern_index) {
33 	case 0:
34 		/* 0x5555AAAA */
35 		for (uint32_t i = 0; i < len / 4; i++) {
36 			pui32TxPtr[i] = (0x5555AAAA);
37 		}
38 		break;
39 	case 1:
40 		/*  0xFFFF0000 */
41 		for (uint32_t i = 0; i < len / 4; i++) {
42 			pui32TxPtr[i] = (0xFFFF0000);
43 		}
44 		break;
45 	case 2:
46 		/* walking */
47 		for (uint32_t i = 0; i < len; i++) {
48 			pui8TxPtr[i] = 0x01 << (i % 8);
49 		}
50 		break;
51 	case 3:
52 		/* incremental from 1 */
53 		for (uint32_t i = 0; i < len; i++) {
54 			pui8TxPtr[i] = ((i + 1) & 0xFF);
55 		}
56 		break;
57 	case 4:
58 		/* decremental from 0xff */
59 		for (uint32_t i = 0; i < len; i++) {
60 			/* decrement starting from 0xff */
61 			pui8TxPtr[i] = (0xff - i) & 0xFF;
62 		}
63 		break;
64 	default:
65 		/* incremental from 1 */
66 		for (uint32_t i = 0; i < len; i++) {
67 			pui8TxPtr[i] = ((i + 1) & 0xFF);
68 		}
69 		break;
70 	}
71 }
72 
test_multi_sector_rw(const struct device * flash_dev)73 static int test_multi_sector_rw(const struct device *flash_dev)
74 {
75 	int rc = 0;
76 	const struct flash_pages_layout *layout = NULL;
77 	size_t layout_size = 0;
78 	size_t min_page_size = -1;
79 	size_t offs;
80 
81 	TC_PRINT("\n===================================================================\n");
82 	TC_PRINT("Perform test on multiple consequtive sectors on %s\n", flash_dev->name);
83 
84 	TC_PRINT("\nTest 0: Get Flash page layout\n");
85 
86 	const struct flash_driver_api *api = flash_dev->api;
87 
88 	api->page_layout(flash_dev, &layout, &layout_size);
89 
90 	if (layout && layout_size) {
91 		TC_PRINT("----pages-------size----\n");
92 		for (int i = 0; i < layout_size; ++i) {
93 			TC_PRINT("%2d: 0x%-8X  0x%-8x\n", i, layout[i].pages_count,
94 				 layout[i].pages_size);
95 			min_page_size = MIN(min_page_size, layout[i].pages_size);
96 		}
97 	} else {
98 		TC_PRINT("Empty flash_pages_layout!\n");
99 		return TC_FAIL;
100 	}
101 
102 	TC_PRINT("\nPage size selected: %d\n", min_page_size);
103 
104 	for (int i = 0; i < MSPI_FLASH_TEST_SIZE; i += min_page_size) {
105 		prepare_test_pattern(i % 5, expected + i,
106 				     MIN(min_page_size, MSPI_FLASH_TEST_SIZE - i));
107 	}
108 
109 	TC_PRINT("\nTest 1: Flash erase\n");
110 
111 	/* Full flash erase if MSPI_FLASH_TEST_REGION_OFFSET = 0 and
112 	 * MSPI_FLASH_SECTOR_SIZE = flash size
113 	 * Erase 2 sectors for check for erase of consequtive sectors
114 	 */
115 	rc = flash_erase(flash_dev, MSPI_FLASH_TEST_REGION_OFFSET, MSPI_FLASH_SECTOR_SIZE * 2);
116 	if (rc != 0) {
117 		TC_PRINT("Flash erase failed! %d\n", rc);
118 		return TC_FAIL;
119 	}
120 	/* Read the content and check for erased */
121 	memset(actual, 0, MSPI_FLASH_TEST_SIZE);
122 
123 	offs = MSPI_FLASH_TEST_REGION_OFFSET;
124 	while (offs < MSPI_FLASH_TEST_REGION_OFFSET + 2 * MSPI_FLASH_SECTOR_SIZE) {
125 		rc = flash_read(flash_dev, offs, actual, MSPI_FLASH_TEST_SIZE);
126 		if (rc != 0) {
127 			TC_PRINT("Flash read failed! %d\n", rc);
128 			return TC_FAIL;
129 		}
130 		if (actual[0] != 0xff) {
131 			TC_PRINT("Flash erase failed at offset 0x%x got 0x%x\n", offs,
132 					actual[0]);
133 			return TC_FAIL;
134 		}
135 		offs += MSPI_FLASH_SECTOR_SIZE;
136 	}
137 	TC_PRINT("Flash erase succeeded!\n");
138 
139 	TC_PRINT("\nTest 2: Flash write\n");
140 
141 	offs = MSPI_FLASH_TEST_REGION_OFFSET;
142 	while (offs < MSPI_FLASH_TEST_REGION_OFFSET + 2 * MSPI_FLASH_SECTOR_SIZE) {
143 		TC_PRINT("\nAttempting to write %zu bytes at offset 0x%x\n", MSPI_FLASH_TEST_SIZE,
144 			 offs);
145 		rc = flash_write(flash_dev, offs, expected, MSPI_FLASH_TEST_SIZE);
146 		if (rc != 0) {
147 			TC_PRINT("Flash write failed! %d\n", rc);
148 			return TC_FAIL;
149 		}
150 
151 		memset(actual, 0, MSPI_FLASH_TEST_SIZE);
152 		rc = flash_read(flash_dev, offs, actual, MSPI_FLASH_TEST_SIZE);
153 		if (rc != 0) {
154 			TC_PRINT("Flash read failed! %d\n", rc);
155 			return TC_FAIL;
156 		}
157 
158 		if (memcmp(expected, actual, MSPI_FLASH_TEST_SIZE) == 0) {
159 			TC_PRINT("Data read matches data written. Good!!\n");
160 		} else {
161 			const uint8_t *wp = expected;
162 			const uint8_t *rp = actual;
163 			const uint8_t *rpe = rp + MSPI_FLASH_TEST_SIZE;
164 			int count = 0;
165 
166 			TC_PRINT("Data read does not match data written!!\n");
167 			while (rp < rpe) {
168 				if (*rp != *wp) {
169 					TC_PRINT("%08x wrote %02x read %02x MISMATCH\n",
170 						 (uint32_t)(offs + (rp - actual)), *wp, *rp);
171 					count++;
172 				}
173 				if (count > 100) {
174 					TC_PRINT("Too many data mismatch!!\n");
175 					break;
176 				}
177 				++rp;
178 				++wp;
179 			}
180 			return TC_FAIL;
181 		}
182 		offs += MSPI_FLASH_SECTOR_SIZE;
183 	}
184 
185 	return TC_PASS;
186 }
187 
ZTEST(mspi_flash,test_multi_sector_rw)188 ZTEST(mspi_flash, test_multi_sector_rw)
189 {
190 
191 	for (int idx = 0; idx < ARRAY_SIZE(mspi_devices); ++idx) {
192 
193 		zassert_true(device_is_ready(mspi_devices[idx]),
194 					     "flash%d is not ready", idx);
195 		zassert_true(test_multi_sector_rw(mspi_devices[idx]) == TC_PASS);
196 
197 	}
198 
199 }
200 
201 ZTEST_SUITE(mspi_flash, NULL, NULL, NULL, NULL, NULL);
202