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