1 /*
2  * Copyright (c) 2021 Volvo Construction Equipment
3  * Copyright 2023 NXP
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT nxp_imx_flexspi_hyperflash
9 
10 #include <zephyr/kernel.h>
11 #include <errno.h>
12 #include <zephyr/drivers/flash.h>
13 
14 #include <zephyr/logging/log.h>
15 
16 /*
17  * NOTE: If CONFIG_FLASH_MCUX_FLEXSPI_XIP is selected, Any external functions
18  * called while interacting with the flexspi MUST be relocated to SRAM or ITCM
19  * at runtime, so that the chip does not access the flexspi to read program
20  * instructions while it is being written to
21  *
22  * Additionally, no data used by this driver should be stored in flash.
23  */
24 #if defined(CONFIG_FLASH_MCUX_FLEXSPI_XIP) && (CONFIG_FLASH_LOG_LEVEL > 0)
25 #warning "Enabling flash driver logging and XIP mode simultaneously can cause \
26 	read-while-write hazards. This configuration is not recommended."
27 #endif
28 
29 LOG_MODULE_REGISTER(flexspi_hyperflash, CONFIG_FLASH_LOG_LEVEL);
30 
31 #ifdef CONFIG_HAS_MCUX_CACHE
32 #include <fsl_cache.h>
33 #endif
34 
35 #include <zephyr/sys/util.h>
36 
37 #include "memc_mcux_flexspi.h"
38 
39 #define SPI_HYPERFLASH_SECTOR_SIZE              (0x40000U)
40 #define SPI_HYPERFLASH_PAGE_SIZE                (512U)
41 
42 #define HYPERFLASH_ERASE_VALUE                  (0xFF)
43 
44 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_HYPERFLASH_WRITE_BUFFER
45 static uint8_t hyperflash_write_buf[SPI_HYPERFLASH_PAGE_SIZE];
46 #endif
47 
48 enum {
49 	/* Instructions matching with XIP layout */
50 	READ_DATA = 0,
51 	WRITE_DATA = 1,
52 	READ_STATUS = 2,
53 	WRITE_ENABLE = 4,
54 	ERASE_SECTOR = 6,
55 	PAGE_PROGRAM = 10,
56 	ERASE_CHIP = 12,
57 };
58 
59 #define CUSTOM_LUT_LENGTH                      64
60 
61 static const uint32_t flash_flexspi_hyperflash_lut[CUSTOM_LUT_LENGTH] = {
62 	/* Read Data */
63 	[4 * READ_DATA] =
64 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0xA0,
65 				kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
66 	[4 * READ_DATA + 1] =
67 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10,
68 				kFLEXSPI_Command_READ_DDR,  kFLEXSPI_8PAD, 0x04),
69 	/* Write Data */
70 	[4 * WRITE_DATA] =
71 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0x20,
72 				kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
73 	[4 * WRITE_DATA + 1] =
74 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10,
75 				kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x02),
76 	/* Read Status */
77 	[4 * READ_STATUS] =
78 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
79 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
80 	[4 * READ_STATUS + 1] =
81 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
82 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
83 	[4 * READ_STATUS + 2] =
84 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
85 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
86 	[4 * READ_STATUS + 3] =
87 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
88 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x70),
89 	[4 * READ_STATUS + 4] =
90 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0xA0,
91 				kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
92 	[4 * READ_STATUS + 5] =
93 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR,      kFLEXSPI_8PAD, 0x10,
94 				kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, 0x0B),
95 	[4 * READ_STATUS + 6] =
96 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04,
97 				kFLEXSPI_Command_STOP,     kFLEXSPI_1PAD, 0x0),
98 	/* Write Enable */
99 	[4 * WRITE_ENABLE] =
100 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20,
101 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
102 	[4 * WRITE_ENABLE + 1] =
103 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
104 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
105 	[4 * WRITE_ENABLE + 2] =
106 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
107 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
108 	[4 * WRITE_ENABLE + 3] =
109 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
110 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
111 	[4 * WRITE_ENABLE + 4] =
112 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20,
113 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
114 	[4 * WRITE_ENABLE + 5] =
115 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
116 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
117 	[4 * WRITE_ENABLE + 6] =
118 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
119 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x02),
120 	[4 * WRITE_ENABLE + 7] =
121 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
122 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
123 
124 	/* Erase Sector  */
125 	[4 * ERASE_SECTOR] =
126 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
127 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
128 	[4 * ERASE_SECTOR + 1] =
129 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
130 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
131 	[4 * ERASE_SECTOR + 2] =
132 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
133 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
134 	[4 * ERASE_SECTOR + 3] =
135 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
136 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x80),
137 	[4 * ERASE_SECTOR + 4] =
138 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
139 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
140 	[4 * ERASE_SECTOR + 5] =
141 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
142 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
143 	[4 * ERASE_SECTOR + 6] =
144 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
145 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
146 	[4 * ERASE_SECTOR + 7] =
147 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
148 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
149 	[4 * ERASE_SECTOR + 8] =
150 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
151 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
152 	[4 * ERASE_SECTOR + 9] =
153 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
154 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
155 	[4 * ERASE_SECTOR + 10] =
156 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
157 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x02),
158 	[4 * ERASE_SECTOR + 11] =
159 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
160 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
161 	[4 * ERASE_SECTOR + 12] =
162 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0x00,
163 				kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
164 	[4 * ERASE_SECTOR + 13] =
165 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10,
166 				kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0x00),
167 	[4 * ERASE_SECTOR + 14] =
168 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,  kFLEXSPI_8PAD, 0x30,
169 				kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00),
170 
171 	/* program page with word program command sequence */
172 	[4 * PAGE_PROGRAM] =
173 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20,
174 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
175 	[4 * PAGE_PROGRAM + 1] =
176 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
177 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
178 	[4 * PAGE_PROGRAM + 2] =
179 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
180 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
181 	[4 * PAGE_PROGRAM + 3] =
182 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
183 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xA0),
184 	[4 * PAGE_PROGRAM + 4] =
185 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR,       kFLEXSPI_8PAD, 0x20,
186 				kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18),
187 	[4 * PAGE_PROGRAM + 5] =
188 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10,
189 				kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x80),
190 
191 	/* Erase chip */
192 	[4 * ERASE_CHIP] =
193 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
194 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
195 	[4 * ERASE_CHIP + 1] =
196 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
197 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
198 	[4 * ERASE_CHIP + 2] =
199 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
200 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
201 	[4 * ERASE_CHIP + 3] =
202 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
203 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x80),
204 	/* 1 */
205 	[4 * ERASE_CHIP + 4] =
206 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
207 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
208 	[4 * ERASE_CHIP + 5] =
209 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
210 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
211 	[4 * ERASE_CHIP + 6] =
212 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
213 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
214 	[4 * ERASE_CHIP + 7] =
215 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
216 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
217 	/* 2 */
218 	[4 * ERASE_CHIP + 8] =
219 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
220 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
221 	[4 * ERASE_CHIP + 9] =
222 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
223 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
224 	[4 * ERASE_CHIP + 10] =
225 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
226 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x02),
227 	[4 * ERASE_CHIP + 11] =
228 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
229 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55),
230 	/* 3 */
231 	[4 * ERASE_CHIP + 12] =
232 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
233 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00),
234 	[4 * ERASE_CHIP + 13] =
235 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
236 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA),
237 	[4 * ERASE_CHIP + 14] =
238 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
239 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05),
240 	[4 * ERASE_CHIP + 15] =
241 		FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00,
242 				kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x10),
243 };
244 
245 
246 struct flash_flexspi_hyperflash_config {
247 	const struct device *controller;
248 };
249 
250 /* Device variables used in critical sections should be in this structure */
251 struct flash_flexspi_hyperflash_data {
252 	struct device controller;
253 	flexspi_device_config_t config;
254 	flexspi_port_t port;
255 	struct flash_pages_layout layout;
256 	struct flash_parameters flash_parameters;
257 };
258 
flash_flexspi_hyperflash_wait_bus_busy(const struct device * dev)259 static int flash_flexspi_hyperflash_wait_bus_busy(const struct device *dev)
260 {
261 	struct flash_flexspi_hyperflash_data *data = dev->data;
262 	flexspi_transfer_t transfer;
263 	int ret;
264 	bool is_busy;
265 	uint32_t read_value;
266 
267 	transfer.deviceAddress = 0;
268 	transfer.port = data->port;
269 	transfer.cmdType = kFLEXSPI_Read;
270 	transfer.SeqNumber = 2;
271 	transfer.seqIndex = READ_STATUS;
272 	transfer.data = &read_value;
273 	transfer.dataSize = 2;
274 
275 	do {
276 		ret = memc_flexspi_transfer(&data->controller, &transfer);
277 		if (ret != 0) {
278 			return ret;
279 		}
280 
281 		is_busy = !(read_value & 0x8000);
282 
283 		if (read_value & 0x3200) {
284 			ret = -EINVAL;
285 			break;
286 		}
287 	} while (is_busy);
288 
289 	return ret;
290 }
291 
flash_flexspi_hyperflash_write_enable(const struct device * dev,uint32_t address)292 static int flash_flexspi_hyperflash_write_enable(const struct device *dev, uint32_t address)
293 {
294 	struct flash_flexspi_hyperflash_data *data = dev->data;
295 	flexspi_transfer_t transfer;
296 	int ret;
297 
298 	transfer.deviceAddress = address;
299 	transfer.port = data->port;
300 	transfer.cmdType = kFLEXSPI_Command;
301 	transfer.SeqNumber = 2;
302 	transfer.seqIndex = WRITE_ENABLE;
303 
304 	ret = memc_flexspi_transfer(&data->controller, &transfer);
305 
306 	return ret;
307 }
308 
flash_flexspi_hyperflash_check_vendor_id(const struct device * dev)309 static int flash_flexspi_hyperflash_check_vendor_id(const struct device *dev)
310 {
311 	struct flash_flexspi_hyperflash_data *data = dev->data;
312 	uint8_t writebuf[4] = {0x00, 0x98};
313 	uint32_t buffer[2];
314 	int ret;
315 	flexspi_transfer_t transfer;
316 
317 	transfer.deviceAddress = (0x555 * 2);
318 	transfer.port = data->port;
319 	transfer.cmdType = kFLEXSPI_Write;
320 	transfer.SeqNumber = 1;
321 	transfer.seqIndex = WRITE_DATA;
322 	transfer.data = (uint32_t *)writebuf;
323 	transfer.dataSize = 2;
324 
325 	LOG_DBG("Reading id");
326 
327 	ret = memc_flexspi_transfer(&data->controller, &transfer);
328 	if (ret != 0) {
329 		LOG_ERR("failed to CFI");
330 		return ret;
331 	}
332 
333 	transfer.deviceAddress = (0x10 * 2);
334 	transfer.port = data->port;
335 	transfer.cmdType = kFLEXSPI_Read;
336 	transfer.SeqNumber = 1;
337 	transfer.seqIndex = READ_DATA;
338 	transfer.data = buffer;
339 	transfer.dataSize = 8;
340 
341 	ret = memc_flexspi_transfer(&data->controller, &transfer);
342 	if (ret != 0) {
343 		LOG_ERR("failed to read id");
344 		return ret;
345 	}
346 	buffer[1] &= 0xFFFF;
347 	/* Check that the data read out is  unicode "QRY" in big-endian order */
348 	if ((buffer[0] != 0x52005100) || (buffer[1] != 0x5900)) {
349 		LOG_ERR("data read out is wrong!");
350 		return -EINVAL;
351 	}
352 
353 	writebuf[1] = 0xF0;
354 	transfer.deviceAddress = 0;
355 	transfer.port = data->port;
356 	transfer.cmdType = kFLEXSPI_Write;
357 	transfer.SeqNumber = 1;
358 	transfer.seqIndex = WRITE_DATA;
359 	transfer.data = (uint32_t *)writebuf;
360 	transfer.dataSize = 2;
361 
362 	ret = memc_flexspi_transfer(&data->controller, &transfer);
363 	if (ret != 0) {
364 		LOG_ERR("failed to exit");
365 		return ret;
366 	}
367 
368 	memc_flexspi_reset(&data->controller);
369 
370 	return ret;
371 }
372 
flash_flexspi_hyperflash_page_program(const struct device * dev,off_t offset,const void * buffer,size_t len)373 static int flash_flexspi_hyperflash_page_program(const struct device *dev, off_t
374 		offset, const void *buffer, size_t len)
375 {
376 	struct flash_flexspi_hyperflash_data *data = dev->data;
377 
378 	flexspi_transfer_t transfer = {
379 		.deviceAddress = offset,
380 		.port = data->port,
381 		.cmdType = kFLEXSPI_Write,
382 		.SeqNumber = 2,
383 		.seqIndex = PAGE_PROGRAM,
384 		.data = (uint32_t *)buffer,
385 		.dataSize = len,
386 	};
387 
388 	LOG_DBG("Page programming %d bytes to 0x%08lx", len, offset);
389 
390 	return memc_flexspi_transfer(&data->controller, &transfer);
391 }
392 
flash_flexspi_hyperflash_read(const struct device * dev,off_t offset,void * buffer,size_t len)393 static int flash_flexspi_hyperflash_read(const struct device *dev, off_t offset,
394 		void *buffer, size_t len)
395 {
396 	struct flash_flexspi_hyperflash_data *data = dev->data;
397 
398 	uint8_t *src = memc_flexspi_get_ahb_address(&data->controller,
399 			data->port,
400 			offset);
401 	if (!src) {
402 		return -EINVAL;
403 	}
404 
405 	memcpy(buffer, src, len);
406 
407 	return 0;
408 }
409 
flash_flexspi_hyperflash_write(const struct device * dev,off_t offset,const void * buffer,size_t len)410 static int flash_flexspi_hyperflash_write(const struct device *dev, off_t offset,
411 		const void *buffer, size_t len)
412 {
413 	struct flash_flexspi_hyperflash_data *data = dev->data;
414 	size_t size = len;
415 	uint8_t *src = (uint8_t *)buffer;
416 	unsigned int key = 0;
417 	int i, j;
418 	int ret = -1;
419 
420 	uint8_t *dst = memc_flexspi_get_ahb_address(&data->controller,
421 			data->port,
422 			offset);
423 	if (!dst) {
424 		return -EINVAL;
425 	}
426 
427 	if (memc_flexspi_is_running_xip(&data->controller)) {
428 		/*
429 		 * ==== ENTER CRITICAL SECTION ====
430 		 * No flash access should be performed in critical section. All
431 		 * code and data accessed must reside in ram.
432 		 */
433 		key = irq_lock();
434 	}
435 
436 	/* Clock FlexSPI at 84 MHZ (42MHz SCLK in DDR mode) */
437 	(void)memc_flexspi_update_clock(&data->controller, &data->config,
438 					data->port, MHZ(84));
439 
440 	while (len) {
441 		/* Writing between two page sizes crashes the platform so we
442 		 * have to write the part that fits in the first page and then
443 		 * update the offset.
444 		 */
445 		i = MIN(SPI_HYPERFLASH_PAGE_SIZE - (offset %
446 					SPI_HYPERFLASH_PAGE_SIZE), len);
447 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_HYPERFLASH_WRITE_BUFFER
448 		for (j = 0; j < i; j++) {
449 			hyperflash_write_buf[j] = src[j];
450 		}
451 #endif
452 		ret = flash_flexspi_hyperflash_write_enable(dev, offset);
453 		if (ret != 0) {
454 			LOG_ERR("failed to enable write");
455 			break;
456 		}
457 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_HYPERFLASH_WRITE_BUFFER
458 		ret = flash_flexspi_hyperflash_page_program(dev, offset,
459 				hyperflash_write_buf, i);
460 #else
461 		ret = flash_flexspi_hyperflash_page_program(dev, offset, src, i);
462 #endif
463 		if (ret != 0) {
464 			LOG_ERR("failed to write");
465 			break;
466 		}
467 
468 		ret = flash_flexspi_hyperflash_wait_bus_busy(dev);
469 		if (ret != 0) {
470 			LOG_ERR("failed to wait bus busy");
471 			break;
472 		}
473 
474 		/* Do software reset. */
475 		memc_flexspi_reset(&data->controller);
476 		src += i;
477 		offset += i;
478 		len -= i;
479 	}
480 
481 	/* Clock FlexSPI at 332 MHZ (166 MHz SCLK in DDR mode) */
482 	(void)memc_flexspi_update_clock(&data->controller, &data->config,
483 					data->port, MHZ(332));
484 
485 #ifdef CONFIG_HAS_MCUX_CACHE
486 	DCACHE_InvalidateByRange((uint32_t) dst, size);
487 #endif
488 
489 	if (memc_flexspi_is_running_xip(&data->controller)) {
490 		/* ==== EXIT CRITICAL SECTION ==== */
491 		irq_unlock(key);
492 	}
493 
494 	return ret;
495 }
496 
flash_flexspi_hyperflash_erase(const struct device * dev,off_t offset,size_t size)497 static int flash_flexspi_hyperflash_erase(const struct device *dev, off_t offset, size_t size)
498 {
499 	struct flash_flexspi_hyperflash_data *data = dev->data;
500 	flexspi_transfer_t transfer;
501 	int ret = -1;
502 	int i;
503 	unsigned int key = 0;
504 	int num_sectors = size / SPI_HYPERFLASH_SECTOR_SIZE;
505 	uint8_t *dst = memc_flexspi_get_ahb_address(&data->controller,
506 			data->port,
507 			offset);
508 
509 	if (!dst) {
510 		return -EINVAL;
511 	}
512 
513 	if (offset % SPI_HYPERFLASH_SECTOR_SIZE) {
514 		LOG_ERR("Invalid offset");
515 		return -EINVAL;
516 	}
517 
518 	if (size % SPI_HYPERFLASH_SECTOR_SIZE) {
519 		LOG_ERR("Invalid offset");
520 		return -EINVAL;
521 	}
522 
523 	if (memc_flexspi_is_running_xip(&data->controller)) {
524 		/*
525 		 * ==== ENTER CRITICAL SECTION ====
526 		 * No flash access should be performed in critical section. All
527 		 * code and data accessed must reside in ram.
528 		 */
529 		key = irq_lock();
530 	}
531 
532 	for (i = 0; i < num_sectors; i++) {
533 		ret = flash_flexspi_hyperflash_write_enable(dev, offset);
534 		if (ret != 0) {
535 			LOG_ERR("failed to write_enable");
536 			break;
537 		}
538 
539 		LOG_DBG("Erasing sector at 0x%08lx", offset);
540 
541 		transfer.deviceAddress = offset;
542 		transfer.port = data->port;
543 		transfer.cmdType = kFLEXSPI_Command;
544 		transfer.SeqNumber = 4;
545 		transfer.seqIndex = ERASE_SECTOR;
546 
547 		ret = memc_flexspi_transfer(&data->controller, &transfer);
548 		if (ret != 0) {
549 			LOG_ERR("failed to erase");
550 			break;
551 		}
552 
553 		/* wait bus busy */
554 		ret = flash_flexspi_hyperflash_wait_bus_busy(dev);
555 		if (ret != 0) {
556 			LOG_ERR("failed to wait bus busy");
557 			break;
558 		}
559 
560 		/* Do software reset. */
561 		memc_flexspi_reset(&data->controller);
562 
563 		offset += SPI_HYPERFLASH_SECTOR_SIZE;
564 	}
565 
566 #ifdef CONFIG_HAS_MCUX_CACHE
567 	DCACHE_InvalidateByRange((uint32_t) dst, size);
568 #endif
569 
570 	if (memc_flexspi_is_running_xip(&data->controller)) {
571 		/* ==== EXIT CRITICAL SECTION ==== */
572 		irq_unlock(key);
573 	}
574 
575 	return ret;
576 }
577 
flash_flexspi_hyperflash_get_parameters(const struct device * dev)578 static const struct flash_parameters *flash_flexspi_hyperflash_get_parameters(
579 		const struct device *dev)
580 {
581 	struct flash_flexspi_hyperflash_data *data = dev->data;
582 
583 	return &data->flash_parameters;
584 }
585 
586 
flash_flexspi_hyperflash_pages_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)587 static void flash_flexspi_hyperflash_pages_layout(const struct device *dev,
588 		const struct flash_pages_layout **layout,
589 		size_t *layout_size)
590 {
591 	struct flash_flexspi_hyperflash_data *data = dev->data;
592 
593 	*layout = &data->layout;
594 	*layout_size = 1;
595 }
596 
flash_flexspi_hyperflash_init(const struct device * dev)597 static int flash_flexspi_hyperflash_init(const struct device *dev)
598 {
599 	const struct flash_flexspi_hyperflash_config *config = dev->config;
600 	struct flash_flexspi_hyperflash_data *data = dev->data;
601 
602 	/* Since the controller variable may be used in critical sections,
603 	 * copy the device pointer into a variable stored in RAM
604 	 */
605 	memcpy(&data->controller, config->controller, sizeof(struct device));
606 
607 	if (!device_is_ready(&data->controller)) {
608 		LOG_ERR("Controller device not ready");
609 		return -ENODEV;
610 	}
611 
612 	memc_flexspi_wait_bus_idle(&data->controller);
613 
614 	if (memc_flexspi_is_running_xip(&data->controller)) {
615 		/* Wait for bus idle before configuring */
616 		memc_flexspi_wait_bus_idle(&data->controller);
617 	}
618 	if (memc_flexspi_set_device_config(&data->controller, &data->config,
619 	    (const uint32_t *)flash_flexspi_hyperflash_lut,
620 	    sizeof(flash_flexspi_hyperflash_lut) / MEMC_FLEXSPI_CMD_SIZE,
621 	    data->port)) {
622 		LOG_ERR("Could not set device configuration");
623 		return -EINVAL;
624 	}
625 
626 	memc_flexspi_reset(&data->controller);
627 
628 	if (flash_flexspi_hyperflash_check_vendor_id(dev)) {
629 		LOG_ERR("Could not read vendor id");
630 		return -EIO;
631 	}
632 
633 	return 0;
634 }
635 
636 static const struct flash_driver_api flash_flexspi_hyperflash_api = {
637 	.read = flash_flexspi_hyperflash_read,
638 	.write = flash_flexspi_hyperflash_write,
639 	.erase = flash_flexspi_hyperflash_erase,
640 	.get_parameters = flash_flexspi_hyperflash_get_parameters,
641 #if defined(CONFIG_FLASH_PAGE_LAYOUT)
642 	.page_layout = flash_flexspi_hyperflash_pages_layout,
643 #endif
644 };
645 
646 #define CONCAT3(x, y, z) x ## y ## z
647 
648 #define CS_INTERVAL_UNIT(unit)						\
649 	CONCAT3(kFLEXSPI_CsIntervalUnit, unit, SckCycle)
650 
651 #define AHB_WRITE_WAIT_UNIT(unit)					\
652 	CONCAT3(kFLEXSPI_AhbWriteWaitUnit, unit, AhbCycle)
653 
654 #define FLASH_FLEXSPI_DEVICE_CONFIG(n)					\
655 	{								\
656 		.flexspiRootClk = MHZ(42),				\
657 		.flashSize = DT_INST_PROP(n, size) / 8 / KB(1),		\
658 		.CSIntervalUnit =					\
659 			CS_INTERVAL_UNIT(				\
660 				DT_INST_PROP(n, cs_interval_unit)),	\
661 		.CSInterval = DT_INST_PROP(n, cs_interval),		\
662 		.CSHoldTime = DT_INST_PROP(n, cs_hold_time),		\
663 		.CSSetupTime = DT_INST_PROP(n, cs_setup_time),		\
664 		.dataValidTime = DT_INST_PROP(n, data_valid_time),	\
665 		.columnspace = DT_INST_PROP(n, column_space),		\
666 		.enableWordAddress = DT_INST_PROP(n, word_addressable),	\
667 		.AWRSeqIndex = WRITE_DATA,					\
668 		.AWRSeqNumber = 1,					\
669 		.ARDSeqIndex = READ_DATA,				\
670 		.ARDSeqNumber = 1,					\
671 		.AHBWriteWaitUnit =					\
672 			AHB_WRITE_WAIT_UNIT(				\
673 				DT_INST_PROP(n, ahb_write_wait_unit)),	\
674 		.AHBWriteWaitInterval =					\
675 			DT_INST_PROP(n, ahb_write_wait_interval),	\
676 	}								\
677 
678 #define FLASH_FLEXSPI_HYPERFLASH(n)					\
679 	static struct flash_flexspi_hyperflash_config			\
680 		flash_flexspi_hyperflash_config_##n = {			\
681 		.controller = DEVICE_DT_GET(DT_INST_BUS(n)),		\
682 	};								\
683 	static struct flash_flexspi_hyperflash_data			\
684 		flash_flexspi_hyperflash_data_##n = {			\
685 		.config = FLASH_FLEXSPI_DEVICE_CONFIG(n),		\
686 		.port = DT_INST_REG_ADDR(n),				\
687 		.layout = {						\
688 			.pages_count = DT_INST_PROP(n, size) / 8	\
689 				/ SPI_HYPERFLASH_SECTOR_SIZE,		\
690 			.pages_size = SPI_HYPERFLASH_SECTOR_SIZE,	\
691 		},							\
692 		.flash_parameters = {					\
693 			.write_block_size = DT_INST_PROP(n, write_block_size), \
694 			.erase_value = HYPERFLASH_ERASE_VALUE,		\
695 		},							\
696 	};								\
697 									\
698 	DEVICE_DT_INST_DEFINE(n,					\
699 			      flash_flexspi_hyperflash_init,		\
700 			      NULL,					\
701 			      &flash_flexspi_hyperflash_data_##n,	\
702 			      &flash_flexspi_hyperflash_config_##n,	\
703 			      POST_KERNEL,				\
704 			      CONFIG_FLASH_INIT_PRIORITY,		\
705 			      &flash_flexspi_hyperflash_api);
706 
707 DT_INST_FOREACH_STATUS_OKAY(FLASH_FLEXSPI_HYPERFLASH)
708