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