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 	defined(CONFIG_FLASH_RENESAS_RA_QSPI) || defined(CONFIG_FLASH_RENESAS_RZ_QSPI_XSPI) ||     \
42 	defined(CONFIG_FLASH_RENESAS_RZ_QSPI_SPIBSC)
43 #define SPI_FLASH_MULTI_SECTOR_TEST
44 #endif
45 
46 #if DT_HAS_COMPAT_STATUS_OKAY(jedec_spi_nor)
47 #define SPI_FLASH_COMPAT jedec_spi_nor
48 #elif DT_HAS_COMPAT_STATUS_OKAY(jedec_mspi_nor)
49 #define SPI_FLASH_COMPAT jedec_mspi_nor
50 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_qspi_nor)
51 #define SPI_FLASH_COMPAT st_stm32_qspi_nor
52 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_ospi_nor)
53 #define SPI_FLASH_COMPAT st_stm32_ospi_nor
54 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_xspi_nor)
55 #define SPI_FLASH_COMPAT st_stm32_xspi_nor
56 #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_qspi_nor)
57 #define SPI_FLASH_COMPAT nordic_qspi_nor
58 #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_ospi_b_nor)
59 #define SPI_FLASH_COMPAT renesas_ra_ospi_b_nor
60 #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_qspi_nor)
61 #define SPI_FLASH_COMPAT renesas_ra_qspi_nor
62 #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rz_qspi_xspi)
63 #define SPI_FLASH_COMPAT renesas_rz_qspi_xspi
64 #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rz_qspi_spibsc)
65 #define SPI_FLASH_COMPAT renesas_rz_qspi_spibsc
66 #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_xspi_nor)
67 #define SPI_FLASH_COMPAT nxp_xspi_nor
68 #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_imx_flexspi_nor)
69 #define SPI_FLASH_COMPAT nxp_imx_flexspi_nor
70 #else
71 #define SPI_FLASH_COMPAT invalid
72 #endif
73 
74 #if defined(CONFIG_FLASH_RENESAS_RA_OSPI_B)
75 const uint8_t erased[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
76 #else
77 const uint8_t erased[] = { 0xff, 0xff, 0xff, 0xff };
78 #endif
79 
single_sector_test(const struct device * flash_dev)80 void single_sector_test(const struct device *flash_dev)
81 {
82 #if defined(CONFIG_FLASH_RENESAS_RA_OSPI_B)
83 	const uint8_t expected[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
84 #else
85 	const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 };
86 #endif
87 	const size_t len = sizeof(expected);
88 	uint8_t buf[sizeof(expected)];
89 	int rc;
90 
91 	printf("\nPerform test on single sector");
92 	/* Write protection needs to be disabled before each write or
93 	 * erase, since the flash component turns on write protection
94 	 * automatically after completion of write and erase
95 	 * operations.
96 	 */
97 	printf("\nTest 1: Flash erase\n");
98 
99 	/* Full flash erase if SPI_FLASH_TEST_REGION_OFFSET = 0 and
100 	 * SPI_FLASH_SECTOR_SIZE = flash size
101 	 */
102 	rc = flash_erase(flash_dev, SPI_FLASH_TEST_REGION_OFFSET,
103 			 SPI_FLASH_SECTOR_SIZE);
104 	if (rc != 0) {
105 		printf("Flash erase failed! %d\n", rc);
106 	} else {
107 		/* Check erased pattern */
108 		memset(buf, 0, len);
109 		rc = flash_read(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, buf, len);
110 		if (rc != 0) {
111 			printf("Flash read failed! %d\n", rc);
112 			return;
113 		}
114 		if (memcmp(erased, buf, len) != 0) {
115 			printf("Flash erase failed at offset 0x%x got 0x%x\n",
116 				SPI_FLASH_TEST_REGION_OFFSET, *(uint32_t *)buf);
117 			return;
118 		}
119 		printf("Flash erase succeeded!\n");
120 	}
121 	printf("\nTest 2: Flash write\n");
122 
123 	printf("Attempting to write %zu bytes\n", len);
124 	rc = flash_write(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, expected, len);
125 	if (rc != 0) {
126 		printf("Flash write failed! %d\n", rc);
127 		return;
128 	}
129 
130 	memset(buf, 0, len);
131 	rc = flash_read(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, buf, len);
132 	if (rc != 0) {
133 		printf("Flash read failed! %d\n", rc);
134 		return;
135 	}
136 
137 	if (memcmp(expected, buf, len) == 0) {
138 		printf("Data read matches data written. Good!!\n");
139 	} else {
140 		const uint8_t *wp = expected;
141 		const uint8_t *rp = buf;
142 		const uint8_t *rpe = rp + len;
143 
144 		printf("Data read does not match data written!!\n");
145 		while (rp < rpe) {
146 			printf("%08x wrote %02x read %02x %s\n",
147 			       (uint32_t)(SPI_FLASH_TEST_REGION_OFFSET + (rp - buf)),
148 			       *wp, *rp, (*rp == *wp) ? "match" : "MISMATCH");
149 			++rp;
150 			++wp;
151 		}
152 	}
153 }
154 
155 #if defined SPI_FLASH_MULTI_SECTOR_TEST
multi_sector_test(const struct device * flash_dev)156 void multi_sector_test(const struct device *flash_dev)
157 {
158 #if defined(CONFIG_FLASH_RENESAS_RA_OSPI_B)
159 	const uint8_t expected[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
160 #else
161 	const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 };
162 #endif
163 	const size_t len = sizeof(expected);
164 	uint8_t buf[sizeof(expected)];
165 	int rc;
166 
167 	printf("\nPerform test on multiple consecutive sectors");
168 
169 	/* Write protection needs to be disabled before each write or
170 	 * erase, since the flash component turns on write protection
171 	 * automatically after completion of write and erase
172 	 * operations.
173 	 */
174 	printf("\nTest 1: Flash erase\n");
175 
176 	/* Full flash erase if SPI_FLASH_TEST_REGION_OFFSET = 0 and
177 	 * SPI_FLASH_SECTOR_SIZE = flash size
178 	 * Erase 2 sectors for check for erase of consequtive sectors
179 	 */
180 	rc = flash_erase(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, SPI_FLASH_SECTOR_SIZE * 2);
181 	if (rc != 0) {
182 		printf("Flash erase failed! %d\n", rc);
183 	} else {
184 		/* Read the content and check for erased */
185 		memset(buf, 0, len);
186 		size_t offs = SPI_FLASH_TEST_REGION_OFFSET;
187 
188 		while (offs < SPI_FLASH_TEST_REGION_OFFSET + 2 * SPI_FLASH_SECTOR_SIZE) {
189 			rc = flash_read(flash_dev, offs, buf, len);
190 			if (rc != 0) {
191 				printf("Flash read failed! %d\n", rc);
192 				return;
193 			}
194 			if (memcmp(erased, buf, len) != 0) {
195 				printf("Flash erase failed at offset 0x%x got 0x%x\n",
196 				offs, *(uint32_t *)buf);
197 				return;
198 			}
199 			offs += SPI_FLASH_SECTOR_SIZE;
200 		}
201 		printf("Flash erase succeeded!\n");
202 	}
203 
204 	printf("\nTest 2: Flash write\n");
205 
206 	size_t offs = SPI_FLASH_TEST_REGION_OFFSET;
207 
208 	while (offs < SPI_FLASH_TEST_REGION_OFFSET + 2 * SPI_FLASH_SECTOR_SIZE) {
209 		printf("Attempting to write %zu bytes at offset 0x%x\n", len, offs);
210 		rc = flash_write(flash_dev, offs, expected, len);
211 		if (rc != 0) {
212 			printf("Flash write failed! %d\n", rc);
213 			return;
214 		}
215 
216 		memset(buf, 0, len);
217 		rc = flash_read(flash_dev, offs, buf, len);
218 		if (rc != 0) {
219 			printf("Flash read failed! %d\n", rc);
220 			return;
221 		}
222 
223 		if (memcmp(expected, buf, len) == 0) {
224 			printf("Data read matches data written. Good!!\n");
225 		} else {
226 			const uint8_t *wp = expected;
227 			const uint8_t *rp = buf;
228 			const uint8_t *rpe = rp + len;
229 
230 			printf("Data read does not match data written!!\n");
231 			while (rp < rpe) {
232 				printf("%08x wrote %02x read %02x %s\n",
233 					(uint32_t)(offs + (rp - buf)),
234 					*wp, *rp, (*rp == *wp) ? "match" : "MISMATCH");
235 				++rp;
236 				++wp;
237 			}
238 		}
239 		offs += SPI_FLASH_SECTOR_SIZE;
240 	}
241 }
242 #endif
243 
main(void)244 int main(void)
245 {
246 	const struct device *flash_dev = DEVICE_DT_GET_ONE(SPI_FLASH_COMPAT);
247 
248 	if (!device_is_ready(flash_dev)) {
249 		printk("%s: device not ready.\n", flash_dev->name);
250 		return 0;
251 	}
252 
253 	printf("\n%s SPI flash testing\n", flash_dev->name);
254 	printf("==========================\n");
255 
256 	single_sector_test(flash_dev);
257 #if defined SPI_FLASH_MULTI_SECTOR_TEST
258 	multi_sector_test(flash_dev);
259 #endif
260 	return 0;
261 }
262