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