1 /*
2 * Copyright 2021,2023 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT nxp_imx_flexspi_mx25um51345g
8
9 #include <zephyr/drivers/flash.h>
10 #include <zephyr/logging/log.h>
11 #include <zephyr/irq.h>
12 #include <zephyr/sys/util.h>
13 #include "spi_nor.h"
14 #include "memc_mcux_flexspi.h"
15
16 #ifdef CONFIG_HAS_MCUX_CACHE
17 #include <fsl_cache.h>
18 #endif
19
20 #define NOR_ERASE_VALUE 0xff
21
22 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_NOR_WRITE_BUFFER
23 static uint8_t nor_write_buf[SPI_NOR_PAGE_SIZE];
24 #endif
25
26 /*
27 * NOTE: If CONFIG_FLASH_MCUX_FLEXSPI_XIP is selected, Any external functions
28 * called while interacting with the flexspi MUST be relocated to SRAM or ITCM
29 * at runtime, so that the chip does not access the flexspi to read program
30 * instructions while it is being written to
31 *
32 * Additionally, no data used by this driver should be stored in flash.
33 */
34 #if defined(CONFIG_FLASH_MCUX_FLEXSPI_XIP) && (CONFIG_FLASH_LOG_LEVEL > 0)
35 #warning "Enabling flash driver logging and XIP mode simultaneously can cause \
36 read-while-write hazards. This configuration is not recommended."
37 #endif
38
39 /* FLASH_ENABLE_OCTAL_CMD: (01 = STR OPI Enable) , (02 = DTR OPI Enable) */
40 #if CONFIG_FLASH_MCUX_FLEXSPI_MX25UM51345G_OPI_DTR
41 #define NOR_FLASH_ENABLE_OCTAL_CMD 0x2
42 /* In OPI DTR mode, all writes must be 2 byte aligned, and multiples of 2 bytes */
43 #define NOR_WRITE_SIZE 2
44 #else
45 #define NOR_FLASH_ENABLE_OCTAL_CMD 0x1
46 #define NOR_WRITE_SIZE 1
47 #endif
48
49 LOG_MODULE_REGISTER(flash_flexspi_nor, CONFIG_FLASH_LOG_LEVEL);
50
51 enum {
52 /* Instructions matching with XIP layout */
53 READ,
54 WRITE_ENABLE_OPI,
55 WRITE_ENABLE,
56 ERASE_SECTOR,
57 PAGE_PROGRAM_INPUT,
58 PAGE_PROGRAM,
59 READ_ID_OPI,
60 ENTER_OPI,
61 READ_STATUS_REG,
62 ERASE_CHIP,
63 };
64
65 /* Device variables used in critical sections should be in this structure */
66 struct flash_flexspi_nor_data {
67 const struct device *controller;
68 flexspi_device_config_t config;
69 flexspi_port_t port;
70 uint64_t size;
71 struct flash_pages_layout layout;
72 struct flash_parameters flash_parameters;
73 };
74
75 static const uint32_t flash_flexspi_nor_lut[][4] = {
76 [READ_ID_OPI] = {
77 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x9F,
78 kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x60),
79 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x20,
80 kFLEXSPI_Command_DUMMY_DDR, kFLEXSPI_8PAD, 0x16),
81 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04,
82 kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0),
83 },
84
85 [WRITE_ENABLE] = {
86 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x06,
87 kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
88 },
89
90 [ENTER_OPI] = {
91 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x72,
92 kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x20),
93 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04,
94 kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
95 },
96
97 #if (NOR_FLASH_ENABLE_OCTAL_CMD == 0x1)
98 [READ_STATUS_REG] = {
99 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0x05,
100 kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0xFA),
101 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_8PAD, 0x20,
102 kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_8PAD, 0x14),
103 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_8PAD, 0x04,
104 kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0),
105 },
106 [WRITE_ENABLE_OPI] = {
107 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0x06,
108 kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0xF9),
109 },
110
111 [ERASE_SECTOR] = {
112 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0x21,
113 kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0xDE),
114 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_8PAD, 0x20,
115 kFLEXSPI_Command_STOP, kFLEXSPI_8PAD, 0),
116 },
117
118 [ERASE_CHIP] = {
119 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0x60,
120 kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0x9F),
121 },
122
123 [READ] = {
124 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0xEC,
125 kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0x13),
126 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_8PAD, 0x20,
127 kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_8PAD, 0x14),
128 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_8PAD, 0x04,
129 kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0),
130 },
131
132 [PAGE_PROGRAM] = {
133 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0x12,
134 kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0xED),
135 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_8PAD, 0x20,
136 kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_8PAD, 0x04),
137 },
138 #else
139 [READ_STATUS_REG] = {
140 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05,
141 kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xFA),
142 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x20,
143 kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x4),
144 },
145
146 [WRITE_ENABLE_OPI] = {
147 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x06,
148 kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xF9),
149 },
150
151 [ERASE_SECTOR] = {
152 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x21,
153 kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xDE),
154 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x20,
155 kFLEXSPI_Command_STOP, kFLEXSPI_8PAD, 0),
156 },
157
158 [ERASE_CHIP] = {
159 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x60,
160 kFLEXSPI_Command_SDR, kFLEXSPI_8PAD, 0x9F),
161 },
162
163 [READ] = {
164 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xEE,
165 kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x11),
166 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x20,
167 kFLEXSPI_Command_DUMMY_DDR, kFLEXSPI_8PAD, 0x08),
168 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04,
169 kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0),
170 },
171
172 [PAGE_PROGRAM] = {
173 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x12,
174 kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xED),
175 FLEXSPI_LUT_SEQ(kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x20,
176 kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x04),
177 },
178 #endif
179
180 };
181
flash_flexspi_nor_get_vendor_id(const struct device * dev,uint8_t * vendor_id)182 static int flash_flexspi_nor_get_vendor_id(const struct device *dev,
183 uint8_t *vendor_id)
184 {
185 struct flash_flexspi_nor_data *data = dev->data;
186 uint32_t buffer = 0;
187 int ret;
188
189 flexspi_transfer_t transfer = {
190 .deviceAddress = 0,
191 .port = data->port,
192 .cmdType = kFLEXSPI_Read,
193 .SeqNumber = 1,
194 .seqIndex = READ_ID_OPI,
195 .data = &buffer,
196 .dataSize = 1,
197 };
198
199 LOG_DBG("Reading id");
200
201 ret = memc_flexspi_transfer(data->controller, &transfer);
202 *vendor_id = buffer;
203
204 return ret;
205 }
206
flash_flexspi_nor_read_status(const struct device * dev,uint32_t * status)207 static int flash_flexspi_nor_read_status(const struct device *dev,
208 uint32_t *status)
209 {
210 struct flash_flexspi_nor_data *data = dev->data;
211
212 flexspi_transfer_t transfer = {
213 .deviceAddress = 0,
214 .port = data->port,
215 .cmdType = kFLEXSPI_Read,
216 .SeqNumber = 1,
217 .seqIndex = READ_STATUS_REG,
218 .data = status,
219 .dataSize = 1,
220 };
221
222 LOG_DBG("Reading status register");
223
224 return memc_flexspi_transfer(data->controller, &transfer);
225 }
226
flash_flexspi_nor_write_status(const struct device * dev,uint32_t * status)227 static int flash_flexspi_nor_write_status(const struct device *dev,
228 uint32_t *status)
229 {
230 struct flash_flexspi_nor_data *data = dev->data;
231
232 flexspi_transfer_t transfer = {
233 .deviceAddress = 0,
234 .port = data->port,
235 .cmdType = kFLEXSPI_Write,
236 .SeqNumber = 1,
237 .seqIndex = ENTER_OPI,
238 .data = status,
239 .dataSize = 1,
240 };
241
242 LOG_DBG("Writing status register");
243
244 return memc_flexspi_transfer(data->controller, &transfer);
245 }
246
flash_flexspi_nor_write_enable(const struct device * dev,bool enableOctal)247 static int flash_flexspi_nor_write_enable(const struct device *dev,
248 bool enableOctal)
249 {
250 struct flash_flexspi_nor_data *data = dev->data;
251 flexspi_transfer_t transfer;
252
253 transfer.deviceAddress = 0;
254 transfer.port = data->port;
255 transfer.cmdType = kFLEXSPI_Command;
256 transfer.SeqNumber = 1;
257 if (enableOctal) {
258 transfer.seqIndex = WRITE_ENABLE_OPI;
259 } else {
260 transfer.seqIndex = WRITE_ENABLE;
261 }
262 transfer.data = NULL;
263 transfer.dataSize = 0;
264
265 LOG_DBG("Enabling write");
266
267 return memc_flexspi_transfer(data->controller, &transfer);
268 }
269
flash_flexspi_nor_erase_sector(const struct device * dev,off_t offset)270 static int flash_flexspi_nor_erase_sector(const struct device *dev,
271 off_t offset)
272 {
273 struct flash_flexspi_nor_data *data = dev->data;
274
275 flexspi_transfer_t transfer = {
276 .deviceAddress = offset,
277 .port = data->port,
278 .cmdType = kFLEXSPI_Command,
279 .SeqNumber = 1,
280 .seqIndex = ERASE_SECTOR,
281 .data = NULL,
282 .dataSize = 0,
283 };
284
285 LOG_DBG("Erasing sector at 0x%08zx", (ssize_t) offset);
286
287 return memc_flexspi_transfer(data->controller, &transfer);
288 }
289
flash_flexspi_nor_erase_chip(const struct device * dev)290 static int flash_flexspi_nor_erase_chip(const struct device *dev)
291 {
292 struct flash_flexspi_nor_data *data = dev->data;
293
294 flexspi_transfer_t transfer = {
295 .deviceAddress = 0,
296 .port = data->port,
297 .cmdType = kFLEXSPI_Command,
298 .SeqNumber = 1,
299 .seqIndex = ERASE_CHIP,
300 .data = NULL,
301 .dataSize = 0,
302 };
303
304 LOG_DBG("Erasing chip");
305
306 return memc_flexspi_transfer(data->controller, &transfer);
307 }
308
flash_flexspi_nor_page_program(const struct device * dev,off_t offset,const void * buffer,size_t len)309 static int flash_flexspi_nor_page_program(const struct device *dev,
310 off_t offset, const void *buffer, size_t len)
311 {
312 struct flash_flexspi_nor_data *data = dev->data;
313
314 flexspi_transfer_t transfer = {
315 .deviceAddress = offset,
316 .port = data->port,
317 .cmdType = kFLEXSPI_Write,
318 .SeqNumber = 1,
319 .seqIndex = PAGE_PROGRAM,
320 .data = (uint32_t *) buffer,
321 .dataSize = len,
322 };
323
324 LOG_DBG("Page programming %d bytes to 0x%08zx", len, (ssize_t) offset);
325
326 return memc_flexspi_transfer(data->controller, &transfer);
327 }
328
flash_flexspi_nor_wait_bus_busy(const struct device * dev)329 static int flash_flexspi_nor_wait_bus_busy(const struct device *dev)
330 {
331 uint32_t status = 0;
332 int ret;
333
334 do {
335 ret = flash_flexspi_nor_read_status(dev, &status);
336 LOG_DBG("status: 0x%x", status);
337 if (ret) {
338 LOG_ERR("Could not read status");
339 return ret;
340 }
341 } while (status & BIT(0));
342
343 return 0;
344 }
345
flash_flexspi_enable_octal_mode(const struct device * dev)346 static int flash_flexspi_enable_octal_mode(const struct device *dev)
347 {
348 struct flash_flexspi_nor_data *data = dev->data;
349 /* FLASH_ENABLE_OCTAL_CMD: (01 = STR OPI Enable, 02 = DTR OPI Enable) */
350 uint32_t status = NOR_FLASH_ENABLE_OCTAL_CMD;
351
352 flash_flexspi_nor_write_enable(dev, false);
353 flash_flexspi_nor_write_status(dev, &status);
354 flash_flexspi_nor_wait_bus_busy(dev);
355 memc_flexspi_reset(data->controller);
356
357 return 0;
358 }
359
flash_flexspi_nor_read(const struct device * dev,off_t offset,void * buffer,size_t len)360 static int flash_flexspi_nor_read(const struct device *dev, off_t offset,
361 void *buffer, size_t len)
362 {
363 struct flash_flexspi_nor_data *data = dev->data;
364 uint8_t *src = memc_flexspi_get_ahb_address(data->controller,
365 data->port,
366 offset);
367
368 memcpy(buffer, src, len);
369
370 return 0;
371 }
372
flash_flexspi_nor_write(const struct device * dev,off_t offset,const void * buffer,size_t len)373 static int flash_flexspi_nor_write(const struct device *dev, off_t offset,
374 const void *buffer, size_t len)
375 {
376 struct flash_flexspi_nor_data *data = dev->data;
377 size_t size = len;
378 uint8_t *src = (uint8_t *) buffer;
379 int i;
380 unsigned int key = 0;
381
382 uint8_t *dst = memc_flexspi_get_ahb_address(data->controller,
383 data->port,
384 offset);
385
386 if (memc_flexspi_is_running_xip(data->controller)) {
387 /*
388 * ==== ENTER CRITICAL SECTION ====
389 * No flash access should be performed in critical section. All
390 * code and data accessed must reside in ram.
391 */
392 key = irq_lock();
393 }
394 if (IS_ENABLED(CONFIG_FLASH_MCUX_FLEXSPI_MX25UM51345G_OPI_DTR)) {
395 /* Check that write size and length are even */
396 if ((offset & 0x1) || (len & 0x1)) {
397 return -EINVAL;
398 }
399 }
400
401 while (len) {
402 /* If the offset isn't a multiple of the NOR page size, we first need
403 * to write the remaining part that fits, otherwise the write could
404 * be wrapped around within the same page
405 */
406 i = MIN(SPI_NOR_PAGE_SIZE - (offset % SPI_NOR_PAGE_SIZE), len);
407 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_NOR_WRITE_BUFFER
408 memcpy(nor_write_buf, src, i);
409 #endif
410 flash_flexspi_nor_write_enable(dev, true);
411 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_NOR_WRITE_BUFFER
412 flash_flexspi_nor_page_program(dev, offset, nor_write_buf, i);
413 #else
414 flash_flexspi_nor_page_program(dev, offset, src, i);
415 #endif
416 flash_flexspi_nor_wait_bus_busy(dev);
417 memc_flexspi_reset(data->controller);
418 src += i;
419 offset += i;
420 len -= i;
421 }
422
423 if (memc_flexspi_is_running_xip(data->controller)) {
424 /* ==== EXIT CRITICAL SECTION ==== */
425 irq_unlock(key);
426 }
427
428 #ifdef CONFIG_HAS_MCUX_CACHE
429 DCACHE_InvalidateByRange((uint32_t) dst, size);
430 #endif
431
432 return 0;
433 }
434
flash_flexspi_nor_erase(const struct device * dev,off_t offset,size_t size)435 static int flash_flexspi_nor_erase(const struct device *dev, off_t offset,
436 size_t size)
437 {
438 struct flash_flexspi_nor_data *data = dev->data;
439 int num_sectors = size / SPI_NOR_SECTOR_SIZE;
440 int i;
441 unsigned int key = 0;
442
443 uint8_t *dst = memc_flexspi_get_ahb_address(data->controller,
444 data->port,
445 offset);
446
447 if (offset % SPI_NOR_SECTOR_SIZE) {
448 LOG_ERR("Invalid offset");
449 return -EINVAL;
450 }
451
452 if (size % SPI_NOR_SECTOR_SIZE) {
453 LOG_ERR("Invalid size");
454 return -EINVAL;
455 }
456
457 if (memc_flexspi_is_running_xip(data->controller)) {
458 /*
459 * ==== ENTER CRITICAL SECTION ====
460 * No flash access should be performed in critical section. All
461 * code and data accessed must reside in ram.
462 */
463 key = irq_lock();
464 }
465
466 if ((offset == 0) && (size == data->config.flashSize * KB(1))) {
467 flash_flexspi_nor_write_enable(dev, true);
468 flash_flexspi_nor_erase_chip(dev);
469 flash_flexspi_nor_wait_bus_busy(dev);
470 memc_flexspi_reset(data->controller);
471 } else {
472 for (i = 0; i < num_sectors; i++) {
473 flash_flexspi_nor_write_enable(dev, true);
474 flash_flexspi_nor_erase_sector(dev, offset);
475 flash_flexspi_nor_wait_bus_busy(dev);
476 memc_flexspi_reset(data->controller);
477 offset += SPI_NOR_SECTOR_SIZE;
478 }
479 }
480
481 if (memc_flexspi_is_running_xip(data->controller)) {
482 /* ==== EXIT CRITICAL SECTION ==== */
483 irq_unlock(key);
484 }
485
486 #ifdef CONFIG_HAS_MCUX_CACHE
487 DCACHE_InvalidateByRange((uint32_t) dst, size);
488 #endif
489
490 return 0;
491 }
492
flash_flexspi_nor_get_parameters(const struct device * dev)493 static const struct flash_parameters *flash_flexspi_nor_get_parameters(
494 const struct device *dev)
495 {
496 struct flash_flexspi_nor_data *data = dev->data;
497
498 return &data->flash_parameters;
499 }
500
flash_flexspi_nor_get_size(const struct device * dev,uint64_t * size)501 static int flash_flexspi_nor_get_size(const struct device *dev, uint64_t *size)
502 {
503 const struct flash_flexspi_nor_data *data = dev->data;
504
505 *size = data->size;
506
507 return 0;
508 }
509
510 #if defined(CONFIG_FLASH_PAGE_LAYOUT)
flash_flexspi_nor_pages_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)511 static void flash_flexspi_nor_pages_layout(const struct device *dev,
512 const struct flash_pages_layout **layout, size_t *layout_size)
513 {
514 struct flash_flexspi_nor_data *data = dev->data;
515
516 *layout = &data->layout;
517 *layout_size = 1;
518 }
519 #endif /* CONFIG_FLASH_PAGE_LAYOUT */
520
flash_flexspi_nor_init(const struct device * dev)521 static int flash_flexspi_nor_init(const struct device *dev)
522 {
523 struct flash_flexspi_nor_data *data = dev->data;
524 uint8_t vendor_id;
525
526 if (!device_is_ready(data->controller)) {
527 LOG_ERR("Controller device not ready");
528 return -ENODEV;
529 }
530
531 if (memc_flexspi_is_running_xip(data->controller)) {
532 /* Wait for bus idle before configuring */
533 memc_flexspi_wait_bus_idle(data->controller);
534 }
535
536 if (memc_flexspi_set_device_config(data->controller, &data->config,
537 (const uint32_t *)flash_flexspi_nor_lut,
538 sizeof(flash_flexspi_nor_lut) / MEMC_FLEXSPI_CMD_SIZE,
539 data->port)) {
540 LOG_ERR("Could not set device configuration");
541 return -EINVAL;
542 }
543
544 memc_flexspi_reset(data->controller);
545
546 if (flash_flexspi_enable_octal_mode(dev)) {
547 LOG_ERR("Could not enable octal mode");
548 return -EIO;
549 }
550
551 if (flash_flexspi_nor_get_vendor_id(dev, &vendor_id)) {
552 LOG_ERR("Could not read vendor id");
553 return -EIO;
554 }
555 LOG_DBG("Vendor id: 0x%0x", vendor_id);
556
557 return 0;
558 }
559
560 static DEVICE_API(flash, flash_flexspi_nor_api) = {
561 .erase = flash_flexspi_nor_erase,
562 .write = flash_flexspi_nor_write,
563 .read = flash_flexspi_nor_read,
564 .get_parameters = flash_flexspi_nor_get_parameters,
565 .get_size = flash_flexspi_nor_get_size,
566 #if defined(CONFIG_FLASH_PAGE_LAYOUT)
567 .page_layout = flash_flexspi_nor_pages_layout,
568 #endif
569 };
570
571 #define CONCAT3(x, y, z) x ## y ## z
572
573 #define CS_INTERVAL_UNIT(unit) \
574 CONCAT3(kFLEXSPI_CsIntervalUnit, unit, SckCycle)
575
576 #define AHB_WRITE_WAIT_UNIT(unit) \
577 CONCAT3(kFLEXSPI_AhbWriteWaitUnit, unit, AhbCycle)
578
579 #define FLASH_FLEXSPI_DEVICE_CONFIG(n) \
580 { \
581 .flexspiRootClk = MHZ(120), \
582 .flashSize = DT_INST_PROP(n, size) / 8 / KB(1), \
583 .CSIntervalUnit = \
584 CS_INTERVAL_UNIT( \
585 DT_INST_PROP(n, cs_interval_unit)), \
586 .CSInterval = DT_INST_PROP(n, cs_interval), \
587 .CSHoldTime = DT_INST_PROP(n, cs_hold_time), \
588 .CSSetupTime = DT_INST_PROP(n, cs_setup_time), \
589 .dataValidTime = DT_INST_PROP(n, data_valid_time), \
590 .columnspace = DT_INST_PROP(n, column_space), \
591 .enableWordAddress = DT_INST_PROP(n, word_addressable), \
592 .AWRSeqIndex = 0, \
593 .AWRSeqNumber = 0, \
594 .ARDSeqIndex = READ, \
595 .ARDSeqNumber = 1, \
596 .AHBWriteWaitUnit = \
597 AHB_WRITE_WAIT_UNIT( \
598 DT_INST_PROP(n, ahb_write_wait_unit)), \
599 .AHBWriteWaitInterval = \
600 DT_INST_PROP(n, ahb_write_wait_interval), \
601 } \
602
603 #define FLASH_FLEXSPI_NOR(n) \
604 static struct flash_flexspi_nor_data \
605 flash_flexspi_nor_data_##n = { \
606 .controller = DEVICE_DT_GET(DT_INST_BUS(n)), \
607 .config = FLASH_FLEXSPI_DEVICE_CONFIG(n), \
608 .port = DT_INST_REG_ADDR(n), \
609 .size = DT_INST_PROP(n, size) / 8, \
610 .layout = { \
611 .pages_count = DT_INST_PROP(n, size) / 8 \
612 / SPI_NOR_SECTOR_SIZE, \
613 .pages_size = SPI_NOR_SECTOR_SIZE, \
614 }, \
615 .flash_parameters = { \
616 .write_block_size = NOR_WRITE_SIZE, \
617 .erase_value = NOR_ERASE_VALUE, \
618 }, \
619 }; \
620 \
621 DEVICE_DT_INST_DEFINE(n, \
622 flash_flexspi_nor_init, \
623 NULL, \
624 &flash_flexspi_nor_data_##n, \
625 NULL, \
626 POST_KERNEL, \
627 CONFIG_FLASH_INIT_PRIORITY, \
628 &flash_flexspi_nor_api);
629
630 DT_INST_FOREACH_STATUS_OKAY(FLASH_FLEXSPI_NOR)
631