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