Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:59

0001 /*
0002  * Copyright (c) 2016, Freescale Semiconductor, Inc.
0003  * Copyright 2016-2022 NXP
0004  * All rights reserved.
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_flexspi.h"
0010 
0011 /* Component ID definition, used by tools. */
0012 #ifndef FSL_COMPONENT_ID
0013 #define FSL_COMPONENT_ID "platform.drivers.flexspi"
0014 #endif
0015 
0016 /*******************************************************************************
0017  * Definitions
0018  ******************************************************************************/
0019 
0020 #define FREQ_1MHz             (1000000UL)
0021 #define FLEXSPI_DLLCR_DEFAULT (0x100UL)
0022 #define FLEXSPI_LUT_KEY_VAL   (0x5AF05AF0UL)
0023 
0024 enum
0025 {
0026     kFLEXSPI_DelayCellUnitMin = 75,  /* 75ps. */
0027     kFLEXSPI_DelayCellUnitMax = 225, /* 225ps. */
0028 };
0029 
0030 enum
0031 {
0032     kFLEXSPI_FlashASampleClockSlaveDelayLocked =
0033         FLEXSPI_STS2_ASLVLOCK_MASK, /* Flash A sample clock slave delay line locked. */
0034     kFLEXSPI_FlashASampleClockRefDelayLocked =
0035         FLEXSPI_STS2_AREFLOCK_MASK, /* Flash A sample clock reference delay line locked. */
0036 #if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK)) && (FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK))
0037     kFLEXSPI_FlashBSampleClockSlaveDelayLocked =
0038         FLEXSPI_STS2_BSLVLOCK_MASK, /* Flash B sample clock slave delay line locked. */
0039 #endif
0040 #if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BREFLOCK)) && (FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BREFLOCK))
0041     kFLEXSPI_FlashBSampleClockRefDelayLocked =
0042         FLEXSPI_STS2_BREFLOCK_MASK, /* Flash B sample clock reference delay line locked. */
0043 #endif
0044 };
0045 
0046 /*! @brief Common sets of flags used by the driver, _flexspi_flag_constants. */
0047 enum
0048 {
0049     /*! IRQ sources enabled by the non-blocking transactional API. */
0050     kIrqFlags = kFLEXSPI_IpTxFifoWatermarkEmptyFlag | kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
0051                 kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
0052                 kFLEXSPI_IpCommandGrantTimeoutFlag | kFLEXSPI_IpCommandExecutionDoneFlag,
0053 
0054     /*! Errors to check for. */
0055     kErrorFlags = kFLEXSPI_SequenceExecutionTimeoutFlag | kFLEXSPI_IpCommandSequenceErrorFlag |
0056                   kFLEXSPI_IpCommandGrantTimeoutFlag,
0057 };
0058 
0059 /* FLEXSPI transfer state, _flexspi_transfer_state. */
0060 enum
0061 {
0062     kFLEXSPI_Idle      = 0x0U, /*!< Transfer is done. */
0063     kFLEXSPI_BusyWrite = 0x1U, /*!< FLEXSPI is busy write transfer. */
0064     kFLEXSPI_BusyRead  = 0x2U, /*!< FLEXSPI is busy write transfer. */
0065 };
0066 
0067 /*! @brief Typedef for interrupt handler. */
0068 typedef void (*flexspi_isr_t)(FLEXSPI_Type *base, flexspi_handle_t *handle);
0069 
0070 /*******************************************************************************
0071  * Prototypes
0072  ******************************************************************************/
0073 static void FLEXSPI_Memset(void *src, uint8_t value, size_t length);
0074 
0075 /*!
0076  * @brief Calculate flash A/B sample clock DLL.
0077  *
0078  * @param base FLEXSPI base pointer.
0079  * @param config Flash configuration parameters.
0080  */
0081 static uint32_t FLEXSPI_CalculateDll(FLEXSPI_Type *base, flexspi_device_config_t *config);
0082 
0083 /*******************************************************************************
0084  * Variables
0085  ******************************************************************************/
0086 /*! @brief Pointers to flexspi bases for each instance. */
0087 static FLEXSPI_Type *const s_flexspiBases[] = FLEXSPI_BASE_PTRS;
0088 
0089 /*! @brief Pointers to flexspi IRQ number for each instance. */
0090 static const IRQn_Type s_flexspiIrqs[] = FLEXSPI_IRQS;
0091 
0092 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0093 /* Clock name array */
0094 static const clock_ip_name_t s_flexspiClock[] = FLEXSPI_CLOCKS;
0095 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0096 
0097 #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
0098 /*! @brief Pointers to flexspi handles for each instance. */
0099 static flexspi_handle_t *s_flexspiHandle[ARRAY_SIZE(s_flexspiBases)];
0100 #endif
0101 
0102 #if defined(FSL_FEATURE_FLEXSPI_HAS_RESET) && FSL_FEATURE_FLEXSPI_HAS_RESET
0103 /*! @brief Pointers to FLEXSPI resets for each instance. */
0104 static const reset_ip_name_t s_flexspiResets[] = FLEXSPI_RSTS;
0105 #endif
0106 
0107 #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
0108 /*! @brief Pointer to flexspi IRQ handler. */
0109 static flexspi_isr_t s_flexspiIsr;
0110 #endif
0111 /*******************************************************************************
0112  * Code
0113  ******************************************************************************/
0114 /* To avoid compiler opitimizing this API into memset() in library. */
0115 #if defined(__ICCARM__)
0116 #pragma optimize = none
0117 #endif /* defined(__ICCARM__) */
0118 static void FLEXSPI_Memset(void *src, uint8_t value, size_t length)
0119 {
0120     assert(src != NULL);
0121     uint8_t *p = src;
0122 
0123     for (uint32_t i = 0U; i < length; i++)
0124     {
0125         *p = value;
0126         p++;
0127     }
0128 }
0129 
0130 uint32_t FLEXSPI_GetInstance(FLEXSPI_Type *base)
0131 {
0132     uint32_t instance;
0133 
0134     /* Find the instance index from base address mappings. */
0135     for (instance = 0; instance < ARRAY_SIZE(s_flexspiBases); instance++)
0136     {
0137         if (s_flexspiBases[instance] == base)
0138         {
0139             break;
0140         }
0141     }
0142 
0143     assert(instance < ARRAY_SIZE(s_flexspiBases));
0144 
0145     return instance;
0146 }
0147 
0148 static uint32_t FLEXSPI_CalculateDll(FLEXSPI_Type *base, flexspi_device_config_t *config)
0149 {
0150     bool isUnifiedConfig = true;
0151     uint32_t flexspiDllValue;
0152     uint32_t dllValue;
0153     uint32_t temp;
0154 #if defined(FSL_FEATURE_FLEXSPI_DQS_DELAY_PS) && FSL_FEATURE_FLEXSPI_DQS_DELAY_PS
0155     uint32_t internalDqsDelayPs = FSL_FEATURE_FLEXSPI_DQS_DELAY_PS;
0156 #endif
0157     uint32_t rxSampleClock = (base->MCR0 & FLEXSPI_MCR0_RXCLKSRC_MASK) >> FLEXSPI_MCR0_RXCLKSRC_SHIFT;
0158     switch (rxSampleClock)
0159     {
0160         case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackInternally:
0161         case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackFromDqsPad:
0162         case (uint32_t)kFLEXSPI_ReadSampleClkLoopbackFromSckPad:
0163             isUnifiedConfig = true;
0164             break;
0165         case (uint32_t)kFLEXSPI_ReadSampleClkExternalInputFromDqsPad:
0166             if (config->isSck2Enabled)
0167             {
0168                 isUnifiedConfig = true;
0169             }
0170             else
0171             {
0172                 isUnifiedConfig = false;
0173             }
0174             break;
0175         default:
0176             assert(false);
0177             break;
0178     }
0179 
0180     if (isUnifiedConfig)
0181     {
0182         flexspiDllValue = FLEXSPI_DLLCR_DEFAULT; /* 1 fixed delay cells in DLL delay chain) */
0183     }
0184     else
0185     {
0186         if (config->flexspiRootClk >= 100U * FREQ_1MHz)
0187         {
0188 #if defined(FSL_FEATURE_FLEXSPI_DQS_DELAY_MIN) && FSL_FEATURE_FLEXSPI_DQS_DELAY_MIN
0189             /* DLLEN = 1, SLVDLYTARGET = 0x0, */
0190             flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x00);
0191 #else
0192             /* DLLEN = 1, SLVDLYTARGET = 0xF, */
0193             flexspiDllValue = FLEXSPI_DLLCR_DLLEN(1) | FLEXSPI_DLLCR_SLVDLYTARGET(0x0F);
0194 #endif
0195         }
0196         else
0197         {
0198             temp     = (uint32_t)config->dataValidTime * 1000U; /* Convert data valid time in ns to ps. */
0199             dllValue = temp / (uint32_t)kFLEXSPI_DelayCellUnitMin;
0200             if (dllValue * (uint32_t)kFLEXSPI_DelayCellUnitMin < temp)
0201             {
0202                 dllValue++;
0203             }
0204             flexspiDllValue = FLEXSPI_DLLCR_OVRDEN(1) | FLEXSPI_DLLCR_OVRDVAL(dllValue);
0205         }
0206     }
0207     return flexspiDllValue;
0208 }
0209 
0210 status_t FLEXSPI_CheckAndClearError(FLEXSPI_Type *base, uint32_t status)
0211 {
0212     status_t result = kStatus_Success;
0213 
0214     /* Check for error. */
0215     status &= (uint32_t)kErrorFlags;
0216     if (0U != status)
0217     {
0218         /* Select the correct error code.. */
0219         if (0U != (status & (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag))
0220         {
0221             result = kStatus_FLEXSPI_SequenceExecutionTimeout;
0222         }
0223         else if (0U != (status & (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag))
0224         {
0225             result = kStatus_FLEXSPI_IpCommandSequenceError;
0226         }
0227         else if (0U != (status & (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag))
0228         {
0229             result = kStatus_FLEXSPI_IpCommandGrantTimeout;
0230         }
0231         else
0232         {
0233             assert(false);
0234         }
0235 
0236         /* Clear the flags. */
0237         FLEXSPI_ClearInterruptStatusFlags(base, status);
0238 
0239         /* Reset fifos. These flags clear automatically. */
0240         base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
0241         base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
0242     }
0243 
0244     return result;
0245 }
0246 
0247 /*!
0248  * brief Initializes the FLEXSPI module and internal state.
0249  *
0250  * This function enables the clock for FLEXSPI and also configures the FLEXSPI with the
0251  * input configure parameters. Users should call this function before any FLEXSPI operations.
0252  *
0253  * param base FLEXSPI peripheral base address.
0254  * param config FLEXSPI configure structure.
0255  */
0256 void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config)
0257 {
0258     uint32_t configValue = 0;
0259     uint8_t i            = 0;
0260 
0261 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0262     /* Enable the flexspi clock */
0263     (void)CLOCK_EnableClock(s_flexspiClock[FLEXSPI_GetInstance(base)]);
0264 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0265 
0266 #if defined(FSL_FEATURE_FLEXSPI_HAS_RESET) && FSL_FEATURE_FLEXSPI_HAS_RESET
0267     /* Reset the FLEXSPI module */
0268     RESET_PeripheralReset(s_flexspiResets[FLEXSPI_GetInstance(base)]);
0269 #endif
0270 
0271     /* Reset peripheral before configuring it. */
0272     base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
0273     FLEXSPI_SoftwareReset(base);
0274 
0275     /* Configure MCR0 configuration items. */
0276     configValue = FLEXSPI_MCR0_RXCLKSRC(config->rxSampleClock) | FLEXSPI_MCR0_DOZEEN(config->enableDoze) |
0277                   FLEXSPI_MCR0_IPGRANTWAIT(config->ipGrantTimeoutCycle) |
0278                   FLEXSPI_MCR0_AHBGRANTWAIT(config->ahbConfig.ahbGrantTimeoutCycle) |
0279                   FLEXSPI_MCR0_SCKFREERUNEN(config->enableSckFreeRunning) |
0280                   FLEXSPI_MCR0_HSEN(config->enableHalfSpeedAccess) |
0281 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN)
0282                   FLEXSPI_MCR0_COMBINATIONEN(config->enableCombination) |
0283 #endif
0284 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN)
0285                   FLEXSPI_MCR0_ATDFEN(config->ahbConfig.enableAHBWriteIpTxFifo) |
0286 #endif
0287 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN)
0288                   FLEXSPI_MCR0_ARDFEN(config->ahbConfig.enableAHBWriteIpRxFifo) |
0289 #endif
0290                   FLEXSPI_MCR0_MDIS_MASK;
0291     base->MCR0 = configValue;
0292 
0293     /* Configure MCR1 configurations. */
0294     configValue =
0295         FLEXSPI_MCR1_SEQWAIT(config->seqTimeoutCycle) | FLEXSPI_MCR1_AHBBUSWAIT(config->ahbConfig.ahbBusTimeoutCycle);
0296     base->MCR1 = configValue;
0297 
0298     /* Configure MCR2 configurations. */
0299     configValue = base->MCR2;
0300     configValue &= ~(FLEXSPI_MCR2_RESUMEWAIT_MASK |
0301 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT)
0302                      FLEXSPI_MCR2_SCKBDIFFOPT_MASK |
0303 #endif
0304                      FLEXSPI_MCR2_SAMEDEVICEEN_MASK | FLEXSPI_MCR2_CLRAHBBUFOPT_MASK);
0305     configValue |= FLEXSPI_MCR2_RESUMEWAIT(config->ahbConfig.resumeWaitCycle) |
0306 #if defined(FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB) && FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB
0307                    FLEXSPI_MCR2_RXCLKSRC_B(config->rxSampleClockPortB) |
0308 #endif
0309 #if defined(FSL_FEATURE_FLEXSPI_SUPPORT_RXCLKSRC_DIFF) && FSL_FEATURE_FLEXSPI_SUPPORT_RXCLKSRC_DIFF
0310                    FLEXSPI_MCR2_RX_CLK_SRC_DIFF(config->rxSampleClockDiff) |
0311 #endif
0312 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT)
0313                    FLEXSPI_MCR2_SCKBDIFFOPT(config->enableSckBDiffOpt) |
0314 #endif
0315                    FLEXSPI_MCR2_SAMEDEVICEEN(config->enableSameConfigForAll) |
0316                    FLEXSPI_MCR2_CLRAHBBUFOPT(config->ahbConfig.enableClearAHBBufferOpt);
0317 
0318     base->MCR2 = configValue;
0319 
0320     /* Configure AHB control items. */
0321     configValue = base->AHBCR;
0322     configValue &= ~(FLEXSPI_AHBCR_READADDROPT_MASK | FLEXSPI_AHBCR_PREFETCHEN_MASK | FLEXSPI_AHBCR_BUFFERABLEEN_MASK |
0323                      FLEXSPI_AHBCR_CACHABLEEN_MASK);
0324     configValue |= FLEXSPI_AHBCR_READADDROPT(config->ahbConfig.enableReadAddressOpt) |
0325                    FLEXSPI_AHBCR_PREFETCHEN(config->ahbConfig.enableAHBPrefetch) |
0326                    FLEXSPI_AHBCR_BUFFERABLEEN(config->ahbConfig.enableAHBBufferable) |
0327                    FLEXSPI_AHBCR_CACHABLEEN(config->ahbConfig.enableAHBCachable);
0328     base->AHBCR = configValue;
0329 
0330     /* Configure AHB rx buffers. */
0331     for (i = 0; i < (uint32_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++)
0332     {
0333         configValue = base->AHBRXBUFCR0[i];
0334 
0335         configValue &= ~(FLEXSPI_AHBRXBUFCR0_PREFETCHEN_MASK | FLEXSPI_AHBRXBUFCR0_PRIORITY_MASK |
0336                          FLEXSPI_AHBRXBUFCR0_MSTRID_MASK | FLEXSPI_AHBRXBUFCR0_BUFSZ_MASK);
0337         configValue |= FLEXSPI_AHBRXBUFCR0_PREFETCHEN(config->ahbConfig.buffer[i].enablePrefetch) |
0338                        FLEXSPI_AHBRXBUFCR0_PRIORITY(config->ahbConfig.buffer[i].priority) |
0339                        FLEXSPI_AHBRXBUFCR0_MSTRID(config->ahbConfig.buffer[i].masterIndex) |
0340                        FLEXSPI_AHBRXBUFCR0_BUFSZ((uint32_t)config->ahbConfig.buffer[i].bufferSize / 8U);
0341         base->AHBRXBUFCR0[i] = configValue;
0342     }
0343 
0344     /* Configure IP Fifo watermarks. */
0345     base->IPRXFCR &= ~FLEXSPI_IPRXFCR_RXWMRK_MASK;
0346     base->IPRXFCR |= FLEXSPI_IPRXFCR_RXWMRK((uint32_t)config->rxWatermark / 8U - 1U);
0347     base->IPTXFCR &= ~FLEXSPI_IPTXFCR_TXWMRK_MASK;
0348     base->IPTXFCR |= FLEXSPI_IPTXFCR_TXWMRK((uint32_t)config->txWatermark / 8U - 1U);
0349 
0350     /* Reset flash size on all ports */
0351     for (i = 0; i < (uint32_t)kFLEXSPI_PortCount; i++)
0352     {
0353         base->FLSHCR0[i] = 0;
0354     }
0355 }
0356 
0357 /*!
0358  * brief Gets default settings for FLEXSPI.
0359  *
0360  * param config FLEXSPI configuration structure.
0361  */
0362 void FLEXSPI_GetDefaultConfig(flexspi_config_t *config)
0363 {
0364     /* Initializes the configure structure to zero. */
0365     FLEXSPI_Memset(config, 0, sizeof(*config));
0366 
0367     config->rxSampleClock        = kFLEXSPI_ReadSampleClkLoopbackInternally;
0368     config->enableSckFreeRunning = false;
0369 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN)
0370     config->enableCombination = false;
0371 #endif
0372     config->enableDoze            = true;
0373     config->enableHalfSpeedAccess = false;
0374 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR2_SCKBDIFFOPT)
0375     config->enableSckBDiffOpt = false;
0376 #endif
0377     config->enableSameConfigForAll = false;
0378     config->seqTimeoutCycle        = 0xFFFFU;
0379     config->ipGrantTimeoutCycle    = 0xFFU;
0380     config->txWatermark            = 8;
0381     config->rxWatermark            = 8;
0382 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ATDFEN)
0383     config->ahbConfig.enableAHBWriteIpTxFifo = false;
0384 #endif
0385 #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_ARDFEN)
0386     config->ahbConfig.enableAHBWriteIpRxFifo = false;
0387 #endif
0388     config->ahbConfig.ahbGrantTimeoutCycle = 0xFFU;
0389     config->ahbConfig.ahbBusTimeoutCycle   = 0xFFFFU;
0390     config->ahbConfig.resumeWaitCycle      = 0x20U;
0391     FLEXSPI_Memset(config->ahbConfig.buffer, 0, sizeof(config->ahbConfig.buffer));
0392     /* Use invalid master ID 0xF and buffer size 0 for the first several buffers. */
0393     for (uint8_t i = 0; i < ((uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 2U); i++)
0394     {
0395         config->ahbConfig.buffer[i].enablePrefetch = true; /* Default enable AHB prefetch. */
0396         config->ahbConfig.buffer[i].masterIndex = 0xFU; /* Invalid master index which is not used, so will never hit. */
0397         config->ahbConfig.buffer[i].bufferSize =
0398             0; /* Default buffer size 0 for buffer0 to buffer(FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 3U)*/
0399     }
0400 
0401     for (uint8_t i = ((uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT - 2U);
0402          i < (uint8_t)FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT; i++)
0403     {
0404         config->ahbConfig.buffer[i].enablePrefetch = true; /* Default enable AHB prefetch. */
0405         config->ahbConfig.buffer[i].bufferSize     = 256U; /* Default buffer size 256 bytes. */
0406     }
0407     config->ahbConfig.enableClearAHBBufferOpt = false;
0408     config->ahbConfig.enableReadAddressOpt    = false;
0409     config->ahbConfig.enableAHBPrefetch       = false;
0410     config->ahbConfig.enableAHBBufferable     = false;
0411     config->ahbConfig.enableAHBCachable       = false;
0412 }
0413 
0414 /*!
0415  * brief Deinitializes the FLEXSPI module.
0416  *
0417  * Clears the FLEXSPI state and  FLEXSPI module registers.
0418  * param base FLEXSPI peripheral base address.
0419  */
0420 void FLEXSPI_Deinit(FLEXSPI_Type *base)
0421 {
0422     /* Reset peripheral. */
0423     FLEXSPI_SoftwareReset(base);
0424 }
0425 
0426 /*!
0427  * brief Update FLEXSPI DLL value depending on currently flexspi root clock.
0428  *
0429  * param base FLEXSPI peripheral base address.
0430  * param config Flash configuration parameters.
0431  * param port FLEXSPI Operation port.
0432  */
0433 void FLEXSPI_UpdateDllValue(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
0434 {
0435     uint32_t configValue = 0;
0436     uint32_t statusValue = 0;
0437     uint8_t index        = (uint8_t)port >> 1U; /* PortA with index 0, PortB with index 1. */
0438 
0439     /* Wait for bus to be idle before changing flash configuration. */
0440     while (!FLEXSPI_GetBusIdleStatus(base))
0441     {
0442     }
0443 
0444     /* Configure DLL. */
0445     configValue        = FLEXSPI_CalculateDll(base, config);
0446     base->DLLCR[index] = configValue;
0447 
0448     /* Exit stop mode. */
0449     base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
0450 
0451     /* According to ERR011377, need to delay at least 100 NOPs to ensure the DLL is locked. */
0452     if (index == 0U)
0453     {
0454         statusValue =
0455             ((uint32_t)kFLEXSPI_FlashASampleClockSlaveDelayLocked | (uint32_t)kFLEXSPI_FlashASampleClockRefDelayLocked);
0456     }
0457 #if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK)) && (FSL_FEATURE_FLEXSPI_HAS_NO_STS2_BSLVLOCK))
0458     else
0459     {
0460         statusValue =
0461             ((uint32_t)kFLEXSPI_FlashBSampleClockSlaveDelayLocked | (uint32_t)kFLEXSPI_FlashBSampleClockRefDelayLocked);
0462     }
0463 #endif
0464     if (0U != (configValue & FLEXSPI_DLLCR_DLLEN_MASK))
0465     {
0466 #if defined(FSL_FEATURE_FLEXSPI_HAS_ERRATA_051426) && (FSL_FEATURE_FLEXSPI_HAS_ERRATA_051426)
0467         if (config->isFroClockSource == false)
0468 #endif
0469         {
0470             /* Wait slave delay line locked and slave reference delay line locked. */
0471             while ((base->STS2 & statusValue) != statusValue)
0472             {
0473             }
0474         }
0475 
0476         /* Wait at least 100 NOPs*/
0477         for (uint8_t delay = 100U; delay > 0U; delay--)
0478         {
0479             __NOP();
0480         }
0481     }
0482 }
0483 
0484 /*!
0485  * brief Configures the connected device parameter.
0486  *
0487  * This function configures the connected device relevant parameters, such as the size, command, and so on.
0488  * The flash configuration value cannot have a default value. The user needs to configure it according to the
0489  * connected device.
0490  *
0491  * param base FLEXSPI peripheral base address.
0492  * param config Flash configuration parameters.
0493  * param port FLEXSPI Operation port.
0494  */
0495 void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port)
0496 {
0497     uint32_t configValue = 0;
0498     uint8_t index        = (uint8_t)port >> 1U; /* PortA with index 0, PortB with index 1. */
0499 
0500     /* Wait for bus to be idle before changing flash configuration. */
0501     while (!FLEXSPI_GetBusIdleStatus(base))
0502     {
0503     }
0504 
0505     /* Configure flash size and address shift. */
0506 #if defined(FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT) && (FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT)
0507     base->FLSHCR0[port] = config->flashSize | FLEXSPI_FLSHCR0_ADDRSHIFT(config->addressShift);
0508 #else
0509     base->FLSHCR0[port] = config->flashSize;
0510 #endif /* FSL_FEATURE_FLEXSPI_SUPPORT_ADDRESS_SHIFT */
0511 
0512     /* Configure flash parameters. */
0513     base->FLSHCR1[port] = FLEXSPI_FLSHCR1_CSINTERVAL(config->CSInterval) |
0514                           FLEXSPI_FLSHCR1_CSINTERVALUNIT(config->CSIntervalUnit) |
0515                           FLEXSPI_FLSHCR1_TCSH(config->CSHoldTime) | FLEXSPI_FLSHCR1_TCSS(config->CSSetupTime) |
0516                           FLEXSPI_FLSHCR1_CAS(config->columnspace) | FLEXSPI_FLSHCR1_WA(config->enableWordAddress);
0517 
0518     /* Configure AHB operation items. */
0519     configValue = base->FLSHCR2[port];
0520 
0521     configValue &= ~(FLEXSPI_FLSHCR2_AWRWAITUNIT_MASK | FLEXSPI_FLSHCR2_AWRWAIT_MASK | FLEXSPI_FLSHCR2_AWRSEQNUM_MASK |
0522                      FLEXSPI_FLSHCR2_AWRSEQID_MASK | FLEXSPI_FLSHCR2_ARDSEQNUM_MASK | FLEXSPI_FLSHCR2_ARDSEQID_MASK);
0523 
0524     configValue |=
0525         FLEXSPI_FLSHCR2_AWRWAITUNIT(config->AHBWriteWaitUnit) | FLEXSPI_FLSHCR2_AWRWAIT(config->AHBWriteWaitInterval);
0526 
0527     if (config->AWRSeqNumber > 0U)
0528     {
0529         configValue |= FLEXSPI_FLSHCR2_AWRSEQID((uint32_t)config->AWRSeqIndex) |
0530                        FLEXSPI_FLSHCR2_AWRSEQNUM((uint32_t)config->AWRSeqNumber - 1U);
0531     }
0532 
0533     if (config->ARDSeqNumber > 0U)
0534     {
0535         configValue |= FLEXSPI_FLSHCR2_ARDSEQID((uint32_t)config->ARDSeqIndex) |
0536                        FLEXSPI_FLSHCR2_ARDSEQNUM((uint32_t)config->ARDSeqNumber - 1U);
0537     }
0538 
0539     base->FLSHCR2[port] = configValue;
0540 
0541     /* Configure DLL. */
0542     FLEXSPI_UpdateDllValue(base, config, port);
0543 
0544     /* Step into stop mode. */
0545     base->MCR0 |= FLEXSPI_MCR0_MDIS_MASK;
0546 
0547     /* Configure write mask. */
0548     if (config->enableWriteMask)
0549     {
0550         base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMOPT1_MASK;
0551     }
0552     else
0553     {
0554         base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMOPT1_MASK;
0555     }
0556 
0557     if (index == 0U) /*PortA*/
0558     {
0559         base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENA_MASK;
0560         base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENA(config->enableWriteMask);
0561     }
0562 #if !((defined(FSL_FEATURE_FLEXSPI_HAS_NO_FLSHCR4_WMENB)) && (FSL_FEATURE_FLEXSPI_HAS_NO_FLSHCR4_WMENB))
0563     else
0564     {
0565         base->FLSHCR4 &= ~FLEXSPI_FLSHCR4_WMENB_MASK;
0566         base->FLSHCR4 |= FLEXSPI_FLSHCR4_WMENB(config->enableWriteMask);
0567     }
0568 #endif
0569 
0570     /* Exit stop mode. */
0571     base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK;
0572 
0573     /* Wait for bus to be idle before use it access to external flash. */
0574     while (!FLEXSPI_GetBusIdleStatus(base))
0575     {
0576     }
0577 }
0578 
0579 /*! brief Updates the LUT table.
0580  *
0581  * param base FLEXSPI peripheral base address.
0582  * param index From which index start to update. It could be any index of the LUT table, which
0583  * also allows user to update command content inside a command. Each command consists of up to
0584  * 8 instructions and occupy 4*32-bit memory.
0585  * param cmd Command sequence array.
0586  * param count Number of sequences.
0587  */
0588 void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count)
0589 {
0590     assert(index < 64U);
0591 
0592     uint32_t i = 0;
0593     volatile uint32_t *lutBase;
0594 
0595     /* Wait for bus to be idle before changing flash configuration. */
0596     while (!FLEXSPI_GetBusIdleStatus(base))
0597     {
0598     }
0599 
0600     /* Unlock LUT for update. */
0601 #if !((defined(FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO)) && (FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO))
0602     base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
0603 #endif
0604     base->LUTCR = 0x02;
0605 
0606     lutBase = &base->LUT[index];
0607     for (i = 0; i < count; i++)
0608     {
0609         *lutBase++ = *cmd++;
0610     }
0611 
0612     /* Lock LUT. */
0613 #if !((defined(FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO)) && (FSL_FEATURE_FLEXSPI_LUTKEY_IS_RO))
0614     base->LUTKEY = FLEXSPI_LUT_KEY_VAL;
0615 #endif
0616     base->LUTCR = 0x01;
0617 }
0618 
0619 /*! brief Update read sample clock source
0620  *
0621  * param base FLEXSPI peripheral base address.
0622  * param clockSource clockSource of type #flexspi_read_sample_clock_t
0623  */
0624 void FLEXSPI_UpdateRxSampleClock(FLEXSPI_Type *base, flexspi_read_sample_clock_t clockSource)
0625 {
0626     uint32_t mcr0Val;
0627 
0628     /* Wait for bus to be idle before changing flash configuration. */
0629     while (!FLEXSPI_GetBusIdleStatus(base))
0630     {
0631     }
0632 
0633     mcr0Val = base->MCR0;
0634     mcr0Val &= ~FLEXSPI_MCR0_RXCLKSRC_MASK;
0635     mcr0Val |= FLEXSPI_MCR0_RXCLKSRC(clockSource);
0636     base->MCR0 = mcr0Val;
0637 
0638     /* Reset peripheral. */
0639     FLEXSPI_SoftwareReset(base);
0640 }
0641 
0642 /*!
0643  * brief Sends a buffer of data bytes using blocking method.
0644  * note This function blocks via polling until all bytes have been sent.
0645  * param base FLEXSPI peripheral base address
0646  * param buffer The data bytes to send
0647  * param size The number of data bytes to send
0648  * retval kStatus_Success write success without error
0649  * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
0650  * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
0651  * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
0652  */
0653 status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size)
0654 {
0655     uint32_t txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1U;
0656     uint32_t status;
0657     status_t result = kStatus_Success;
0658     uint32_t i      = 0;
0659 
0660     /* Send data buffer */
0661     while (0U != size)
0662     {
0663         /* Wait until there is room in the fifo. This also checks for errors. */
0664         while (0U == ((status = base->INTR) & (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag))
0665         {
0666         }
0667 
0668         result = FLEXSPI_CheckAndClearError(base, status);
0669 
0670         if (kStatus_Success != result)
0671         {
0672             return result;
0673         }
0674 
0675         /* Write watermark level data into tx fifo . */
0676         if (size >= 8U * txWatermark)
0677         {
0678             for (i = 0U; i < 2U * txWatermark; i++)
0679             {
0680                 base->TFDR[i] = *(uint32_t *)(void *)buffer;
0681                 buffer += 4U;
0682             }
0683 
0684             size = size - 8U * txWatermark;
0685         }
0686         else
0687         {
0688             /* Write word aligned data into tx fifo. */
0689             for (i = 0U; i < (size / 4U); i++)
0690             {
0691                 base->TFDR[i] = *(uint32_t *)(void *)buffer;
0692                 buffer += 4U;
0693             }
0694 
0695             /* Adjust size by the amount processed. */
0696             size -= 4U * i;
0697 
0698             /* Write word un-aligned data into tx fifo. */
0699             if (0x00U != size)
0700             {
0701                 uint32_t tempVal = 0x00U;
0702 
0703                 for (uint32_t j = 0U; j < size; j++)
0704                 {
0705                     tempVal |= ((uint32_t)*buffer++ << (8U * j));
0706                 }
0707 
0708                 base->TFDR[i] = tempVal;
0709             }
0710 
0711             size = 0U;
0712         }
0713 
0714         /* Push a watermark level data into IP TX FIFO. */
0715         base->INTR |= (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag;
0716     }
0717 
0718     return result;
0719 }
0720 
0721 /*!
0722  * brief Receives a buffer of data bytes using a blocking method.
0723  * note This function blocks via polling until all bytes have been sent.
0724  * param base FLEXSPI peripheral base address
0725  * param buffer The data bytes to send
0726  * param size The number of data bytes to receive
0727  * retval kStatus_Success read success without error
0728  * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
0729  * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
0730  * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
0731  */
0732 status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size)
0733 {
0734     uint32_t rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1U;
0735     uint32_t status;
0736     status_t result = kStatus_Success;
0737     uint32_t i      = 0;
0738     bool isReturn   = false;
0739 
0740     /* Send data buffer */
0741     while (0U != size)
0742     {
0743         if (size >= 8U * rxWatermark)
0744         {
0745             /* Wait until there is room in the fifo. This also checks for errors. */
0746             while (0U == ((status = base->INTR) & (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag))
0747             {
0748                 result = FLEXSPI_CheckAndClearError(base, status);
0749 
0750                 if (kStatus_Success != result)
0751                 {
0752                     isReturn = true;
0753                     break;
0754                 }
0755             }
0756         }
0757         else
0758         {
0759             /* Wait fill level. This also checks for errors. */
0760             while (size > ((((base->IPRXFSTS) & FLEXSPI_IPRXFSTS_FILL_MASK) >> FLEXSPI_IPRXFSTS_FILL_SHIFT) * 8U))
0761             {
0762                 result = FLEXSPI_CheckAndClearError(base, base->INTR);
0763 
0764                 if (kStatus_Success != result)
0765                 {
0766                     isReturn = true;
0767                     break;
0768                 }
0769             }
0770         }
0771 
0772         if (isReturn)
0773         {
0774             break;
0775         }
0776 
0777         result = FLEXSPI_CheckAndClearError(base, base->INTR);
0778 
0779         if (kStatus_Success != result)
0780         {
0781             break;
0782         }
0783 
0784         /* Read watermark level data from rx fifo. */
0785         if (size >= 8U * rxWatermark)
0786         {
0787             for (i = 0U; i < 2U * rxWatermark; i++)
0788             {
0789                 *(uint32_t *)(void *)buffer = base->RFDR[i];
0790                 buffer += 4U;
0791             }
0792 
0793             size = size - 8U * rxWatermark;
0794         }
0795         else
0796         {
0797             /* Read word aligned data from rx fifo. */
0798             for (i = 0U; i < (size / 4U); i++)
0799             {
0800                 *(uint32_t *)(void *)buffer = base->RFDR[i];
0801                 buffer += 4U;
0802             }
0803 
0804             /* Adjust size by the amount processed. */
0805             size -= 4U * i;
0806 
0807             /* Read word un-aligned data from rx fifo. */
0808             if (0x00U != size)
0809             {
0810                 uint32_t tempVal = base->RFDR[i];
0811 
0812                 for (i = 0U; i < size; i++)
0813                 {
0814                     *buffer++ = ((uint8_t)(tempVal >> (8U * i)) & 0xFFU);
0815                 }
0816             }
0817 
0818             size = 0;
0819         }
0820 
0821         /* Pop out a watermark level datas from IP RX FIFO. */
0822         base->INTR |= (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
0823     }
0824 
0825     return result;
0826 }
0827 
0828 /*!
0829  * brief Execute command to transfer a buffer data bytes using a blocking method.
0830  * param base FLEXSPI peripheral base address
0831  * param xfer pointer to the transfer structure.
0832  * retval kStatus_Success command transfer success without error
0833  * retval kStatus_FLEXSPI_SequenceExecutionTimeout sequence execution timeout
0834  * retval kStatus_FLEXSPI_IpCommandSequenceError IP command sequence error detected
0835  * retval kStatus_FLEXSPI_IpCommandGrantTimeout IP command grant timeout detected
0836  */
0837 status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer)
0838 {
0839     uint32_t configValue = 0;
0840     status_t result      = kStatus_Success;
0841 
0842     /* Clear sequence pointer before sending data to external devices. */
0843     base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
0844 
0845     /* Clear former pending status before start this transfer. */
0846     base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
0847                   FLEXSPI_INTR_IPCMDGE_MASK;
0848 
0849     /* Configure base address. */
0850     base->IPCR0 = xfer->deviceAddress;
0851 
0852     /* Reset fifos. */
0853     base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
0854     base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
0855 
0856     /* Configure data size. */
0857     if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
0858     {
0859         configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
0860     }
0861 
0862     /* Configure sequence ID. */
0863     configValue |=
0864         FLEXSPI_IPCR1_ISEQID((uint32_t)xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->SeqNumber - 1U);
0865     base->IPCR1 = configValue;
0866 
0867     /* Start Transfer. */
0868     base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
0869 
0870     if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
0871     {
0872         result = FLEXSPI_WriteBlocking(base, (uint8_t *)xfer->data, xfer->dataSize);
0873     }
0874     else if (xfer->cmdType == kFLEXSPI_Read)
0875     {
0876         result = FLEXSPI_ReadBlocking(base, (uint8_t *)xfer->data, xfer->dataSize);
0877     }
0878     else
0879     {
0880         /* Empty else. */
0881     }
0882 
0883     /* Wait for bus to be idle before changing flash configuration. */
0884     while (!FLEXSPI_GetBusIdleStatus(base))
0885     {
0886     }
0887 
0888     if (xfer->cmdType == kFLEXSPI_Command)
0889     {
0890         result = FLEXSPI_CheckAndClearError(base, base->INTR);
0891     }
0892 
0893     return result;
0894 }
0895 
0896 /*!
0897  * brief Initializes the FLEXSPI handle which is used in transactional functions.
0898  *
0899  * param base FLEXSPI peripheral base address.
0900  * param handle pointer to flexspi_handle_t structure to store the transfer state.
0901  * param callback pointer to user callback function.
0902  * param userData user parameter passed to the callback function.
0903  */
0904 void FLEXSPI_TransferCreateHandle(FLEXSPI_Type *base,
0905                                   flexspi_handle_t *handle,
0906                                   flexspi_transfer_callback_t callback,
0907                                   void *userData)
0908 {
0909     assert(NULL != handle);
0910 
0911     uint32_t instance = FLEXSPI_GetInstance(base);
0912 
0913     /* Zero handle. */
0914     (void)memset(handle, 0, sizeof(*handle));
0915 
0916     /* Set callback and userData. */
0917     handle->completionCallback = callback;
0918     handle->userData           = userData;
0919 
0920 #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
0921     /* Save the context in global variables to support the double weak mechanism. */
0922     s_flexspiHandle[instance] = handle;
0923     s_flexspiIsr              = FLEXSPI_TransferHandleIRQ;
0924 #endif
0925 
0926     /* Enable NVIC interrupt. */
0927     (void)EnableIRQ(s_flexspiIrqs[instance]);
0928 }
0929 
0930 /*!
0931  * brief Performs a interrupt non-blocking transfer on the FLEXSPI bus.
0932  *
0933  * note Calling the API returns immediately after transfer initiates. The user needs
0934  * to call FLEXSPI_GetTransferCount to poll the transfer status to check whether
0935  * the transfer is finished. If the return status is not kStatus_FLEXSPI_Busy, the transfer
0936  * is finished. For FLEXSPI_Read, the dataSize should be multiple of rx watermark level, or
0937  * FLEXSPI could not read data properly.
0938  *
0939  * param base FLEXSPI peripheral base address.
0940  * param handle pointer to flexspi_handle_t structure which stores the transfer state.
0941  * param xfer pointer to flexspi_transfer_t structure.
0942  * retval kStatus_Success Successfully start the data transmission.
0943  * retval kStatus_FLEXSPI_Busy Previous transmission still not finished.
0944  */
0945 status_t FLEXSPI_TransferNonBlocking(FLEXSPI_Type *base, flexspi_handle_t *handle, flexspi_transfer_t *xfer)
0946 {
0947     uint32_t configValue = 0;
0948     status_t result      = kStatus_Success;
0949 
0950     assert(NULL != handle);
0951     assert(NULL != xfer);
0952 
0953     /* Check if the I2C bus is idle - if not return busy status. */
0954     if (handle->state != (uint32_t)kFLEXSPI_Idle)
0955     {
0956         result = kStatus_FLEXSPI_Busy;
0957     }
0958     else
0959     {
0960         handle->data              = (uint8_t *)xfer->data;
0961         handle->dataSize          = xfer->dataSize;
0962         handle->transferTotalSize = xfer->dataSize;
0963         handle->state = (xfer->cmdType == kFLEXSPI_Read) ? (uint32_t)kFLEXSPI_BusyRead : (uint32_t)kFLEXSPI_BusyWrite;
0964 
0965         /* Clear sequence pointer before sending data to external devices. */
0966         base->FLSHCR2[xfer->port] |= FLEXSPI_FLSHCR2_CLRINSTRPTR_MASK;
0967 
0968         /* Clear former pending status before start this transfer. */
0969         base->INTR |= FLEXSPI_INTR_AHBCMDERR_MASK | FLEXSPI_INTR_IPCMDERR_MASK | FLEXSPI_INTR_AHBCMDGE_MASK |
0970                       FLEXSPI_INTR_IPCMDGE_MASK;
0971 
0972         /* Configure base address. */
0973         base->IPCR0 = xfer->deviceAddress;
0974 
0975         /* Reset fifos. */
0976         base->IPTXFCR |= FLEXSPI_IPTXFCR_CLRIPTXF_MASK;
0977         base->IPRXFCR |= FLEXSPI_IPRXFCR_CLRIPRXF_MASK;
0978 
0979         /* Configure data size. */
0980         if ((xfer->cmdType == kFLEXSPI_Read) || (xfer->cmdType == kFLEXSPI_Write))
0981         {
0982             configValue = FLEXSPI_IPCR1_IDATSZ(xfer->dataSize);
0983         }
0984 
0985         /* Configure sequence ID. */
0986         configValue |=
0987             FLEXSPI_IPCR1_ISEQID((uint32_t)xfer->seqIndex) | FLEXSPI_IPCR1_ISEQNUM((uint32_t)xfer->SeqNumber - 1U);
0988         base->IPCR1 = configValue;
0989 
0990         /* Start Transfer. */
0991         base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
0992 
0993         if (handle->state == (uint32_t)kFLEXSPI_BusyRead)
0994         {
0995             FLEXSPI_EnableInterrupts(base, (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag |
0996                                                (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag |
0997                                                (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag |
0998                                                (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag |
0999                                                (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag);
1000         }
1001         else
1002         {
1003             FLEXSPI_EnableInterrupts(
1004                 base, (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag | (uint32_t)kFLEXSPI_SequenceExecutionTimeoutFlag |
1005                           (uint32_t)kFLEXSPI_IpCommandSequenceErrorFlag | (uint32_t)kFLEXSPI_IpCommandGrantTimeoutFlag |
1006                           (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag);
1007         }
1008     }
1009 
1010     return result;
1011 }
1012 
1013 /*!
1014  * brief Gets the master transfer status during a interrupt non-blocking transfer.
1015  *
1016  * param base FLEXSPI peripheral base address.
1017  * param handle pointer to flexspi_handle_t structure which stores the transfer state.
1018  * param count Number of bytes transferred so far by the non-blocking transaction.
1019  * retval kStatus_InvalidArgument count is Invalid.
1020  * retval kStatus_Success Successfully return the count.
1021  */
1022 status_t FLEXSPI_TransferGetCount(FLEXSPI_Type *base, flexspi_handle_t *handle, size_t *count)
1023 {
1024     assert(NULL != handle);
1025 
1026     status_t result = kStatus_Success;
1027 
1028     if (handle->state == (uint32_t)kFLEXSPI_Idle)
1029     {
1030         result = kStatus_NoTransferInProgress;
1031     }
1032     else
1033     {
1034         *count = handle->transferTotalSize - handle->dataSize;
1035     }
1036 
1037     return result;
1038 }
1039 
1040 /*!
1041  * brief Aborts an interrupt non-blocking transfer early.
1042  *
1043  * note This API can be called at any time when an interrupt non-blocking transfer initiates
1044  * to abort the transfer early.
1045  *
1046  * param base FLEXSPI peripheral base address.
1047  * param handle pointer to flexspi_handle_t structure which stores the transfer state
1048  */
1049 void FLEXSPI_TransferAbort(FLEXSPI_Type *base, flexspi_handle_t *handle)
1050 {
1051     assert(NULL != handle);
1052 
1053     FLEXSPI_DisableInterrupts(base, (uint32_t)kIrqFlags);
1054     handle->state = (uint32_t)kFLEXSPI_Idle;
1055 }
1056 
1057 /*!
1058  * brief Master interrupt handler.
1059  *
1060  * param base FLEXSPI peripheral base address.
1061  * param handle pointer to flexspi_handle_t structure.
1062  */
1063 void FLEXSPI_TransferHandleIRQ(FLEXSPI_Type *base, flexspi_handle_t *handle)
1064 {
1065     uint32_t status;
1066     status_t result;
1067     uint32_t intEnableStatus;
1068     uint32_t txWatermark;
1069     uint32_t rxWatermark;
1070     uint32_t i = 0;
1071 
1072     status          = base->INTR;
1073     intEnableStatus = base->INTEN;
1074 
1075     /* Check if interrupt is enabled and status is alerted. */
1076     if ((status & intEnableStatus) != 0U)
1077     {
1078         result = FLEXSPI_CheckAndClearError(base, status);
1079 
1080         if ((result != kStatus_Success) && (handle->completionCallback != NULL))
1081         {
1082             FLEXSPI_TransferAbort(base, handle);
1083             if (NULL != handle->completionCallback)
1084             {
1085                 handle->completionCallback(base, handle, result, handle->userData);
1086             }
1087         }
1088         else
1089         {
1090             if ((0U != (status & (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag)) &&
1091                 (handle->state == (uint32_t)kFLEXSPI_BusyRead))
1092             {
1093                 rxWatermark = ((base->IPRXFCR & FLEXSPI_IPRXFCR_RXWMRK_MASK) >> FLEXSPI_IPRXFCR_RXWMRK_SHIFT) + 1U;
1094 
1095                 /* Read watermark level data from rx fifo . */
1096                 if (handle->dataSize >= 8U * rxWatermark)
1097                 {
1098                     /* Read watermark level data from rx fifo . */
1099                     for (i = 0U; i < 2U * rxWatermark; i++)
1100                     {
1101                         *(uint32_t *)(void *)handle->data = base->RFDR[i];
1102                         handle->data += 4U;
1103                     }
1104 
1105                     handle->dataSize = handle->dataSize - 8U * rxWatermark;
1106                 }
1107                 else
1108                 {
1109                     /* Read word aligned data from rx fifo. */
1110                     for (i = 0U; i < (handle->dataSize / 4U); i++)
1111                     {
1112                         *(uint32_t *)(void *)handle->data = base->RFDR[i];
1113                         handle->data += 4U;
1114                     }
1115 
1116                     /* Adjust size by the amount processed. */
1117                     handle->dataSize -= 4U * i;
1118 
1119                     /* Read word un-aligned data from rx fifo. */
1120                     if (0x00U != handle->dataSize)
1121                     {
1122                         uint32_t tempVal = base->RFDR[i];
1123 
1124                         for (i = 0U; i < handle->dataSize; i++)
1125                         {
1126                             *handle->data++ = ((uint8_t)(tempVal >> (8U * i)) & 0xFFU);
1127                         }
1128                     }
1129 
1130                     handle->dataSize = 0;
1131                 }
1132                 /* Pop out a watermark level data from IP RX FIFO. */
1133                 base->INTR |= (uint32_t)kFLEXSPI_IpRxFifoWatermarkAvailableFlag;
1134             }
1135 
1136             if (0U != (status & (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag))
1137             {
1138                 base->INTR |= (uint32_t)kFLEXSPI_IpCommandExecutionDoneFlag;
1139 
1140                 FLEXSPI_TransferAbort(base, handle);
1141 
1142                 if (NULL != handle->completionCallback)
1143                 {
1144                     handle->completionCallback(base, handle, kStatus_Success, handle->userData);
1145                 }
1146             }
1147 
1148             /* TX FIFO empty interrupt, push watermark level data into tx FIFO. */
1149             if ((0U != (status & (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag)) &&
1150                 (handle->state == (uint32_t)kFLEXSPI_BusyWrite))
1151             {
1152                 if (0U != handle->dataSize)
1153                 {
1154                     txWatermark = ((base->IPTXFCR & FLEXSPI_IPTXFCR_TXWMRK_MASK) >> FLEXSPI_IPTXFCR_TXWMRK_SHIFT) + 1U;
1155                     /* Write watermark level data into tx fifo . */
1156                     if (handle->dataSize >= 8U * txWatermark)
1157                     {
1158                         for (i = 0; i < 2U * txWatermark; i++)
1159                         {
1160                             base->TFDR[i] = *(uint32_t *)(void *)handle->data;
1161                             handle->data += 4U;
1162                         }
1163 
1164                         handle->dataSize = handle->dataSize - 8U * txWatermark;
1165                     }
1166                     else
1167                     {
1168                         /* Write word aligned data into tx fifo. */
1169                         for (i = 0U; i < (handle->dataSize / 4U); i++)
1170                         {
1171                             base->TFDR[i] = *(uint32_t *)(void *)handle->data;
1172                             handle->data += 4U;
1173                         }
1174 
1175                         /* Adjust size by the amount processed. */
1176                         handle->dataSize -= 4U * i;
1177 
1178                         /* Write word un-aligned data into tx fifo. */
1179                         if (0x00U != handle->dataSize)
1180                         {
1181                             uint32_t tempVal = 0x00U;
1182 
1183                             for (uint32_t j = 0U; j < handle->dataSize; j++)
1184                             {
1185                                 tempVal |= ((uint32_t)*handle->data++ << (8U * j));
1186                             }
1187 
1188                             base->TFDR[i] = tempVal;
1189                         }
1190 
1191                         handle->dataSize = 0;
1192                     }
1193 
1194                     /* Push a watermark level data into IP TX FIFO. */
1195                     base->INTR |= (uint32_t)kFLEXSPI_IpTxFifoWatermarkEmptyFlag;
1196                 }
1197             }
1198             else
1199             {
1200                 /* Empty else */
1201             }
1202         }
1203     }
1204     else
1205     {
1206         /* Empty else */
1207     }
1208 }
1209 
1210 #if defined(FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ) && FSL_DRIVER_TRANSFER_DOUBLE_WEAK_IRQ
1211 #if defined(FLEXSPI)
1212 void FLEXSPI_DriverIRQHandler(void);
1213 void FLEXSPI_DriverIRQHandler(void)
1214 {
1215     s_flexspiIsr(FLEXSPI, s_flexspiHandle[0]);
1216     SDK_ISR_EXIT_BARRIER;
1217 }
1218 #endif
1219 
1220 #if defined(FLEXSPI0)
1221 void FLEXSPI0_DriverIRQHandler(void);
1222 void FLEXSPI0_DriverIRQHandler(void)
1223 {
1224     s_flexspiIsr(FLEXSPI0, s_flexspiHandle[0]);
1225     SDK_ISR_EXIT_BARRIER;
1226 }
1227 #endif
1228 #if defined(FLEXSPI1)
1229 void FLEXSPI1_DriverIRQHandler(void);
1230 void FLEXSPI1_DriverIRQHandler(void)
1231 {
1232     s_flexspiIsr(FLEXSPI1, s_flexspiHandle[1]);
1233     SDK_ISR_EXIT_BARRIER;
1234 }
1235 #endif
1236 
1237 #if defined(LSIO__FLEXSPI0)
1238 void LSIO_OCTASPI0_INT_DriverIRQHandler(void);
1239 void LSIO_OCTASPI0_INT_DriverIRQHandler(void)
1240 {
1241     s_flexspiIsr(LSIO__FLEXSPI0, s_flexspiHandle[0]);
1242     SDK_ISR_EXIT_BARRIER;
1243 }
1244 #endif
1245 #if defined(LSIO__FLEXSPI1)
1246 void LSIO_OCTASPI1_INT_DriverIRQHandler(void);
1247 void LSIO_OCTASPI1_INT_DriverIRQHandler(void)
1248 {
1249     s_flexspiIsr(LSIO__FLEXSPI1, s_flexspiHandle[1]);
1250     SDK_ISR_EXIT_BARRIER;
1251 }
1252 #endif
1253 
1254 #if defined(FSL_FEATURE_FLEXSPI_HAS_SHARED_IRQ0_IRQ1) && FSL_FEATURE_FLEXSPI_HAS_SHARED_IRQ0_IRQ1
1255 
1256 void FLEXSPI0_FLEXSPI1_DriverIRQHandler(void);
1257 void FLEXSPI0_FLEXSPI1_DriverIRQHandler(void)
1258 {
1259     /* If handle is registered, treat the transfer function is enabled. */
1260     if (NULL != s_flexspiHandle[0])
1261     {
1262         s_flexspiIsr(FLEXSPI0, s_flexspiHandle[0]);
1263     }
1264     if (NULL != s_flexspiHandle[1])
1265     {
1266         s_flexspiIsr(FLEXSPI1, s_flexspiHandle[1]);
1267     }
1268 }
1269 #endif
1270 
1271 #endif