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