1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2022, 2023 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_flexspi.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.flexspi"
14 #endif
15 
16 /*******************************************************************************
17  * Definitions
18  ******************************************************************************/
19 
20 #define FREQ_1MHz             (1000000UL)
21 #define FLEXSPI_DLLCR_DEFAULT (0x100UL)
22 #define FLEXSPI_LUT_KEY_VAL   (0x5AF05AF0UL)
23 
24 enum
25 {
26     kFLEXSPI_DelayCellUnitMin = 75,  /* 75ps. */
27     kFLEXSPI_DelayCellUnitMax = 225, /* 225ps. */
28 };
29 
30 enum
31 {
32     kFLEXSPI_FlashASampleClockSlaveDelayLocked =
33         FLEXSPI_STS2_ASLVLOCK_MASK, /* Flash A sample clock slave delay line locked. */
34     kFLEXSPI_FlashASampleClockRefDelayLocked =
35         FLEXSPI_STS2_AREFLOCK_MASK, /* Flash A sample clock reference delay line locked. */
36 #if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK)) && (FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK))
37     kFLEXSPI_FlashBSampleClockSlaveDelayLocked =
38         FLEXSPI_STS2_BSLVLOCK_MASK, /* Flash B sample clock slave delay line locked. */
39 #endif
40 #if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BREFLOCK)) && (FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BREFLOCK))
41     kFLEXSPI_FlashBSampleClockRefDelayLocked =
42         FLEXSPI_STS2_BREFLOCK_MASK, /* Flash B sample clock reference delay line locked. */
43 #endif
44 };
45 
46 /*! @brief Common sets of flags used by the driver, _flexspi_flag_constants. */
47 enum
48 {
49     /*! IRQ sources enabled by the non-blocking transactional API. */
50     kIrqFlags = kFLEXSPI_IpTxFifoWatermarkEmptyFlag | kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
51                 kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
52                 kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExecutionDoneFlag,
53 
54     /*! Errors to check for. */
55     kErrorFlags = kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
56                   kFLEXSPI_IpCommandGrantTimeoutFlag,
57 };
58 
59 /* FLEXSPI transfer state, _flexspi_transfer_state. */
60 enum
61 {
62     kFLEXSPI_Idle      = 0x0U, /*!< Transfer is done. */
63     kFLEXSPI_BusyWrite = 0x1U, /*!< FLEXSPI is busy write transfer. */
64     kFLEXSPI_BusyRead  = 0x2U, /*!< FLEXSPI is busy write transfer. */
65 };
66 
67 /*! @brief Typedef for interrupt handler. */
68 typedef void (*flexspi_isr_t)(FLEXSPI_Type *base, flexspi_handle_t *handle);
69 
70 /*******************************************************************************
71  * Prototypes
72  ******************************************************************************/
73 static void FLEXSPI_Memset(void *src, uint8_t value, size_t length);
74 
75 /*!
76  * @brief Calculate flash A/B sample clock DLL.
77  *
78  * @param base FLEXSPI base pointer.
79  * @param config Flash configuration parameters.
80  */
81 static uint32_t FLEXSPI_CalculateDll(FLEXSPI_Type *base, flexspi_device_config_t *config);
82 
83 /*******************************************************************************
84  * Variables
85  ******************************************************************************/
86 /*! @brief Pointers to flexspi bases for each instance. */
87 static FLEXSPI_Type *const s_flexspiBases[] = FLEXSPI_BASE_PTRS;
88 
89 /*! @brief Pointers to flexspi IRQ number for each instance. */
90 static const IRQn_Type s_flexspiIrqs[] = FLEXSPI_IRQS;
91 
92 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
93 /* Clock name array */
94 static const clock_ip_name_t s_flexspiClock[] = FLEXSPI_CLOCKS;
95 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
96 
97 #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
98 /*! @brief Pointers to flexspi handles for each instance. */
99 static flexspi_handle_t *s_flexspiHandle[ARRAY_SIZE(s_flexspiBases)];
100 #endif
101 
102 #if defined(FSL_FEATURE_FLEXSPI_HAS_RESET) && FSL_FEATURE_FLEXSPI_HAS_RESET
103 /*! @brief Pointers to FLEXSPI resets for each instance. */
104 static const reset_ip_name_t s_flexspiResets[] = FLEXSPI_RSTS;
105 #endif
106 
107 #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
108 /*! @brief Pointer to flexspi IRQ handler. */
109 static flexspi_isr_t s_flexspiIsr;
110 #endif
111 /*******************************************************************************
112  * Code
113  ******************************************************************************/
114 /* To avoid compiler opitimizing this API into memset() in library. */
115 #if defined(__ICCARM__)
116 #pragma optimize = none
117 #endif /* defined(__ICCARM__) */
FLEXSPI_Memset(void * src,uint8_t value,size_t length)118 static void FLEXSPI_Memset(void *src, uint8_t value, size_t length)
119 {
120     assert(src != NULL);
121     uint8_t *p = (uint8_t *)src;
122 
123     for (uint32_t i = 0U; i < length; i++)
124     {
125         *p = value;
126         p++;
127     }
128 }
129 
FLEXSPI_GetInstance(FLEXSPI_Type * base)130 uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base)
131 {
132     uint32_t instance;
133 
134     /* Find the instance index from base address mappings. */
135     for (instance = 0; instance < ARRAY_SIZE(s_flexspiBases); instance++)
136     {
137         if (s_flexspiBases[instance] == base)
138         {
139             break;
140         }
141     }
142 
143     assert(instance < ARRAY_SIZE(s_flexspiBases));
144 
145     return instance;
146 }
147 
FLEXSPI_CalculateDll(FLEXSPI_Type * base,flexspi_device_config_t * config)148 static uint32_t FLEXSPI_CalculateDll(FLEXSPI_Type *base, flexspi_device_config_t *config)
149 {
150     bool isUnifiedConfig = true;
151     uint32_t flexspiDllValue;
152     uint32_t dllValue;
153     uint32_t temp;
154 #if defined(FSL_FEATURE_FLEXSPI_DQS_DELAY_PS) && FSL_FEATURE_FLEXSPI_DQS_DELAY_PS
155     uint32_t internalDqsDelayPs = FSL_FEATURE_FLEXSPI_DQS_DELAY_PS;
156 #endif
157     uint32_t rxSampleClock = (base->MCR0 & FLEXSPI_MCR0_RXCLKSRC_MASK) >> FLEXSPI_MCR0_RXCLKSRC_SHIFT;
158     switch (rxSampleClock)
159     {
160         case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackInternally:
161         case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackFromDqsPad:
162         case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackFromSckPad:
163             isUnifiedConfig = true;
164             break;
165         case (uint32_t)kFLEXSPI_ReadSampleClkExternalInputFromDqsPad:
166             if (config->isSck2Enabled)
167             {
168                 isUnifiedConfig = true;
169             }
170             else
171             {
172                 isUnifiedConfig = false;
173             }
174             break;
175         default:
176             assert(false);
177             break;
178     }
179 
180     if (isUnifiedConfig)
181     {
182         flexspiDllValue = FLEXSPI_DLLCR_DEFAULT; /* 1 fixed delay cells in DLL delay chain) */
183     }
184     else
185     {
186         if (config->flexspiRootClk >= 100U * FREQ_1MHz)
187         {
188 #if defined(FSL_FEATURE_FLEXSPI_DQS_DELAY_MIN) && FSL_FEATURE_FLEXSPI_DQS_DELAY_MIN
189             /* DLLEN = 1, SLVDLYTARGET = 0x0, */
190             flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x00);
191 #else
192             /* DLLEN = 1, SLVDLYTARGET = 0xF, */
193             flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x0F);
194 #endif
195 #if (defined(FSL_FEATURE_FLEXSPI_HAS_REFPHASEGAP) && FSL_FEATURE_FLEXSPI_HAS_REFPHASEGAP)
196             flexspiDllValue |= FLEXSPI_DLLCR_REFPHASEGAP(2U);
197 #endif /* FSL_FEATURE_FLEXSPI_HAS_REFPHASEGAP */
198         }
199         else
200         {
201             temp     = (uint32_t)config->dataValidTime * 1000U; /* Convert data valid time in ns to ps. */
202             dllValue = temp / (uint32_t)kFLEXSPI_DelayCellUnitMin;
203             if (dllValue * (uint32_t)kFLEXSPI_DelayCellUnitMin < temp)
204             {
205                 dllValue++;
206             }
207             flexspiDllValue = FLEXSPI_DLLCR_OVRDEN(1) | FLEXSPI_DLLCR_OVRDVAL(dllValue);
208         }
209     }
210     return flexspiDllValue;
211 }
212 
FLEXSPI_CheckAndClearError(FLEXSPI_Type * base,uint32_t status)213 status_t FLEXSPI_CheckAndClearError(FLEXSPI_Type *base, uint32_t status)
214 {
215     status_t result = kStatus_Success;
216 
217     /* Check for error. */
218     status &= (uint32_t)kErrorFlags;
219     if (0U != status)
220     {
221         /* Select the correct error code.. */
222         if (0U != (status & (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag))
223         {
224             result = kStatus_FLEXSPI_SequenceExecutionTimeout;
225         }
226         else if (0U != (status & (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag))
227         {
228             result = kStatus_FLEXSPI_IpCommandSequenceError;
229         }
230         else if (0U != (status & (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag))
231         {
232             result = kStatus_FLEXSPI_IpCommandGrantTimeout;
233         }
234         else
235         {
236             assert(false);
237         }
238 
239         /* Clear the flags. */
240         FLEXSPI_ClearInterruptStatusFlags(base, status);
241     }
242 
243     return result;
244 }
245 
246 /*!
247  * brief Initializes the FLEXSPI module and internal state.
248  *
249  * This function enables the clock for FLEXSPI and also configures the FLEXSPI with the
250  * input configure parameters. Users should call this function before any FLEXSPI operations.
251  *
252  * param base FLEXSPI peripheral base address.
253  * param config FLEXSPI configure structure.
254  */
FLEXSPI_Init(FLEXSPI_Type * base,const flexspi_config_t * config)255 void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config)
256 {
257     uint32_t configValue = 0;
258     uint8_t i            = 0;
259 
260 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
261     /* Enable the flexspi clock */
262     (void)CLOCK_EnableClock(s_flexspiClock[FLEXSPI_GetInstance(base)]);
263 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
264 
265 #if defined(FSL_FEATURE_FLEXSPI_HAS_RESET) && FSL_FEATURE_FLEXSPI_HAS_RESET
266     /* Reset the FLEXSPI module */
267     RESET_PeripheralReset(s_flexspiResets[FLEXSPI_GetInstance(base)]);
268 #endif
269 
270     /* Reset peripheral before configuring it. */
271     base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
272     FLEXSPI_SoftwareReset(base);
273 
274     /* Configure MCR0 configuration items. */
275     configValue = FLEXSPI_MCR0_RXCLKSRC(config->rxSampleClock) | FLEXSPI_MCR0_DOZEEN(config->enableDoze) |
276                   FLEXSPI_MCR0_IPGRANTWAIT(config->ipGrantTimeoutCycle) |
277                   FLEXSPI_MCR0_AHBGRANTWAIT(config->ahbConfig.ahbGrantTimeoutCycle) |
278                   FLEXSPI_MCR0_SCKFREERUNEN(config->enableSckFreeRunning) |
279                   FLEXSPI_MCR0_HSEN(config->enableHalfSpeedAccess) |
280 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN)
281                   FLEXSPI_MCR0_COMBINATIONEN(config->enableCombination) |
282 #endif
283 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN)
284                   FLEXSPI_MCR0_ATDFEN(config->ahbConfig.enableAHBWriteIpTxFifo) |
285 #endif
286 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN)
287                   FLEXSPI_MCR0_ARDFEN(config->ahbConfig.enableAHBWriteIpRxFifo) |
288 #endif
289                   FLEXSPI_MCR0_MDIS_MASK;
290     base->MCR0 = configValue;
291 
292     /* Configure MCR1 configurations. */
293     configValue =
294         FLEXSPI_MCR1_SEQWAIT(config->seqTimeoutCycle) | FLEXSPI_MCR1_AHBBUSWAIT(config->ahbConfig.ahbBusTimeoutCycle);
295     base->MCR1 = configValue;
296 
297     /* Configure MCR2 configurations. */
298     configValue = base->MCR2;
299     configValue &= ~(FLEXSPI_MCR2_RESUMEWAIT_MASK |
300 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT)
301                      FLEXSPI_MCR2_SCKBDIFFOPT_MASK |
302 #endif
303                      FLEXSPI_MCR2_SAMEDEVICEEN_MASK | FLEXSPI_MCR2_CLRAHBBUFOPT_MASK);
304     configValue |= FLEXSPI_MCR2_RESUMEWAIT(config->ahbConfig.resumeWaitCycle) |
305 #if defined(FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB) && FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB
306                    FLEXSPI_MCR2_RXCLKSRC_B(config->rxSampleClockPortB) |
307 #endif
308 #if defined(FSL_FEATURE_FLEXSPI_SUPPORT_RXCLKSRC_DIFF) && FSL_FEATURE_FLEXSPI_SUPPORT_RXCLKSRC_DIFF
309                    FLEXSPI_MCR2_RX_CLK_SRC_DIFF(config->rxSampleClockDiff) |
310 #endif
311 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT)
312                    FLEXSPI_MCR2_SCKBDIFFOPT(config->enableSckBDiffOpt) |
313 #endif
314                    FLEXSPI_MCR2_SAMEDEVICEEN(config->enableSameConfigForAll) |
315                    FLEXSPI_MCR2_CLRAHBBUFOPT(config->ahbConfig.enableClearAHBBufferOpt);
316 
317     base->MCR2 = configValue;
318 
319     /* Configure AHB control items. */
320     configValue = base->AHBCR;
321     configValue &= ~(FLEXSPI_AHBCR_READADDROPT_MASK | FLEXSPI_AHBCR_PREFETCHEN_MASK | FLEXSPI_AHBCR_BUFFERABLEEN_MASK |
322                      FLEXSPI_AHBCR_CACHABLEEN_MASK);
323     configValue |= FLEXSPI_AHBCR_READADDROPT(config->ahbConfig.enableReadAddressOpt) |
324                    FLEXSPI_AHBCR_PREFETCHEN(config->ahbConfig.enableAHBPrefetch) |
325                    FLEXSPI_AHBCR_BUFFERABLEEN(config->ahbConfig.enableAHBBufferable) |
326                    FLEXSPI_AHBCR_CACHABLEEN(config->ahbConfig.enableAHBCachable);
327     base->AHBCR = configValue;
328 
329     /* Configure AHB rx buffers. */
330     for (i = 0; i < (uint32_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++)
331     {
332         configValue = base->AHBRXBUFCR0[i];
333 
334         configValue &= ~(FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK | FLEXSPI_AHBRXBUFCR0_PRIORITY_MASK |
335                          FLEXSPI_AHBRXBUFCR0_MSTRID_MASK | FLEXSPI_AHBRXBUFCR0_BUFSZ_MASK);
336         configValue |= FLEXSPI_AHBRXBUFCR0_PREFETCHEN(config->ahbConfig.buffer[i].enablePrefetch) |
337                        FLEXSPI_AHBRXBUFCR0_PRIORITY(config->ahbConfig.buffer[i].priority) |
338                        FLEXSPI_AHBRXBUFCR0_MSTRID(config->ahbConfig.buffer[i].masterIndex) |
339                        FLEXSPI_AHBRXBUFCR0_BUFSZ((uint32_t)config->ahbConfig.buffer[i].bufferSize / 8U);
340         base->AHBRXBUFCR0[i] = configValue;
341     }
342 
343     /* Configure IP Fifo watermarks. */
344     base->IPRXFCR &= ~FLEXSPI_IPRXFCR_RXWMRK_MASK;
345     base->IPRXFCR |= FLEXSPI_IPRXFCR_RXWMRK((uint32_t)config->rxWatermark / 8U - 1U);
346     base->IPTXFCR &= ~FLEXSPI_IPTXFCR_TXWMRK_MASK;
347     base->IPTXFCR |= FLEXSPI_IPTXFCR_TXWMRK((uint32_t)config->txWatermark / 8U - 1U);
348 
349     /* Reset flash size on all ports */
350     for (i = 0; i < (uint32_t)kFLEXSPI_PortCount; i++)
351     {
352         base->FLSHCR0[i] = 0;
353     }
354 }
355 
356 /*!
357  * brief Gets default settings for FLEXSPI.
358  *
359  * param config FLEXSPI configuration structure.
360  */
FLEXSPI_GetDefaultConfig(flexspi_config_t * config)361 void FLEXSPI_GetDefaultConfig(flexspi_config_t *config)
362 {
363     /* Initializes the configure structure to zero. */
364     FLEXSPI_Memset(config, 0, sizeof(*config));
365 
366     config->rxSampleClock        = kFLEXSPI_ReadSampleClkLoopbackInternally;
367     config->enableSckFreeRunning = false;
368 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN)
369     config->enableCombination = false;
370 #endif
371     config->enableDoze            = true;
372     config->enableHalfSpeedAccess = false;
373 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT)
374     config->enableSckBDiffOpt = false;
375 #endif
376     config->enableSameConfigForAll = false;
377     config->seqTimeoutCycle        = 0xFFFFU;
378     config->ipGrantTimeoutCycle    = 0xFFU;
379     config->txWatermark            = 8;
380     config->rxWatermark            = 8;
381 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN)
382     config->ahbConfig.enableAHBWriteIpTxFifo = false;
383 #endif
384 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN)
385     config->ahbConfig.enableAHBWriteIpRxFifo = false;
386 #endif
387     config->ahbConfig.ahbGrantTimeoutCycle = 0xFFU;
388     config->ahbConfig.ahbBusTimeoutCycle   = 0xFFFFU;
389     config->ahbConfig.resumeWaitCycle      = 0x20U;
390     FLEXSPI_Memset(config->ahbConfig.buffer, 0, sizeof(config->ahbConfig.buffer));
391     /* Use invalid master ID 0xF and buffer size 0 for the first several buffers. */
392     for (uint8_t i = 0; i < ((uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 2U); i++)
393     {
394         config->ahbConfig.buffer[i].enablePrefetch = true; /* Default enable AHB prefetch. */
395         config->ahbConfig.buffer[i].masterIndex = 0xFU; /* Invalid master index which is not used, so will never hit. */
396         config->ahbConfig.buffer[i].bufferSize =
397             0; /* Default buffer size 0 for buffer0 to buffer(FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 3U)*/
398     }
399 
400     for (uint8_t i = ((uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 2U);
401          i < (uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++)
402     {
403         config->ahbConfig.buffer[i].enablePrefetch = true; /* Default enable AHB prefetch. */
404         config->ahbConfig.buffer[i].bufferSize     = 256U; /* Default buffer size 256 bytes. */
405     }
406     config->ahbConfig.enableClearAHBBufferOpt = false;
407     config->ahbConfig.enableReadAddressOpt    = false;
408     config->ahbConfig.enableAHBPrefetch       = false;
409     config->ahbConfig.enableAHBBufferable     = false;
410     config->ahbConfig.enableAHBCachable       = false;
411 }
412 
413 /*!
414  * brief Deinitializes the FLEXSPI module.
415  *
416  * Clears the FLEXSPI state and  FLEXSPI module registers.
417  * param base FLEXSPI peripheral base address.
418  */
FLEXSPI_Deinit(FLEXSPI_Type * base)419 void FLEXSPI_Deinit(FLEXSPI_Type *base)
420 {
421     /* Reset peripheral. */
422     FLEXSPI_SoftwareReset(base);
423 }
424 
425 /*!
426  * brief Update FLEXSPI DLL value depending on currently flexspi root clock.
427  *
428  * param base FLEXSPI peripheral base address.
429  * param config Flash configuration parameters.
430  * param port FLEXSPI Operation port.
431  */
FLEXSPI_UpdateDllValue(FLEXSPI_Type * base,flexspi_device_config_t * config,flexspi_port_t port)432 void FLEXSPI_UpdateDllValue(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
433 {
434     uint32_t configValue = 0;
435     uint32_t statusValue = 0;
436     uint8_t index        = (uint8_t)port >> 1U; /* PortA with index 0, PortB with index 1. */
437 
438     /* Wait for bus to be idle before changing flash configuration. */
439     while (!FLEXSPI_GetBusIdleStatus(base))
440     {
441     }
442 
443     /* Configure DLL. */
444     configValue        = FLEXSPI_CalculateDll(base, config);
445     base->DLLCR[index] = configValue;
446 
447     /* Exit stop mode. */
448     base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
449 
450     /* According to ERR011377, need to delay at least 100 NOPs to ensure the DLL is locked. */
451     if (index == 0U)
452     {
453         statusValue =
454             ((uint32_t)kFLEXSPI_FlashASampleClockSlaveDelayLocked | (uint32_t)kFLEXSPI_FlashASampleClockRefDelayLocked);
455     }
456 #if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK)) && (FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK))
457     else
458     {
459         statusValue =
460             ((uint32_t)kFLEXSPI_FlashBSampleClockSlaveDelayLocked | (uint32_t)kFLEXSPI_FlashBSampleClockRefDelayLocked);
461     }
462 #endif
463     if (0U != (configValue & FLEXSPI_DLLCR_DLLEN_MASK))
464     {
465 #if defined(FSL_FEATURE_FLEXSPI_HAS_ERRATA_051426) && (FSL_FEATURE_FLEXSPI_HAS_ERRATA_051426)
466         if (config->isFroClockSource == false)
467 #endif
468         {
469             /* Wait slave delay line locked and slave reference delay line locked. */
470             while ((base->STS2 & statusValue) != statusValue)
471             {
472             }
473         }
474 
475         /* Wait at least 100 NOPs*/
476         for (uint8_t delay = 100U; delay > 0U; delay--)
477         {
478             __NOP();
479         }
480     }
481 }
482 
483 /*!
484  * brief Configures the connected device parameter.
485  *
486  * This function configures the connected device relevant parameters, such as the size, command, and so on.
487  * The flash configuration value cannot have a default value. The user needs to configure it according to the
488  * connected device.
489  *
490  * param base FLEXSPI peripheral base address.
491  * param config Flash configuration parameters.
492  * param port FLEXSPI Operation port.
493  */
FLEXSPI_SetFlashConfig(FLEXSPI_Type * base,flexspi_device_config_t * config,flexspi_port_t port)494 void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
495 {
496     uint32_t configValue = 0;
497     uint8_t index        = (uint8_t)port >> 1U; /* PortA with index 0, PortB with index 1. */
498 
499     /* Wait for bus to be idle before changing flash configuration. */
500     while (!FLEXSPI_GetBusIdleStatus(base))
501     {
502     }
503 
504     /* Configure flash size and address shift. */
505 #if defined(FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT) && (FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT)
506     base->FLSHCR0[port] = config->flashSize | FLEXSPI_FLSHCR0_ADDRSHIFT(config->addressShift);
507 #else
508     base->FLSHCR0[port] = config->flashSize;
509 #endif /* FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT */
510 
511     /* Configure flash parameters. */
512     base->FLSHCR1[port] = FLEXSPI_FLSHCR1_CSINTERVAL(config->CSInterval) |
513                           FLEXSPI_FLSHCR1_CSINTERVALUNIT(config->CSIntervalUnit) |
514                           FLEXSPI_FLSHCR1_TCSH(config->CSHoldTime) | FLEXSPI_FLSHCR1_TCSS(config->CSSetupTime) |
515                           FLEXSPI_FLSHCR1_CAS(config->columnspace) | FLEXSPI_FLSHCR1_WA(config->enableWordAddress);
516 
517     /* Configure AHB operation items. */
518     configValue = base->FLSHCR2[port];
519 
520     configValue &= ~(FLEXSPI_FLSHCR2_AWRWAITUNIT_MASK | FLEXSPI_FLSHCR2_AWRWAIT_MASK | FLEXSPI_FLSHCR2_AWRSEQNUM_MASK |
521                      FLEXSPI_FLSHCR2_AWRSEQID_MASK | FLEXSPI_FLSHCR2_ARDSEQNUM_MASK | FLEXSPI_FLSHCR2_ARDSEQID_MASK);
522 
523     configValue |=
524         FLEXSPI_FLSHCR2_AWRWAITUNIT(config->AHBWriteWaitUnit) | FLEXSPI_FLSHCR2_AWRWAIT(config->AHBWriteWaitInterval);
525 
526     if (config->AWRSeqNumber > 0U)
527     {
528         configValue |= FLEXSPI_FLSHCR2_AWRSEQID((uint32_t)config->AWRSeqIndex) |
529                        FLEXSPI_FLSHCR2_AWRSEQNUM((uint32_t)config->AWRSeqNumber - 1U);
530     }
531 
532     if (config->ARDSeqNumber > 0U)
533     {
534         configValue |= FLEXSPI_FLSHCR2_ARDSEQID((uint32_t)config->ARDSeqIndex) |
535                        FLEXSPI_FLSHCR2_ARDSEQNUM((uint32_t)config->ARDSeqNumber - 1U);
536     }
537 
538     base->FLSHCR2[port] = configValue;
539 
540     /* Configure DLL. */
541     FLEXSPI_UpdateDllValue(base, config, port);
542 
543     /* Step into stop mode. */
544     base->MCR0 |= FLEXSPI_MCR0_MDIS_MASK;
545 
546     /* Configure write mask. */
547     if (config->enableWriteMask)
548     {
549         base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMOPT1_MASK;
550     }
551     else
552     {
553         base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMOPT1_MASK;
554     }
555 
556     if (index == 0U) /*PortA*/
557     {
558         base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENA_MASK;
559         base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENA(config->enableWriteMask);
560     }
561 #if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_FLSHCR4_WMENB)) && (FSL_FEATURE_FLEXSPI_HAS_NO_FLSHCR4_WMENB))
562     else
563     {
564         base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENB_MASK;
565         base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENB(config->enableWriteMask);
566     }
567 #endif
568 
569     /* Exit stop mode. */
570     base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
571 
572     /* Wait for bus to be idle before use it access to external flash. */
573     while (!FLEXSPI_GetBusIdleStatus(base))
574     {
575     }
576 }
577 
578 /*! brief Updates the LUT table.
579  *
580  * param base FLEXSPI peripheral base address.
581  * param index From which index start to update. It could be any index of the LUT table, which
582  * also allows user to update command content inside a command. Each command consists of up to
583  * 8 instructions and occupy 4*32-bit memory.
584  * param cmd Command sequence array.
585  * param count Number of sequences.
586  */
FLEXSPI_UpdateLUT(FLEXSPI_Type * base,uint32_t index,const uint32_t * cmd,uint32_t count)587 void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count)
588 {
589     assert(index < 64U);
590 
591     uint32_t i = 0;
592     volatile uint32_t *lutBase;
593 
594     /* Wait for bus to be idle before changing flash configuration. */
595     while (!FLEXSPI_GetBusIdleStatus(base))
596     {
597     }
598 
599     /* Unlock LUT for update. */
600 #if !((defined(FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO)) && (FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO))
601     base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
602 #endif
603     base->LUTCR = 0x02;
604 
605     lutBase = &base->LUT[index];
606     for (i = 0; i < count; i++)
607     {
608         *lutBase++ = *cmd++;
609     }
610 
611     /* Lock LUT. */
612 #if !((defined(FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO)) && (FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO))
613     base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
614 #endif
615     base->LUTCR = 0x01;
616 }
617 
618 /*! brief Update read sample clock source
619  *
620  * param base FLEXSPI peripheral base address.
621  * param clockSource clockSource of type #flexspi_read_sample_clock_t
622  */
FLEXSPI_UpdateRxSampleClock(FLEXSPI_Type * base,flexspi_read_sample_clock_t clockSource)623 void FLEXSPI_UpdateRxSampleClock(FLEXSPI_Type *base, flexspi_read_sample_clock_t clockSource)
624 {
625     uint32_t mcr0Val;
626 
627     /* Wait for bus to be idle before changing flash configuration. */
628     while (!FLEXSPI_GetBusIdleStatus(base))
629     {
630     }
631 
632     mcr0Val = base->MCR0;
633     mcr0Val &= ~FLEXSPI_MCR0_RXCLKSRC_MASK;
634     mcr0Val |= FLEXSPI_MCR0_RXCLKSRC(clockSource);
635     base->MCR0 = mcr0Val;
636 
637     /* Reset peripheral. */
638     FLEXSPI_SoftwareReset(base);
639 }
640 
641 /*!
642  * brief Sends a buffer of data bytes using blocking method.
643  * note This function blocks via polling until all bytes have been sent.
644  * param base FLEXSPI peripheral base address
645  * param buffer The data bytes to send
646  * param size The number of data bytes to send
647  * retval kStatus_Success write success without error
648  * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
649  * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
650  * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
651  */
FLEXSPI_WriteBlocking(FLEXSPI_Type * base,uint8_t * buffer,size_t size)652 status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size)
653 {
654     uint32_t txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1U;
655     uint32_t status;
656     status_t result = kStatus_Success;
657     uint32_t i      = 0;
658 
659     /* Send data buffer */
660     while (0U != size)
661     {
662         /* Wait until there is room in the fifo. This also checks for errors. */
663         while (0U == ((status = base->INTR) & (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag))
664         {
665         }
666 
667         result = FLEXSPI_CheckAndClearError(base, status);
668 
669         if (kStatus_Success != result)
670         {
671             return result;
672         }
673 
674         /* Write watermark level data into tx fifo . */
675         if (size >= 8U * txWatermark)
676         {
677             for (i = 0U; i < 2U * txWatermark; i++)
678             {
679                 base->TFDR[i] = *(uint32_t *)(void *)buffer;
680                 buffer += 4U;
681             }
682 
683             size = size - 8U * txWatermark;
684         }
685         else
686         {
687             /* Write word aligned data into tx fifo. */
688             for (i = 0U; i < (size / 4U); i++)
689             {
690                 base->TFDR[i] = *(uint32_t *)(void *)buffer;
691                 buffer += 4U;
692             }
693 
694             /* Adjust size by the amount processed. */
695             size -= 4U * i;
696 
697             /* Write word un-aligned data into tx fifo. */
698             if (0x00U != size)
699             {
700                 uint32_t tempVal = 0x00U;
701 
702                 for (uint32_t j = 0U; j < size; j++)
703                 {
704                     tempVal |= ((uint32_t)*buffer++ << (8U * j));
705                 }
706 
707                 base->TFDR[i] = tempVal;
708             }
709 
710             size = 0U;
711         }
712 
713         /* Push a watermark level data into IP TX FIFO. */
714         base->INTR = (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag;
715     }
716 
717     return result;
718 }
719 
720 /*!
721  * brief Receives a buffer of data bytes using a blocking method.
722  * note This function blocks via polling until all bytes have been sent.
723  * param base FLEXSPI peripheral base address
724  * param buffer The data bytes to send
725  * param size The number of data bytes to receive
726  * retval kStatus_Success read success without error
727  * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
728  * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
729  * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
730  */
FLEXSPI_ReadBlocking(FLEXSPI_Type * base,uint8_t * buffer,size_t size)731 status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size)
732 {
733     uint32_t rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1U;
734     uint32_t status;
735     status_t result = kStatus_Success;
736     uint32_t i      = 0;
737     bool isReturn   = false;
738 
739     /* Send data buffer */
740     while (0U != size)
741     {
742         if (size >= 8U * rxWatermark)
743         {
744             /* Wait until there is room in the fifo. This also checks for errors. */
745             while (0U == ((status = base->INTR) & (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag))
746             {
747                 result = FLEXSPI_CheckAndClearError(base, status);
748 
749                 if (kStatus_Success != result)
750                 {
751                     isReturn = true;
752                     break;
753                 }
754             }
755         }
756         else
757         {
758             /* Wait fill level. This also checks for errors. */
759             while (size > ((((base->IPRXFSTS) & FLEXSPI_IPRXFSTS_FILL_MASK) >> FLEXSPI_IPRXFSTS_FILL_SHIFT) * 8U))
760             {
761                 result = FLEXSPI_CheckAndClearError(base, base->INTR);
762 
763                 if (kStatus_Success != result)
764                 {
765                     isReturn = true;
766                     break;
767                 }
768             }
769         }
770 
771         if (isReturn)
772         {
773             break;
774         }
775 
776         result = FLEXSPI_CheckAndClearError(base, base->INTR);
777 
778         if (kStatus_Success != result)
779         {
780             break;
781         }
782 
783         /* Read watermark level data from rx fifo. */
784         if (size >= 8U * rxWatermark)
785         {
786             for (i = 0U; i < 2U * rxWatermark; i++)
787             {
788                 *(uint32_t *)(void *)buffer = base->RFDR[i];
789                 buffer += 4U;
790             }
791 
792             size = size - 8U * rxWatermark;
793         }
794         else
795         {
796             /* Read word aligned data from rx fifo. */
797             for (i = 0U; i < (size / 4U); i++)
798             {
799                 *(uint32_t *)(void *)buffer = base->RFDR[i];
800                 buffer += 4U;
801             }
802 
803             /* Adjust size by the amount processed. */
804             size -= 4U * i;
805 
806             /* Read word un-aligned data from rx fifo. */
807             if (0x00U != size)
808             {
809                 uint32_t tempVal = base->RFDR[i];
810 
811                 for (i = 0U; i < size; i++)
812                 {
813                     *buffer++ = ((uint8_t)(tempVal >> (8U * i)) & 0xFFU);
814                 }
815             }
816 
817             size = 0;
818         }
819 
820         /* Pop out a watermark level datas from IP RX FIFO. */
821         base->INTR = (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
822     }
823 
824     return result;
825 }
826 
827 /*!
828  * brief Execute command to transfer a buffer data bytes using a blocking method.
829  * param base FLEXSPI peripheral base address
830  * param xfer pointer to the transfer structure.
831  * retval kStatus_Success command transfer success without error
832  * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
833  * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
834  * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
835  */
FLEXSPI_TransferBlocking(FLEXSPI_Type * base,flexspi_transfer_t * xfer)836 status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer)
837 {
838     uint32_t configValue = 0;
839     status_t result      = kStatus_Success;
840 
841     /* Clear sequence pointer before sending data to external devices. */
842     base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
843 
844     /* Clear former pending status before start this transfer. */
845     base->INTR = FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
846                  FLEXSPI_INTR_IPCMDGE_MASK | FLEXSPI_INTR_IPCMDDONE_MASK;
847 
848     /* Configure base address. */
849     base->IPCR0 = xfer->deviceAddress;
850 
851     /* Reset fifos. */
852     base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
853     base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
854 
855     /* Configure data size. */
856     if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
857     {
858         configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
859     }
860 
861     /* Configure sequence ID. */
862     configValue |=
863         FLEXSPI_IPCR1_ISEQID((uint32_t)xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->SeqNumber - 1U);
864     base->IPCR1 = configValue;
865 
866     /* Start Transfer. */
867     base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
868 
869     if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
870     {
871         result = FLEXSPI_WriteBlocking(base, (uint8_t *)xfer->data, xfer->dataSize);
872     }
873     else if (xfer->cmdType == kFLEXSPI_Read)
874     {
875         result = FLEXSPI_ReadBlocking(base, (uint8_t *)xfer->data, xfer->dataSize);
876     }
877     else
878     {
879         /* Empty else. */
880     }
881 
882     /* Wait until the IP command execution finishes */
883     while (0UL == (base->INTR & FLEXSPI_INTR_IPCMDDONE_MASK))
884     {
885     }
886 
887     /* Unless there is an error status already set, capture the latest one */
888     if (result == kStatus_Success)
889     {
890         result = FLEXSPI_CheckAndClearError(base, base->INTR);
891     }
892 
893     return result;
894 }
895 
896 /*!
897  * brief Initializes the FLEXSPI handle which is used in transactional functions.
898  *
899  * param base FLEXSPI peripheral base address.
900  * param handle pointer to flexspi_handle_t structure to store the transfer state.
901  * param callback pointer to user callback function.
902  * param userData user parameter passed to the callback function.
903  */
FLEXSPI_TransferCreateHandle(FLEXSPI_Type * base,flexspi_handle_t * handle,flexspi_transfer_callback_t callback,void * userData)904 void FLEXSPI_TransferCreateHandle(FLEXSPI_Type *base,
905                                   flexspi_handle_t *handle,
906                                   flexspi_transfer_callback_t callback,
907                                   void *userData)
908 {
909     assert(NULL != handle);
910 
911     uint32_t instance = FLEXSPI_GetInstance(base);
912 
913     /* Zero handle. */
914     (void)memset(handle, 0, sizeof(*handle));
915 
916     /* Set callback and userData. */
917     handle->completionCallback = callback;
918     handle->userData           = userData;
919 
920 #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
921     /* Save the context in global variables to support the double weak mechanism. */
922     s_flexspiHandle[instance] = handle;
923     s_flexspiIsr              = FLEXSPI_TransferHandleIRQ;
924 #endif
925 
926     /* Enable NVIC interrupt. */
927     (void)EnableIRQ(s_flexspiIrqs[instance]);
928 }
929 
930 /*!
931  * brief Performs a interrupt non-blocking transfer on the FLEXSPI bus.
932  *
933  * note Calling the API returns immediately after transfer initiates. The user needs
934  * to call FLEXSPI_GetTransferCount to poll the transfer status to check whether
935  * the transfer is finished. If the return status is not kStatus_FLEXSPI_Busy, the transfer
936  * is finished. For FLEXSPI_Read, the dataSize should be multiple of rx watermark level, or
937  * FLEXSPI could not read data properly.
938  *
939  * param base FLEXSPI peripheral base address.
940  * param handle pointer to flexspi_handle_t structure which stores the transfer state.
941  * param xfer pointer to flexspi_transfer_t structure.
942  * retval kStatus_Success Successfully start the data transmission.
943  * retval kStatus_FLEXSPI_Busy Previous transmission still not finished.
944  */
FLEXSPI_TransferNonBlocking(FLEXSPI_Type * base,flexspi_handle_t * handle,flexspi_transfer_t * xfer)945 status_t FLEXSPI_TransferNonBlocking(FLEXSPI_Type *base, flexspi_handle_t *handle, flexspi_transfer_t *xfer)
946 {
947     uint32_t configValue = 0;
948     status_t result      = kStatus_Success;
949 
950     assert(NULL != handle);
951     assert(NULL != xfer);
952 
953     /* Check if the I2C bus is idle - if not return busy status. */
954     if (handle->state != (uint32_t)kFLEXSPI_Idle)
955     {
956         result = kStatus_FLEXSPI_Busy;
957     }
958     else
959     {
960         handle->data              = (uint8_t *)xfer->data;
961         handle->dataSize          = xfer->dataSize;
962         handle->transferTotalSize = xfer->dataSize;
963         handle->state = (xfer->cmdType == kFLEXSPI_Read) ? (uint32_t)kFLEXSPI_BusyRead : (uint32_t)kFLEXSPI_BusyWrite;
964 
965         /* Clear sequence pointer before sending data to external devices. */
966         base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
967 
968         /* Clear former pending status before start this transfer. */
969         base->INTR = FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
970                      FLEXSPI_INTR_IPCMDGE_MASK | FLEXSPI_INTR_IPCMDDONE_MASK;
971 
972         /* Configure base address. */
973         base->IPCR0 = xfer->deviceAddress;
974 
975         /* Reset fifos. */
976         base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
977         base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
978 
979         /* Configure data size. */
980         if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write))
981         {
982             configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
983         }
984 
985         /* Configure sequence ID. */
986         configValue |=
987             FLEXSPI_IPCR1_ISEQID((uint32_t)xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->SeqNumber - 1U);
988         base->IPCR1 = configValue;
989 
990         /* Start Transfer. */
991         base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
992 
993         if (handle->state == (uint32_t)kFLEXSPI_BusyRead)
994         {
995             FLEXSPI_EnableInterrupts(base, (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
996                                                (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag |
997                                                (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag |
998                                                (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag |
999                                                (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag);
1000         }
1001         else
1002         {
1003             FLEXSPI_EnableInterrupts(
1004                 base, (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag | (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag |
1005                           (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag | (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag |
1006                           (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag);
1007         }
1008     }
1009 
1010     return result;
1011 }
1012 
1013 /*!
1014  * brief Gets the master transfer status during a interrupt non-blocking transfer.
1015  *
1016  * param base FLEXSPI peripheral base address.
1017  * param handle pointer to flexspi_handle_t structure which stores the transfer state.
1018  * param count Number of bytes transferred so far by the non-blocking transaction.
1019  * retval kStatus_InvalidArgument count is Invalid.
1020  * retval kStatus_Success Successfully return the count.
1021  */
FLEXSPI_TransferGetCount(FLEXSPI_Type * base,flexspi_handle_t * handle,size_t * count)1022 status_t FLEXSPI_TransferGetCount(FLEXSPI_Type *base, flexspi_handle_t *handle, size_t *count)
1023 {
1024     assert(NULL != handle);
1025 
1026     status_t result = kStatus_Success;
1027 
1028     if (handle->state == (uint32_t)kFLEXSPI_Idle)
1029     {
1030         result = kStatus_NoTransferInProgress;
1031     }
1032     else
1033     {
1034         *count = handle->transferTotalSize - handle->dataSize;
1035     }
1036 
1037     return result;
1038 }
1039 
1040 /*!
1041  * brief Aborts an interrupt non-blocking transfer early.
1042  *
1043  * note This API can be called at any time when an interrupt non-blocking transfer initiates
1044  * to abort the transfer early.
1045  *
1046  * param base FLEXSPI peripheral base address.
1047  * param handle pointer to flexspi_handle_t structure which stores the transfer state
1048  */
FLEXSPI_TransferAbort(FLEXSPI_Type * base,flexspi_handle_t * handle)1049 void FLEXSPI_TransferAbort(FLEXSPI_Type *base, flexspi_handle_t *handle)
1050 {
1051     assert(NULL != handle);
1052 
1053     FLEXSPI_DisableInterrupts(base, (uint32_t)kIrqFlags);
1054     handle->state = (uint32_t)kFLEXSPI_Idle;
1055 }
1056 
1057 /*!
1058  * brief Master interrupt handler.
1059  *
1060  * param base FLEXSPI peripheral base address.
1061  * param handle pointer to flexspi_handle_t structure.
1062  */
FLEXSPI_TransferHandleIRQ(FLEXSPI_Type * base,flexspi_handle_t * handle)1063 void FLEXSPI_TransferHandleIRQ(FLEXSPI_Type *base, flexspi_handle_t *handle)
1064 {
1065     uint32_t status;
1066     status_t result;
1067     uint32_t intEnableStatus;
1068     uint32_t txWatermark;
1069     uint32_t rxWatermark;
1070     uint32_t i = 0;
1071 
1072     status          = base->INTR;
1073     intEnableStatus = base->INTEN;
1074 
1075     /* Check if interrupt is enabled and status is alerted. */
1076     if ((status & intEnableStatus) != 0U)
1077     {
1078         result = FLEXSPI_CheckAndClearError(base, status);
1079 
1080         if ((result != kStatus_Success) && (handle->completionCallback != NULL))
1081         {
1082             FLEXSPI_TransferAbort(base, handle);
1083             if (NULL != handle->completionCallback)
1084             {
1085                 handle->completionCallback(base, handle, result, handle->userData);
1086             }
1087         }
1088         else
1089         {
1090             if ((0U != (status & (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag)) &&
1091                 (handle->state == (uint32_t)kFLEXSPI_BusyRead))
1092             {
1093                 rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1U;
1094 
1095                 /* Read watermark level data from rx fifo . */
1096                 if (handle->dataSize >= 8U * rxWatermark)
1097                 {
1098                     /* Read watermark level data from rx fifo . */
1099                     for (i = 0U; i < 2U * rxWatermark; i++)
1100                     {
1101                         *(uint32_t *)(void *)handle->data = base->RFDR[i];
1102                         handle->data += 4U;
1103                     }
1104 
1105                     handle->dataSize = handle->dataSize - 8U * rxWatermark;
1106                 }
1107                 else
1108                 {
1109                     /* Read word aligned data from rx fifo. */
1110                     for (i = 0U; i < (handle->dataSize / 4U); i++)
1111                     {
1112                         *(uint32_t *)(void *)handle->data = base->RFDR[i];
1113                         handle->data += 4U;
1114                     }
1115 
1116                     /* Adjust size by the amount processed. */
1117                     handle->dataSize -= (size_t)4U * i;
1118 
1119                     /* Read word un-aligned data from rx fifo. */
1120                     if (0x00U != handle->dataSize)
1121                     {
1122                         uint32_t tempVal = base->RFDR[i];
1123 
1124                         for (i = 0U; i < handle->dataSize; i++)
1125                         {
1126                             *handle->data++ = ((uint8_t)(tempVal >> (8U * i)) & 0xFFU);
1127                         }
1128                     }
1129 
1130                     handle->dataSize = 0;
1131                 }
1132                 /* Pop out a watermark level data from IP RX FIFO. */
1133                 base->INTR = (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
1134             }
1135 
1136             if (0U != (status & (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag))
1137             {
1138                 base->INTR = (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag;
1139 
1140                 FLEXSPI_TransferAbort(base, handle);
1141 
1142                 if (NULL != handle->completionCallback)
1143                 {
1144                     handle->completionCallback(base, handle, kStatus_Success, handle->userData);
1145                 }
1146             }
1147 
1148             /* TX FIFO empty interrupt, push watermark level data into tx FIFO. */
1149             if ((0U != (status & (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag)) &&
1150                 (handle->state == (uint32_t)kFLEXSPI_BusyWrite))
1151             {
1152                 if (0U != handle->dataSize)
1153                 {
1154                     txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1U;
1155                     /* Write watermark level data into tx fifo . */
1156                     if (handle->dataSize >= 8U * txWatermark)
1157                     {
1158                         for (i = 0; i < 2U * txWatermark; i++)
1159                         {
1160                             base->TFDR[i] = *(uint32_t *)(void *)handle->data;
1161                             handle->data += 4U;
1162                         }
1163 
1164                         handle->dataSize = handle->dataSize - 8U * txWatermark;
1165                     }
1166                     else
1167                     {
1168                         /* Write word aligned data into tx fifo. */
1169                         for (i = 0U; i < (handle->dataSize / 4U); i++)
1170                         {
1171                             base->TFDR[i] = *(uint32_t *)(void *)handle->data;
1172                             handle->data += 4U;
1173                         }
1174 
1175                         /* Adjust size by the amount processed. */
1176                         handle->dataSize -= (size_t)4U * i;
1177 
1178                         /* Write word un-aligned data into tx fifo. */
1179                         if (0x00U != handle->dataSize)
1180                         {
1181                             uint32_t tempVal = 0x00U;
1182 
1183                             for (uint32_t j = 0U; j < handle->dataSize; j++)
1184                             {
1185                                 tempVal |= ((uint32_t)*handle->data++ << (8U * j));
1186                             }
1187 
1188                             base->TFDR[i] = tempVal;
1189                         }
1190 
1191                         handle->dataSize = 0;
1192                     }
1193 
1194                     /* Push a watermark level data into IP TX FIFO. */
1195                     base->INTR = (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag;
1196                 }
1197             }
1198             else
1199             {
1200                 /* Empty else */
1201             }
1202         }
1203     }
1204     else
1205     {
1206         /* Empty else */
1207     }
1208 }
1209 
1210 #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
1211 #if defined(FLEXSPI)
1212 void FLEXSPI_DriverIRQHandler(void);
FLEXSPI_DriverIRQHandler(void)1213 void FLEXSPI_DriverIRQHandler(void)
1214 {
1215     s_flexspiIsr(FLEXSPI, s_flexspiHandle[0]);
1216     SDK_ISR_EXIT_BARRIER;
1217 }
1218 #endif
1219 
1220 #if defined(FLEXSPI0)
1221 void FLEXSPI0_DriverIRQHandler(void);
FLEXSPI0_DriverIRQHandler(void)1222 void FLEXSPI0_DriverIRQHandler(void)
1223 {
1224     s_flexspiIsr(FLEXSPI0, s_flexspiHandle[0]);
1225     SDK_ISR_EXIT_BARRIER;
1226 }
1227 #endif
1228 #if defined(FLEXSPI1)
1229 void FLEXSPI1_DriverIRQHandler(void);
FLEXSPI1_DriverIRQHandler(void)1230 void FLEXSPI1_DriverIRQHandler(void)
1231 {
1232     s_flexspiIsr(FLEXSPI1, s_flexspiHandle[1]);
1233     SDK_ISR_EXIT_BARRIER;
1234 }
1235 #endif
1236 #if defined(FLEXSPI2)
1237 void FLEXSPI2_DriverIRQHandler(void);
FLEXSPI2_DriverIRQHandler(void)1238 void FLEXSPI2_DriverIRQHandler(void)
1239 {
1240     s_flexspiIsr(FLEXSPI2, s_flexspiHandle[2]);
1241     SDK_ISR_EXIT_BARRIER;
1242 }
1243 #endif
1244 
1245 #if defined(LSIO__FLEXSPI0)
1246 void LSIO_OCTASPI0_INT_DriverIRQHandler(void);
LSIO_OCTASPI0_INT_DriverIRQHandler(void)1247 void LSIO_OCTASPI0_INT_DriverIRQHandler(void)
1248 {
1249     s_flexspiIsr(LSIO__FLEXSPI0, s_flexspiHandle[0]);
1250     SDK_ISR_EXIT_BARRIER;
1251 }
1252 #endif
1253 #if defined(LSIO__FLEXSPI1)
1254 void LSIO_OCTASPI1_INT_DriverIRQHandler(void);
LSIO_OCTASPI1_INT_DriverIRQHandler(void)1255 void LSIO_OCTASPI1_INT_DriverIRQHandler(void)
1256 {
1257     s_flexspiIsr(LSIO__FLEXSPI1, s_flexspiHandle[1]);
1258     SDK_ISR_EXIT_BARRIER;
1259 }
1260 #endif
1261 
1262 #if defined(FSL_FEATURE_FLEXSPI_HAS_SHARED_IRQ0_IRQ1) && FSL_FEATURE_FLEXSPI_HAS_SHARED_IRQ0_IRQ1
1263 
1264 void FLEXSPI0_FLEXSPI1_DriverIRQHandler(void);
FLEXSPI0_FLEXSPI1_DriverIRQHandler(void)1265 void FLEXSPI0_FLEXSPI1_DriverIRQHandler(void)
1266 {
1267     /* If handle is registered, treat the transfer function is enabled. */
1268     if (NULL != s_flexspiHandle[0])
1269     {
1270         s_flexspiIsr(FLEXSPI0, s_flexspiHandle[0]);
1271     }
1272     if (NULL != s_flexspiHandle[1])
1273     {
1274         s_flexspiIsr(FLEXSPI1, s_flexspiHandle[1]);
1275     }
1276 }
1277 #endif
1278 
1279 #endif
1280