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