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