1 /*
2  * Copyright (c) 2016 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/flash.h>
9 #include <zephyr/device.h>
10 #include <zephyr/devicetree.h>
11 #include <stdio.h>
12 #include <string.h>
13 
14 #if defined(CONFIG_BOARD_ADAFRUIT_FEATHER_STM32F405)
15 #define SPI_FLASH_TEST_REGION_OFFSET 0xf000
16 #elif defined(CONFIG_BOARD_ARTY_A7_DESIGNSTART_FPGA_CORTEX_M1) || \
17 	defined(CONFIG_BOARD_ARTY_A7_DESIGNSTART_FPGA_CORTEX_M3)
18 /* The FPGA bitstream is stored in the lower 536 sectors of the flash. */
19 #define SPI_FLASH_TEST_REGION_OFFSET \
20 	DT_REG_SIZE(DT_NODE_BY_FIXED_PARTITION_LABEL(fpga_bitstream))
21 #elif defined(CONFIG_BOARD_NPCX9M6F_EVB) || \
22 	defined(CONFIG_BOARD_NPCX7M6FB_EVB)
23 #define SPI_FLASH_TEST_REGION_OFFSET 0x7F000
24 #elif defined(CONFIG_BOARD_EK_RA8M1) || defined(CONFIG_BOARD_EK_RA8D1)
25 #define SPI_FLASH_TEST_REGION_OFFSET 0x40000
26 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_qspi_nor) && DT_PROP(DT_NODELABEL(quadspi), dual_flash)
27 #define SPI_FLASH_TEST_REGION_OFFSET 0xfe000
28 #else
29 #define SPI_FLASH_TEST_REGION_OFFSET 0xff000
30 #endif
31 #if defined(CONFIG_BOARD_EK_RA8M1) || defined(CONFIG_BOARD_EK_RA8D1)
32 #define SPI_FLASH_SECTOR_SIZE 262144
33 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_qspi_nor) && DT_PROP(DT_NODELABEL(quadspi), dual_flash)
34 #define SPI_FLASH_SECTOR_SIZE 8192
35 #else
36 #define SPI_FLASH_SECTOR_SIZE        4096
37 #endif
38 
39 #if defined(CONFIG_FLASH_STM32_OSPI) || defined(CONFIG_FLASH_STM32_QSPI) ||                        \
40 	defined(CONFIG_FLASH_STM32_XSPI) || defined(CONFIG_FLASH_RENESAS_RA_OSPI_B)
41 
42 #define SPI_FLASH_MULTI_SECTOR_TEST
43 #endif
44 
45 #if DT_HAS_COMPAT_STATUS_OKAY(jedec_spi_nor)
46 #define SPI_FLASH_COMPAT jedec_spi_nor
47 #elif DT_HAS_COMPAT_STATUS_OKAY(jedec_mspi_nor)
48 #define SPI_FLASH_COMPAT jedec_mspi_nor
49 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_qspi_nor)
50 #define SPI_FLASH_COMPAT st_stm32_qspi_nor
51 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_ospi_nor)
52 #define SPI_FLASH_COMPAT st_stm32_ospi_nor
53 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_xspi_nor)
54 #define SPI_FLASH_COMPAT st_stm32_xspi_nor
55 #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_qspi_nor)
56 #define SPI_FLASH_COMPAT nordic_qspi_nor
57 #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_ospi_b_nor)
58 #define SPI_FLASH_COMPAT renesas_ra_ospi_b_nor
59 #else
60 #define SPI_FLASH_COMPAT invalid
61 #endif
62 
63 #if defined(CONFIG_FLASH_RENESAS_RA_OSPI_B)
64 const uint8_t erased[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
65 #else
66 const uint8_t erased[] = { 0xff, 0xff, 0xff, 0xff };
67 #endif
68 
single_sector_test(const struct device * flash_dev)69 void single_sector_test(const struct device *flash_dev)
70 {
71 #if defined(CONFIG_FLASH_RENESAS_RA_OSPI_B)
72 	const uint8_t expected[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
73 #else
74 	const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 };
75 #endif
76 	const size_t len = sizeof(expected);
77 	uint8_t buf[sizeof(expected)];
78 	int rc;
79 
80 	printf("\nPerform test on single sector");
81 	/* Write protection needs to be disabled before each write or
82 	 * erase, since the flash component turns on write protection
83 	 * automatically after completion of write and erase
84 	 * operations.
85 	 */
86 	printf("\nTest 1: Flash erase\n");
87 
88 	/* Full flash erase if SPI_FLASH_TEST_REGION_OFFSET = 0 and
89 	 * SPI_FLASH_SECTOR_SIZE = flash size
90 	 */
91 	rc = flash_erase(flash_dev, SPI_FLASH_TEST_REGION_OFFSET,
92 			 SPI_FLASH_SECTOR_SIZE);
93 	if (rc != 0) {
94 		printf("Flash erase failed! %d\n", rc);
95 	} else {
96 		/* Check erased pattern */
97 		memset(buf, 0, len);
98 		rc = flash_read(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, buf, len);
99 		if (rc != 0) {
100 			printf("Flash read failed! %d\n", rc);
101 			return;
102 		}
103 		if (memcmp(erased, buf, len) != 0) {
104 			printf("Flash erase failed at offset 0x%x got 0x%x\n",
105 				SPI_FLASH_TEST_REGION_OFFSET, *(uint32_t *)buf);
106 			return;
107 		}
108 		printf("Flash erase succeeded!\n");
109 	}
110 	printf("\nTest 2: Flash write\n");
111 
112 	printf("Attempting to write %zu bytes\n", len);
113 	rc = flash_write(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, expected, len);
114 	if (rc != 0) {
115 		printf("Flash write failed! %d\n", rc);
116 		return;
117 	}
118 
119 	memset(buf, 0, len);
120 	rc = flash_read(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, buf, len);
121 	if (rc != 0) {
122 		printf("Flash read failed! %d\n", rc);
123 		return;
124 	}
125 
126 	if (memcmp(expected, buf, len) == 0) {
127 		printf("Data read matches data written. Good!!\n");
128 	} else {
129 		const uint8_t *wp = expected;
130 		const uint8_t *rp = buf;
131 		const uint8_t *rpe = rp + len;
132 
133 		printf("Data read does not match data written!!\n");
134 		while (rp < rpe) {
135 			printf("%08x wrote %02x read %02x %s\n",
136 			       (uint32_t)(SPI_FLASH_TEST_REGION_OFFSET + (rp - buf)),
137 			       *wp, *rp, (*rp == *wp) ? "match" : "MISMATCH");
138 			++rp;
139 			++wp;
140 		}
141 	}
142 }
143 
144 #if defined SPI_FLASH_MULTI_SECTOR_TEST
multi_sector_test(const struct device * flash_dev)145 void multi_sector_test(const struct device *flash_dev)
146 {
147 #if defined(CONFIG_FLASH_RENESAS_RA_OSPI_B)
148 	const uint8_t expected[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
149 #else
150 	const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 };
151 #endif
152 	const size_t len = sizeof(expected);
153 	uint8_t buf[sizeof(expected)];
154 	int rc;
155 
156 	printf("\nPerform test on multiple consecutive sectors");
157 
158 	/* Write protection needs to be disabled before each write or
159 	 * erase, since the flash component turns on write protection
160 	 * automatically after completion of write and erase
161 	 * operations.
162 	 */
163 	printf("\nTest 1: Flash erase\n");
164 
165 	/* Full flash erase if SPI_FLASH_TEST_REGION_OFFSET = 0 and
166 	 * SPI_FLASH_SECTOR_SIZE = flash size
167 	 * Erase 2 sectors for check for erase of consequtive sectors
168 	 */
169 	rc = flash_erase(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, SPI_FLASH_SECTOR_SIZE * 2);
170 	if (rc != 0) {
171 		printf("Flash erase failed! %d\n", rc);
172 	} else {
173 		/* Read the content and check for erased */
174 		memset(buf, 0, len);
175 		size_t offs = SPI_FLASH_TEST_REGION_OFFSET;
176 
177 		while (offs < SPI_FLASH_TEST_REGION_OFFSET + 2 * SPI_FLASH_SECTOR_SIZE) {
178 			rc = flash_read(flash_dev, offs, buf, len);
179 			if (rc != 0) {
180 				printf("Flash read failed! %d\n", rc);
181 				return;
182 			}
183 			if (memcmp(erased, buf, len) != 0) {
184 				printf("Flash erase failed at offset 0x%x got 0x%x\n",
185 				offs, *(uint32_t *)buf);
186 				return;
187 			}
188 			offs += SPI_FLASH_SECTOR_SIZE;
189 		}
190 		printf("Flash erase succeeded!\n");
191 	}
192 
193 	printf("\nTest 2: Flash write\n");
194 
195 	size_t offs = SPI_FLASH_TEST_REGION_OFFSET;
196 
197 	while (offs < SPI_FLASH_TEST_REGION_OFFSET + 2 * SPI_FLASH_SECTOR_SIZE) {
198 		printf("Attempting to write %zu bytes at offset 0x%x\n", len, offs);
199 		rc = flash_write(flash_dev, offs, expected, len);
200 		if (rc != 0) {
201 			printf("Flash write failed! %d\n", rc);
202 			return;
203 		}
204 
205 		memset(buf, 0, len);
206 		rc = flash_read(flash_dev, offs, buf, len);
207 		if (rc != 0) {
208 			printf("Flash read failed! %d\n", rc);
209 			return;
210 		}
211 
212 		if (memcmp(expected, buf, len) == 0) {
213 			printf("Data read matches data written. Good!!\n");
214 		} else {
215 			const uint8_t *wp = expected;
216 			const uint8_t *rp = buf;
217 			const uint8_t *rpe = rp + len;
218 
219 			printf("Data read does not match data written!!\n");
220 			while (rp < rpe) {
221 				printf("%08x wrote %02x read %02x %s\n",
222 					(uint32_t)(offs + (rp - buf)),
223 					*wp, *rp, (*rp == *wp) ? "match" : "MISMATCH");
224 				++rp;
225 				++wp;
226 			}
227 		}
228 		offs += SPI_FLASH_SECTOR_SIZE;
229 	}
230 }
231 #endif
232 
main(void)233 int main(void)
234 {
235 	const struct device *flash_dev = DEVICE_DT_GET_ONE(SPI_FLASH_COMPAT);
236 
237 	if (!device_is_ready(flash_dev)) {
238 		printk("%s: device not ready.\n", flash_dev->name);
239 		return 0;
240 	}
241 
242 	printf("\n%s SPI flash testing\n", flash_dev->name);
243 	printf("==========================\n");
244 
245 	single_sector_test(flash_dev);
246 #if defined SPI_FLASH_MULTI_SECTOR_TEST
247 	multi_sector_test(flash_dev);
248 #endif
249 	return 0;
250 }
251