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 (void)memc_flexspi_update_clock(&data->controller, &data->config,
437 data->port, MEMC_FLEXSPI_CLOCK_42M);
438
439 while (len) {
440 /* Writing between two page sizes crashes the platform so we
441 * have to write the part that fits in the first page and then
442 * update the offset.
443 */
444 i = MIN(SPI_HYPERFLASH_PAGE_SIZE - (offset %
445 SPI_HYPERFLASH_PAGE_SIZE), len);
446 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_HYPERFLASH_WRITE_BUFFER
447 for (j = 0; j < i; j++) {
448 hyperflash_write_buf[j] = src[j];
449 }
450 #endif
451 ret = flash_flexspi_hyperflash_write_enable(dev, offset);
452 if (ret != 0) {
453 LOG_ERR("failed to enable write");
454 break;
455 }
456 #ifdef CONFIG_FLASH_MCUX_FLEXSPI_HYPERFLASH_WRITE_BUFFER
457 ret = flash_flexspi_hyperflash_page_program(dev, offset,
458 hyperflash_write_buf, i);
459 #else
460 ret = flash_flexspi_hyperflash_page_program(dev, offset, src, i);
461 #endif
462 if (ret != 0) {
463 LOG_ERR("failed to write");
464 break;
465 }
466
467 ret = flash_flexspi_hyperflash_wait_bus_busy(dev);
468 if (ret != 0) {
469 LOG_ERR("failed to wait bus busy");
470 break;
471 }
472
473 /* Do software reset. */
474 memc_flexspi_reset(&data->controller);
475 src += i;
476 offset += i;
477 len -= i;
478 }
479
480 (void)memc_flexspi_update_clock(&data->controller, &data->config,
481 data->port, MEMC_FLEXSPI_CLOCK_166M);
482
483 #ifdef CONFIG_HAS_MCUX_CACHE
484 DCACHE_InvalidateByRange((uint32_t) dst, size);
485 #endif
486
487 if (memc_flexspi_is_running_xip(&data->controller)) {
488 /* ==== EXIT CRITICAL SECTION ==== */
489 irq_unlock(key);
490 }
491
492 return ret;
493 }
494
flash_flexspi_hyperflash_erase(const struct device * dev,off_t offset,size_t size)495 static int flash_flexspi_hyperflash_erase(const struct device *dev, off_t offset, size_t size)
496 {
497 struct flash_flexspi_hyperflash_data *data = dev->data;
498 flexspi_transfer_t transfer;
499 int ret = -1;
500 int i;
501 unsigned int key = 0;
502 int num_sectors = size / SPI_HYPERFLASH_SECTOR_SIZE;
503 uint8_t *dst = memc_flexspi_get_ahb_address(&data->controller,
504 data->port,
505 offset);
506
507 if (!dst) {
508 return -EINVAL;
509 }
510
511 if (offset % SPI_HYPERFLASH_SECTOR_SIZE) {
512 LOG_ERR("Invalid offset");
513 return -EINVAL;
514 }
515
516 if (size % SPI_HYPERFLASH_SECTOR_SIZE) {
517 LOG_ERR("Invalid offset");
518 return -EINVAL;
519 }
520
521 if (memc_flexspi_is_running_xip(&data->controller)) {
522 /*
523 * ==== ENTER CRITICAL SECTION ====
524 * No flash access should be performed in critical section. All
525 * code and data accessed must reside in ram.
526 */
527 key = irq_lock();
528 }
529
530 for (i = 0; i < num_sectors; i++) {
531 ret = flash_flexspi_hyperflash_write_enable(dev, offset);
532 if (ret != 0) {
533 LOG_ERR("failed to write_enable");
534 break;
535 }
536
537 LOG_DBG("Erasing sector at 0x%08lx", offset);
538
539 transfer.deviceAddress = offset;
540 transfer.port = data->port;
541 transfer.cmdType = kFLEXSPI_Command;
542 transfer.SeqNumber = 4;
543 transfer.seqIndex = ERASE_SECTOR;
544
545 ret = memc_flexspi_transfer(&data->controller, &transfer);
546 if (ret != 0) {
547 LOG_ERR("failed to erase");
548 break;
549 }
550
551 /* wait bus busy */
552 ret = flash_flexspi_hyperflash_wait_bus_busy(dev);
553 if (ret != 0) {
554 LOG_ERR("failed to wait bus busy");
555 break;
556 }
557
558 /* Do software reset. */
559 memc_flexspi_reset(&data->controller);
560
561 offset += SPI_HYPERFLASH_SECTOR_SIZE;
562 }
563
564 #ifdef CONFIG_HAS_MCUX_CACHE
565 DCACHE_InvalidateByRange((uint32_t) dst, size);
566 #endif
567
568 if (memc_flexspi_is_running_xip(&data->controller)) {
569 /* ==== EXIT CRITICAL SECTION ==== */
570 irq_unlock(key);
571 }
572
573 return ret;
574 }
575
flash_flexspi_hyperflash_get_parameters(const struct device * dev)576 static const struct flash_parameters *flash_flexspi_hyperflash_get_parameters(
577 const struct device *dev)
578 {
579 struct flash_flexspi_hyperflash_data *data = dev->data;
580
581 return &data->flash_parameters;
582 }
583
584
flash_flexspi_hyperflash_pages_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)585 static void flash_flexspi_hyperflash_pages_layout(const struct device *dev,
586 const struct flash_pages_layout **layout,
587 size_t *layout_size)
588 {
589 struct flash_flexspi_hyperflash_data *data = dev->data;
590
591 *layout = &data->layout;
592 *layout_size = 1;
593 }
594
flash_flexspi_hyperflash_init(const struct device * dev)595 static int flash_flexspi_hyperflash_init(const struct device *dev)
596 {
597 const struct flash_flexspi_hyperflash_config *config = dev->config;
598 struct flash_flexspi_hyperflash_data *data = dev->data;
599 uint32_t temp_lut[sizeof(flash_flexspi_hyperflash_lut) / sizeof(uint32_t)];
600
601 /* Since the controller variable may be used in critical sections,
602 * copy the device pointer into a variable stored in RAM
603 */
604 memcpy(&data->controller, config->controller, sizeof(struct device));
605
606 if (!device_is_ready(&data->controller)) {
607 LOG_ERR("Controller device not ready");
608 return -ENODEV;
609 }
610
611 memc_flexspi_wait_bus_idle(&data->controller);
612
613 if (!memc_flexspi_is_running_xip(&data->controller) &&
614 memc_flexspi_set_device_config(&data->controller, &data->config,
615 data->port)) {
616 LOG_ERR("Could not set device configuration");
617 return -EINVAL;
618 }
619
620 /*
621 * Using the LUT stored in the FlexSPI directly when updating
622 * the FlexSPI can result in an invalid LUT entry being stored,
623 * as the LUT itself describes how the FlexSPI should access the flash.
624 * To resolve this, copy the LUT to a array placed in RAM before
625 * updating the FlexSPI.
626 */
627 memcpy(temp_lut, flash_flexspi_hyperflash_lut,
628 sizeof(flash_flexspi_hyperflash_lut));
629
630 if (memc_flexspi_update_lut(&data->controller, 0,
631 (const uint32_t *) temp_lut,
632 sizeof(temp_lut) / sizeof(uint32_t))) {
633 LOG_ERR("Could not update lut");
634 return -EINVAL;
635 }
636
637 memc_flexspi_reset(&data->controller);
638
639 if (flash_flexspi_hyperflash_check_vendor_id(dev)) {
640 LOG_ERR("Could not read vendor id");
641 return -EIO;
642 }
643
644 return 0;
645 }
646
647 static const struct flash_driver_api flash_flexspi_hyperflash_api = {
648 .read = flash_flexspi_hyperflash_read,
649 .write = flash_flexspi_hyperflash_write,
650 .erase = flash_flexspi_hyperflash_erase,
651 .get_parameters = flash_flexspi_hyperflash_get_parameters,
652 #if defined(CONFIG_FLASH_PAGE_LAYOUT)
653 .page_layout = flash_flexspi_hyperflash_pages_layout,
654 #endif
655 };
656
657 #define CONCAT3(x, y, z) x ## y ## z
658
659 #define CS_INTERVAL_UNIT(unit) \
660 CONCAT3(kFLEXSPI_CsIntervalUnit, unit, SckCycle)
661
662 #define AHB_WRITE_WAIT_UNIT(unit) \
663 CONCAT3(kFLEXSPI_AhbWriteWaitUnit, unit, AhbCycle)
664
665 #define FLASH_FLEXSPI_DEVICE_CONFIG(n) \
666 { \
667 .flexspiRootClk = MHZ(42), \
668 .flashSize = DT_INST_PROP(n, size) / 8 / KB(1), \
669 .CSIntervalUnit = \
670 CS_INTERVAL_UNIT( \
671 DT_INST_PROP(n, cs_interval_unit)), \
672 .CSInterval = DT_INST_PROP(n, cs_interval), \
673 .CSHoldTime = DT_INST_PROP(n, cs_hold_time), \
674 .CSSetupTime = DT_INST_PROP(n, cs_setup_time), \
675 .dataValidTime = DT_INST_PROP(n, data_valid_time), \
676 .columnspace = DT_INST_PROP(n, column_space), \
677 .enableWordAddress = DT_INST_PROP(n, word_addressable), \
678 .AWRSeqIndex = WRITE_DATA, \
679 .AWRSeqNumber = 1, \
680 .ARDSeqIndex = READ_DATA, \
681 .ARDSeqNumber = 1, \
682 .AHBWriteWaitUnit = \
683 AHB_WRITE_WAIT_UNIT( \
684 DT_INST_PROP(n, ahb_write_wait_unit)), \
685 .AHBWriteWaitInterval = \
686 DT_INST_PROP(n, ahb_write_wait_interval), \
687 } \
688
689 #define FLASH_FLEXSPI_HYPERFLASH(n) \
690 static struct flash_flexspi_hyperflash_config \
691 flash_flexspi_hyperflash_config_##n = { \
692 .controller = DEVICE_DT_GET(DT_INST_BUS(n)), \
693 }; \
694 static struct flash_flexspi_hyperflash_data \
695 flash_flexspi_hyperflash_data_##n = { \
696 .config = FLASH_FLEXSPI_DEVICE_CONFIG(n), \
697 .port = DT_INST_REG_ADDR(n), \
698 .layout = { \
699 .pages_count = DT_INST_PROP(n, size) / 8 \
700 / SPI_HYPERFLASH_SECTOR_SIZE, \
701 .pages_size = SPI_HYPERFLASH_SECTOR_SIZE, \
702 }, \
703 .flash_parameters = { \
704 .write_block_size = DT_INST_PROP(n, write_block_size), \
705 .erase_value = HYPERFLASH_ERASE_VALUE, \
706 }, \
707 }; \
708 \
709 DEVICE_DT_INST_DEFINE(n, \
710 flash_flexspi_hyperflash_init, \
711 NULL, \
712 &flash_flexspi_hyperflash_data_##n, \
713 &flash_flexspi_hyperflash_config_##n, \
714 POST_KERNEL, \
715 CONFIG_FLASH_INIT_PRIORITY, \
716 &flash_flexspi_hyperflash_api);
717
718 DT_INST_FOREACH_STATUS_OKAY(FLASH_FLEXSPI_HYPERFLASH)
719