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