1 /*
2 * Copyright 2024 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stdbool.h>
8
9 #include "mflash_drv.h"
10 #include "fsl_xspi.h"
11 #include "fsl_cache.h"
12 #include "board.h"
13
14 /*******************************************************************************
15 * Definitions
16 ******************************************************************************/
17
18 #define XSPI_INSTANCE XSPI0
19 #define XSPI_CLOCK kCLOCK_Xspi0
20 #define XSPI_RX_SAMPLE_CLOCK kXSPI_ReadSampleClkExternalInputFromDqsPad
21
22 /* Octal mode used by default, pinmux already set to this mode.
23 NOTE: Quad mode has not beed tested */
24
25 #if !defined(MFLASH_USE_OCTAL_MODE) || MFLASH_USE_OCTAL_MODE
26 #define USE_OCTAL_MODE true
27 #else
28 #define USE_OCTAL_MODE false
29 #endif
30
31 #define NOR_CMD_LUT_SEQ_IDX_READ 0
32 #define NOR_CMD_LUT_SEQ_IDX_READ_STATUS 1
33 #define NOR_CMD_LUT_SEQ_IDX_READ_STATUS_OPI 2
34 #define NOR_CMD_LUT_SEQ_IDX_WRITE_ENABLE 3
35 #define NOR_CMD_LUT_SEQ_IDX_WRITE_ENABLE_OPI 4
36 #define NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_OCTAL 7
37 #define NOR_CMD_LUT_SEQ_IDX_ERASE_SECTOR 8
38 #define NOR_CMD_LUT_SEQ_IDX_READ_ID_SPI 9
39 #define NOR_CMD_LUT_SEQ_IDX_READ_ID_OPI 10
40 #define NOR_CMD_LUT_SEQ_IDX_ERASE_CHIP 11
41 #define NOR_CMD_LUT_SEQ_IDX_ENTER_OPI 12
42
43 #define CUSTOM_LUT_LENGTH 80
44 #define FLASH_BUSY_STATUS_OFFSET 0
45 #define FLASH_WE_STATUS_OFFSET 7
46 #define FLASH_ENABLE_OCTAL_CMD 0x02
47
48 /*******************************************************************************
49 * Prototypes
50 ******************************************************************************/
51
52 /*******************************************************************************
53 * Variables
54 ******************************************************************************/
55 static xspi_device_ddr_config_t flashDDrConfig = {
56 .ddrDataAlignedClk = kXSPI_DDRDataAlignedWith2xInternalRefClk,
57 .enableDdr = true,
58 .enableByteSwapInOctalMode = false,
59 };
60 static xspi_device_config_t deviceconfig = {
61 .xspiRootClk = 400000000, /*!< 400MHz */
62 .enableCknPad = false, /*!< Do not support differential clock */
63 .deviceInterface = kXSPI_StrandardExtendedSPI, /*!< Support Single IO and Octal IO */
64 .interfaceSettings.strandardExtendedSPISettings.pageSize = 256, /*!< 256 byte page buffer. */
65 .CSHoldTime = 3,
66 .CSSetupTime = 3,
67 .sampleClkConfig.sampleClkSource = kXSPI_SampleClkFromExternalDQS, /*!< Device support Data strobe signal. */
68 .sampleClkConfig.enableDQSLatency = false,
69 .sampleClkConfig.dllConfig.dllMode = kXSPI_AutoUpdateMode,
70 .sampleClkConfig.dllConfig.useRefValue = true,
71 .sampleClkConfig.dllConfig.enableCdl8 = false,
72 .ptrDeviceDdrConfig = &flashDDrConfig,
73 .addrMode = kXSPI_DeviceByteAddressable,
74 .columnAddrWidth = 0U,
75 .enableCASInterleaving = false,
76 .deviceSize[0] = MFLASH_FLASH_SIZE / 1024U,
77 .deviceSize[1] = MFLASH_FLASH_SIZE / 1024U, /*!< Single DIE flash, so deviceSize1 should equal to deviceSize0. */
78 .ptrDeviceRegInfo = NULL, /*!< Not used in this example. */
79 };
80
81 static const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
82 /*Read*/
83 [5 * NOR_CMD_LUT_SEQ_IDX_READ] =
84 XSPI_LUT_SEQ(kXSPI_Command_DDR, kXSPI_8PAD, 0xEE, kXSPI_Command_DDR, kXSPI_8PAD, 0x11),
85 [5 * NOR_CMD_LUT_SEQ_IDX_READ + 1] =
86 XSPI_LUT_SEQ(kXSPI_Command_RADDR_DDR, kXSPI_8PAD, 0x20, kXSPI_Command_DUMMY_SDR, kXSPI_8PAD, 0x12),
87 [5 * NOR_CMD_LUT_SEQ_IDX_READ + 2] =
88 XSPI_LUT_SEQ(kXSPI_Command_DUMMY_SDR, kXSPI_8PAD, 0x2, kXSPI_Command_READ_DDR, kXSPI_8PAD, 0x4),
89 [5 * NOR_CMD_LUT_SEQ_IDX_READ + 3] = XSPI_LUT_SEQ(kXSPI_Command_STOP, kXSPI_8PAD, 0x0, 0, 0, 0),
90
91 /*Read status SPI*/
92 [5 * NOR_CMD_LUT_SEQ_IDX_READ_STATUS] =
93 XSPI_LUT_SEQ(kXSPI_Command_SDR, kXSPI_1PAD, 0x05, kXSPI_Command_READ_SDR, kXSPI_1PAD, 0x04),
94
95 /* Read Status OPI */
96 [5 * NOR_CMD_LUT_SEQ_IDX_READ_STATUS_OPI] =
97 XSPI_LUT_SEQ(kXSPI_Command_DDR, kXSPI_8PAD, 0x05, kXSPI_Command_DDR, kXSPI_8PAD, 0xFA),
98 [5 * NOR_CMD_LUT_SEQ_IDX_READ_STATUS_OPI + 1] =
99 XSPI_LUT_SEQ(kXSPI_Command_RADDR_DDR, kXSPI_8PAD, 0x20, kXSPI_Command_DUMMY_SDR, kXSPI_8PAD, 0x12),
100 [5 * NOR_CMD_LUT_SEQ_IDX_READ_STATUS_OPI + 2] =
101 XSPI_LUT_SEQ(kXSPI_Command_DUMMY_SDR, kXSPI_8PAD, 0x2, kXSPI_Command_READ_DDR, kXSPI_8PAD, 0x4),
102 [5 * NOR_CMD_LUT_SEQ_IDX_READ_STATUS_OPI + 3] = XSPI_LUT_SEQ(kXSPI_Command_STOP, kXSPI_8PAD, 0x0, 0, 0, 0),
103
104 /*Write enable*/
105 [5 * NOR_CMD_LUT_SEQ_IDX_WRITE_ENABLE] =
106 XSPI_LUT_SEQ(kXSPI_Command_SDR, kXSPI_1PAD, 0x06, kXSPI_Command_STOP, kXSPI_1PAD, 0x04),
107
108 /* Write Enable - OPI */
109 [5 * NOR_CMD_LUT_SEQ_IDX_WRITE_ENABLE_OPI] =
110 XSPI_LUT_SEQ(kXSPI_Command_DDR, kXSPI_8PAD, 0x06, kXSPI_Command_DDR, kXSPI_8PAD, 0xF9),
111
112 /* Read ID */
113 [5 * NOR_CMD_LUT_SEQ_IDX_READ_ID_OPI + 0] =
114 XSPI_LUT_SEQ(kXSPI_Command_DDR, kXSPI_8PAD, 0x9F, kXSPI_Command_DDR, kXSPI_8PAD, 0x60),
115 [5 * NOR_CMD_LUT_SEQ_IDX_READ_ID_OPI + 1] = XSPI_LUT_SEQ(kXSPI_Command_RADDR_DDR,
116 kXSPI_8PAD,
117 0x20,
118 kXSPI_Command_DUMMY_SDR,
119 kXSPI_8PAD,
120 0x04), /*address is 0x00,0x00,0x00,0x00*/
121 [5 * NOR_CMD_LUT_SEQ_IDX_READ_ID_OPI + 2] =
122 XSPI_LUT_SEQ(kXSPI_Command_READ_DDR, kXSPI_8PAD, 0x04, kXSPI_Command_STOP, kXSPI_1PAD, 0x0),
123
124 /* Erase Sector */
125 [5 * NOR_CMD_LUT_SEQ_IDX_ERASE_SECTOR] =
126 XSPI_LUT_SEQ(kXSPI_Command_DDR, kXSPI_8PAD, 0x21, kXSPI_Command_DDR, kXSPI_8PAD, 0xDE),
127 [5 * NOR_CMD_LUT_SEQ_IDX_ERASE_SECTOR + 1] =
128 XSPI_LUT_SEQ(kXSPI_Command_RADDR_DDR, kXSPI_8PAD, 0x20, kXSPI_Command_STOP, kXSPI_8PAD, 0x0),
129
130 /* Enable OPI DDR mode */
131 [5 * NOR_CMD_LUT_SEQ_IDX_ENTER_OPI] =
132 XSPI_LUT_SEQ(kXSPI_Command_SDR, kXSPI_1PAD, 0x72, kXSPI_Command_SDR, kXSPI_1PAD, 0x00),
133 [5 * NOR_CMD_LUT_SEQ_IDX_ENTER_OPI + 1] =
134 XSPI_LUT_SEQ(kXSPI_Command_SDR, kXSPI_1PAD, 0x00, kXSPI_Command_SDR, kXSPI_1PAD, 0x00),
135 [5 * NOR_CMD_LUT_SEQ_IDX_ENTER_OPI + 2] =
136 XSPI_LUT_SEQ(kXSPI_Command_SDR, kXSPI_1PAD, 0x00, kXSPI_Command_WRITE_SDR, kXSPI_1PAD, 0x01),
137
138 /* Page program */
139 [5 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_OCTAL] =
140 XSPI_LUT_SEQ(kXSPI_Command_DDR, kXSPI_8PAD, 0x12, kXSPI_Command_DDR, kXSPI_8PAD, 0xED),
141 [5 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_OCTAL + 1] =
142 XSPI_LUT_SEQ(kXSPI_Command_RADDR_DDR, kXSPI_8PAD, 0x20, kXSPI_Command_WRITE_DDR, kXSPI_8PAD, 0x4),
143
144 /* Erase Chip */
145 [5 * NOR_CMD_LUT_SEQ_IDX_ERASE_CHIP] =
146 XSPI_LUT_SEQ(kXSPI_Command_DDR, kXSPI_8PAD, 0x60, kXSPI_Command_DDR, kXSPI_8PAD, 0x9F),
147 };
148
149 /*******************************************************************************
150 * Code
151 ******************************************************************************/
152 /* Temporary fix untill cache64 control is implemented in xspi driver */
CACHE64_Invalidate(void)153 static void CACHE64_Invalidate(void)
154 {
155 CACHE64_CTRL0->CCR |= CACHE64_CTRL_CCR_INVW0_MASK | CACHE64_CTRL_CCR_INVW1_MASK | CACHE64_CTRL_CCR_GO_MASK;
156 while ((CACHE64_CTRL0->CCR & CACHE64_CTRL_CCR_GO_MASK) != 0x00U)
157 {
158 }
159 CACHE64_CTRL0->CCR &= ~(CACHE64_CTRL_CCR_INVW0_MASK | CACHE64_CTRL_CCR_INVW1_MASK);
160 }
161
xspi_nor_write_enable(XSPI_Type * base,uint32_t baseAddr,bool useOctal)162 static status_t xspi_nor_write_enable(XSPI_Type *base, uint32_t baseAddr, bool useOctal)
163 {
164 xspi_transfer_t flashXfer;
165 status_t status;
166
167 /* Write enable */
168 flashXfer.deviceAddress = MFLASH_BASE_ADDRESS + baseAddr;
169 flashXfer.cmdType = kXSPI_Command;
170 flashXfer.targetGroup = kXSPI_TargetGroup0;
171 flashXfer.data = NULL;
172 flashXfer.dataSize = 0UL;
173 flashXfer.lockArbitration = false;
174 if (useOctal)
175 {
176 flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITE_ENABLE_OPI;
177 }
178 else
179 {
180 flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_WRITE_ENABLE;
181 }
182
183 status = XSPI_TransferBlocking(base, &flashXfer);
184
185 return status;
186 }
187
xspi_nor_wait_bus_busy(XSPI_Type * base,bool useOctal)188 static status_t xspi_nor_wait_bus_busy(XSPI_Type *base, bool useOctal)
189 {
190 /* Wait status ready. */
191 bool isBusy;
192 uint32_t readValue;
193 status_t status;
194 xspi_transfer_t flashXfer;
195
196 flashXfer.deviceAddress = MFLASH_BASE_ADDRESS;
197 flashXfer.cmdType = kXSPI_Read;
198 flashXfer.data = &readValue;
199 flashXfer.targetGroup = kXSPI_TargetGroup0;
200 if (useOctal)
201 {
202 flashXfer.dataSize = 2;
203 flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READ_STATUS_OPI;
204 }
205 else
206 {
207 flashXfer.dataSize = 1;
208 flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READ_STATUS;
209 }
210 flashXfer.lockArbitration = false;
211
212 do
213 {
214 status = XSPI_TransferBlocking(base, &flashXfer);
215
216 if (status != kStatus_Success)
217 {
218 return status;
219 }
220
221 if ((readValue & (1U << FLASH_BUSY_STATUS_OFFSET)) != 0U)
222 {
223 isBusy = true;
224 }
225 else
226 {
227 isBusy = false;
228 }
229
230 } while (isBusy);
231
232 return status;
233 }
234
235 #if defined(FLASH_ENABLE_OCTAL_CMD)
xspi_nor_enable_octal_mode(XSPI_Type * base)236 static status_t xspi_nor_enable_octal_mode(XSPI_Type *base)
237 {
238 xspi_transfer_t flashXfer;
239 status_t status;
240
241 uint32_t writeValue = FLASH_ENABLE_OCTAL_CMD;
242
243 /* Write enable */
244 status = xspi_nor_write_enable(base, 0, false);
245
246 if (status != kStatus_Success)
247 {
248 return status;
249 }
250
251 /* Enable quad mode. */
252 flashXfer.deviceAddress = MFLASH_BASE_ADDRESS;
253 flashXfer.cmdType = kXSPI_Write;
254 flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ENTER_OPI;
255 flashXfer.targetGroup = kXSPI_TargetGroup0;
256 flashXfer.data = &writeValue;
257 flashXfer.dataSize = 1;
258 flashXfer.lockArbitration = false;
259
260 status = XSPI_TransferBlocking(base, &flashXfer);
261 if (status != kStatus_Success)
262 {
263 return status;
264 }
265
266 status = xspi_nor_wait_bus_busy(base, true);
267
268 return status;
269 }
270 #endif
271
xspi_nor_flash_read(XSPI_Type * base,uint32_t dstAddr,uint32_t * src,uint32_t length,bool useOctal)272 static status_t xspi_nor_flash_read(XSPI_Type *base, uint32_t dstAddr, uint32_t *src, uint32_t length, bool useOctal)
273 {
274 status_t status;
275 xspi_transfer_t flashXfer;
276
277 /* Prepare page program command */
278 flashXfer.deviceAddress = MFLASH_BASE_ADDRESS + dstAddr;
279 flashXfer.cmdType = kXSPI_Read;
280 flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_READ;
281 flashXfer.targetGroup = kXSPI_TargetGroup0;
282 flashXfer.data = src;
283 flashXfer.dataSize = length;
284 flashXfer.lockArbitration = false;
285 status = XSPI_TransferBlocking(base, &flashXfer);
286
287 if (status != kStatus_Success)
288 {
289 return status;
290 }
291
292 status = xspi_nor_wait_bus_busy(base, useOctal);
293
294 return status;
295 }
296
xspi_nor_flash_erase_sector(XSPI_Type * base,uint32_t address,bool useOctal)297 static status_t xspi_nor_flash_erase_sector(XSPI_Type *base, uint32_t address, bool useOctal)
298 {
299 status_t status;
300 xspi_transfer_t flashXfer;
301
302 /* Write enable */
303 status = xspi_nor_write_enable(base, 0, useOctal);
304
305 if (status != kStatus_Success)
306 {
307 return status;
308 }
309
310 flashXfer.deviceAddress = MFLASH_BASE_ADDRESS + address;
311 flashXfer.cmdType = kXSPI_Command;
312 flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ERASE_SECTOR;
313 flashXfer.targetGroup = kXSPI_TargetGroup0;
314 flashXfer.data = NULL;
315 flashXfer.dataSize = 0UL;
316 flashXfer.lockArbitration = false;
317 status = XSPI_TransferBlocking(base, &flashXfer);
318
319 if (status != kStatus_Success)
320 {
321 return status;
322 }
323
324 status = xspi_nor_wait_bus_busy(base, useOctal);
325
326 return status;
327 }
328
xspi_nor_flash_page_program(XSPI_Type * base,uint32_t dstAddr,uint32_t * src,bool useOctal)329 static status_t xspi_nor_flash_page_program(XSPI_Type *base, uint32_t dstAddr, uint32_t *src, bool useOctal)
330 {
331 status_t status;
332 xspi_transfer_t flashXfer;
333
334 /* To make sure external flash be in idle status, added wait for busy before program data for
335 an external flash without RWW(read while write) attribute.*/
336 status = xspi_nor_wait_bus_busy(base, useOctal);
337
338 if (kStatus_Success != status)
339 {
340 return status;
341 }
342
343 /* Write enable. */
344 status = xspi_nor_write_enable(base, dstAddr, useOctal);
345
346 if (status != kStatus_Success)
347 {
348 return status;
349 }
350
351 /* Prepare page program command */
352 flashXfer.deviceAddress = MFLASH_BASE_ADDRESS + dstAddr;
353 flashXfer.cmdType = kXSPI_Write;
354 flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_OCTAL;
355 flashXfer.targetGroup = kXSPI_TargetGroup0;
356 flashXfer.data = src;
357 flashXfer.dataSize = MFLASH_PAGE_SIZE;
358 flashXfer.lockArbitration = false;
359 status = XSPI_TransferBlocking(base, &flashXfer);
360
361 if (status != kStatus_Success)
362 {
363 return status;
364 }
365
366 status = xspi_nor_wait_bus_busy(base, useOctal);
367
368 return status;
369 }
370
mflash_drv_init_internal(XSPI_Type * base,bool useOctal)371 static int32_t mflash_drv_init_internal(XSPI_Type *base, bool useOctal)
372 {
373 uint32_t primask;
374 xspi_config_t config;
375 xspi_ahb_access_config_t xspiAhbAccessConfig;
376 xspi_ip_access_config_t xspiIpAccessConfig;
377 status_t status = kStatus_Success;
378
379 /* check the code is not running from the flash it's going to operate on */
380
381 if ((uint32_t)mflash_drv_init_internal >= MFLASH_BASE_ADDRESS &&
382 (uint32_t)mflash_drv_init_internal < (MFLASH_BASE_ADDRESS + MFLASH_FLASH_SIZE))
383 {
384 return kStatus_ReadOnly;
385 }
386
387 primask = __get_PRIMASK();
388 __asm("cpsid i");
389
390 CLOCK_AttachClk(kMAIN_PLL_PFD1_to_XSPI0);
391 CLOCK_SetClkDiv(kCLOCK_DivXspi0Clk, 1u); /*400MHz*/
392
393 POWER_DisablePD(kPDRUNCFG_APD_XSPI0);
394 POWER_DisablePD(kPDRUNCFG_PPD_XSPI0);
395 POWER_ApplyPD();
396
397 config.ptrAhbAccessConfig = &xspiAhbAccessConfig;
398 config.ptrIpAccessConfig = &xspiIpAccessConfig;
399 /* Get XSPI default settings and configure the xspi. */
400 XSPI_GetDefaultConfig(&config);
401
402 config.byteOrder = kXSPI_64BitLE;
403 config.ptrAhbAccessConfig->ahbErrorPayload.highPayload = 0x5A5A5A5AUL;
404 config.ptrAhbAccessConfig->ahbErrorPayload.lowPayload = 0x5A5A5A5AUL;
405 config.ptrAhbAccessConfig->ptrAhbWriteConfig = NULL; /* This demo does not demonstrate AHB write feature.*/
406 config.ptrAhbAccessConfig->ARDSeqIndex = NOR_CMD_LUT_SEQ_IDX_READ;
407 config.ptrAhbAccessConfig->enableAHBBufferWriteFlush = true;
408 config.ptrAhbAccessConfig->enableAHBPrefetch = true;
409
410 config.ptrIpAccessConfig->ptrSfpFradConfig = NULL; /* This demo does not demonstrate SFP feature.*/
411 config.ptrIpAccessConfig->ptrSfpMdadConfig = NULL;
412 config.ptrIpAccessConfig->ipAccessTimeoutValue = 0xFFFFFFFFUL;
413 config.ptrIpAccessConfig->sfpArbitrationLockTimeoutValue = 0xFFFFFFUL;
414 XSPI_Init(base, &config);
415
416 /* Configure flash settings according to serial flash feature. */
417 XSPI_SetDeviceConfig(base, &deviceconfig);
418
419 /* Update LUT*/
420 XSPI_UpdateLUT(base, 0, customLUT, CUSTOM_LUT_LENGTH);
421
422 if (useOctal)
423 {
424 /* Enter quad mode. */
425 status = xspi_nor_enable_octal_mode(base);
426 }
427
428 if (primask == 0U)
429 {
430 __asm("cpsie i");
431 }
432
433 return status;
434 }
435
436 /* API - initialize 'mflash' */
mflash_drv_init(void)437 int32_t mflash_drv_init(void)
438 {
439 /* Necessary to have double wrapper call in non_xip memory */
440 return mflash_drv_init_internal(XSPI_INSTANCE, USE_OCTAL_MODE);
441 }
442
mflash_drv_read_internal(uint32_t addr,uint32_t * buffer,uint32_t len)443 static int32_t mflash_drv_read_internal(uint32_t addr, uint32_t *buffer, uint32_t len)
444 {
445 uint32_t primask = __get_PRIMASK();
446
447 __asm("cpsid i");
448
449 status_t status;
450 status = xspi_nor_flash_read(XSPI_INSTANCE, addr, buffer, len, USE_OCTAL_MODE);
451
452 if (primask == 0U)
453 {
454 __asm("cpsie i");
455 }
456
457 /* Flush pipeline to allow pending interrupts take place
458 * before starting next loop */
459 __ISB();
460
461 return status;
462 }
463
464 /* API - Read data */
mflash_drv_read(uint32_t addr,uint32_t * buffer,uint32_t len)465 int32_t mflash_drv_read(uint32_t addr, uint32_t *buffer, uint32_t len)
466 {
467 /* Check alignment */
468 if (((uint32_t)buffer % 4) || (len % 4))
469 {
470 return kStatus_InvalidArgument;
471 }
472
473 return mflash_drv_read_internal(addr, buffer, len);
474 }
475
476 /* Internal - erase single sector */
mflash_drv_sector_erase_internal(uint32_t sector_addr)477 static int32_t mflash_drv_sector_erase_internal(uint32_t sector_addr)
478 {
479 status_t status;
480 uint32_t primask = __get_PRIMASK();
481
482 __asm("cpsid i");
483
484 status = xspi_nor_flash_erase_sector(XSPI_INSTANCE, sector_addr, USE_OCTAL_MODE);
485
486 // invalidate_caches();
487 DCACHE_InvalidateByRange(MFLASH_BASE_ADDRESS + sector_addr, MFLASH_SECTOR_SIZE);
488 CACHE64_Invalidate();
489
490 if (primask == 0U)
491 {
492 __asm("cpsie i");
493 }
494
495 /* Flush pipeline to allow pending interrupts take place
496 * before starting next loop */
497 __ISB();
498
499 return status;
500 }
501
502 /* Calling wrapper for 'mflash_drv_sector_erase_internal'.
503 * Erase one sector starting at 'sector_addr' - must be sector aligned.
504 */
mflash_drv_sector_erase(uint32_t sector_addr)505 int32_t mflash_drv_sector_erase(uint32_t sector_addr)
506 {
507 if (0 == mflash_drv_is_sector_aligned(sector_addr))
508 return kStatus_InvalidArgument;
509
510 return mflash_drv_sector_erase_internal(sector_addr);
511 }
512
513 /* Internal - write single page */
mflash_drv_page_program_internal(uint32_t page_addr,uint32_t * data)514 static int32_t mflash_drv_page_program_internal(uint32_t page_addr, uint32_t *data)
515 {
516 uint32_t primask = __get_PRIMASK();
517
518 __asm("cpsid i");
519
520 status_t status;
521 status = xspi_nor_flash_page_program(XSPI_INSTANCE, page_addr, data, USE_OCTAL_MODE);
522
523 DCACHE_InvalidateByRange(MFLASH_BASE_ADDRESS + page_addr, MFLASH_PAGE_SIZE);
524 CACHE64_Invalidate();
525
526 if (primask == 0U)
527 {
528 __asm("cpsie i");
529 }
530
531 /* Flush pipeline to allow pending interrupts take place
532 * before starting next loop */
533 __ISB();
534
535 return status;
536 }
537
538 /* Calling wrapper for 'mflash_drv_page_program_internal'.
539 * Write 'data' to 'page_addr' - must be page aligned.
540 * NOTE: Don't try to store constant data that are located in XIP !!
541 */
mflash_drv_page_program(uint32_t page_addr,uint32_t * data)542 int32_t mflash_drv_page_program(uint32_t page_addr, uint32_t *data)
543 {
544 if (0 == mflash_drv_is_page_aligned(page_addr))
545 return kStatus_InvalidArgument;
546
547 return mflash_drv_page_program_internal(page_addr, data);
548 }
549
550 /* API - Get pointer to FLASH region */
mflash_drv_phys2log(uint32_t addr,uint32_t len)551 void *mflash_drv_phys2log(uint32_t addr, uint32_t len)
552 {
553 /* FLASH starts at MFLASH_BASE_ADDRESS */
554 return (void *)(addr + MFLASH_BASE_ADDRESS);
555 }
556
557 /* API - Get pointer to FLASH region */
mflash_drv_log2phys(void * ptr,uint32_t len)558 uint32_t mflash_drv_log2phys(void *ptr, uint32_t len)
559 {
560 /* FLASH starts at MFLASH_BASE_ADDRESS */
561 return ((uint32_t)ptr - MFLASH_BASE_ADDRESS);
562 }
563