Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:05

0001 /******************************************************************************
0002 * Copyright (C) 2014 - 2022 Xilinx, Inc.  All rights reserved.
0003 * SPDX-License-Identifier: MIT
0004 ******************************************************************************/
0005 
0006 
0007 /*****************************************************************************/
0008 /**
0009  *
0010  * @file xqspipsu.c
0011  * @addtogroup Overview
0012  * @{
0013  *
0014  * This file implements the functions required to use the QSPIPSU hardware to
0015  * perform a transfer. These are accessible to the user via xqspipsu.h.
0016  *
0017  * <pre>
0018  * MODIFICATION HISTORY:
0019  *
0020  * Ver   Who Date     Changes
0021  * ----- --- -------- -----------------------------------------------
0022  * 1.0   hk  08/21/14 First release
0023  *       sk  03/13/15 Added IO mode support.
0024  *       hk  03/18/15 Switch to I/O mode before clearing RX FIFO.
0025  *                    Clear and disable DMA interrupts/status in abort.
0026  *                    Use DMA DONE bit instead of BUSY as recommended.
0027  *       sk  04/24/15 Modified the code according to MISRAC-2012.
0028  *       sk  06/17/15 Removed NULL checks for Rx/Tx buffers. As
0029  *                    writing/reading from 0x0 location is permitted.
0030  * 1.1   sk  04/12/16 Added debug message prints.
0031  * 1.2 nsk 07/01/16 Changed XQspiPsu_Select to support GQSPI and LQSPI
0032  *                  selection.
0033  *       rk  07/15/16 Added support for TapDelays at different frequencies.
0034  *     nsk 08/05/16 Added example support PollData and PollTimeout
0035  * 1.3 nsk 09/16/16 Update PollData and PollTimeout support for dual
0036  *                  parallel configurations, modified XQspiPsu_PollData()
0037  *                  and XQspiPsu_Create_PollConfigData()
0038  * 1,5 nsk 08/14/17 Added CCI support
0039  * 1.7 tjs 01/16/18 Removed the check for DMA MSB to be written. (CR#992560)
0040  * 1.7 tjs 01/17/18 Added a support to toggle WP pin of the flash.
0041  * 1.7 tjs 03/14/18 Added support in EL1 NS mode (CR#974882)
0042  * 1.8 tjs 06/26/18 Added an example for accessing 64bit dma within
0043  *                  32 bit application. CR#1004701
0044  * 1.8 tjs 06/26/18 Removed checkpatch warnings.
0045  * 1.8 tjs 07/09/18 Fixed cppcheck and doxygen warnings. (CR#1006336)
0046  * 1.8 tjs 07/18/18 Setup64BRxDma() should be called only if the RxAddress is
0047  *                  greater than 32 bit address space. (CR#1006862)
0048  * 1.8 tjs 09/06/18 Fixed the code in XQspiPsu_GenFifoEntryData() for data
0049  *                  transfer length up to 255 for reducing the extra loop.
0050  * 1.8  mus 11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
0051  * 1.9 tjs 11/22/17 Added the check for A72 and R5 processors (CR-987075)
0052  * 1.9 tjs 04/17/18 Updated register addresses as per the latest revision
0053  *          of versal (CR#999610)
0054  * 1.9  aru 01/17/19 Fixes violations according to MISRAC-2012
0055  *                  in safety mode and modified the code such as
0056  *                  Added UNITPTR inplace of INTPTR,Declared the pointer param
0057  *          as Pointer to const .
0058  * 1.9  nsk 02/01/19 Clear DMA_DST_ADDR_MSB register on 32bit machine, if the
0059  *           address is of only 32bit (CR#1020031)
0060  * 1.9  nsk 02/01/19 Added QSPI idling support.
0061  * 1.9  rama 03/13/19 Fixed MISRA violations related to UR data anamoly,
0062  *                    expression is not a boolean
0063  * 1.9  nsk 03/27/19 Update 64bit dma support
0064  * 1.10 sk  08/20/19 Fixed issues in poll timeout feature.
0065  * 1.11 akm 02/19/20 Added XQspiPsu_StartDmaTransfer() and XQspiPsu_CheckDmaDone()
0066  *           APIs for non-blocking transfer.
0067  * 1.11 sd  01/02/20 Added clocking support
0068  * 1.11 akm 03/09/20 Reorganize the source code, enable qspi controller and
0069  *           interrupts in XQspiPsu_CfgInitialize() API.
0070  * 1.11 akm 03/26/20 Fixed issue by updating XQspiPsu_CfgInitialize to return
0071  *           XST_DEVICE_IS_STARTED instead of asserting, when the
0072  *           instance is already configured.
0073  * 1.13 akm 01/04/21 Fix MISRA-C violations.
0074  * 1.14 akm 06/24/21 Allow enough time for the controller to reset the FIFOs.
0075  * 1.14 akm 08/12/21 Perform Dcache invalidate at the end of the DMA transfer.
0076  * 1.15 akm 10/21/21 Fix MISRA-C violations.
0077  *
0078  * </pre>
0079  *
0080  ******************************************************************************/
0081 
0082 /***************************** Include Files *********************************/
0083 
0084 #include "xqspipsu.h"
0085 #include "xqspipsu_control.h"
0086 #ifndef __rtems__
0087 #include "sleep.h"
0088 #else
0089 #include <bsp/xil-compat.h>
0090 #include <rtems/rtems/cache.h>
0091 #endif
0092 
0093 /************************** Constant Definitions *****************************/
0094 #define MAX_DELAY_CNT   10000000U   /**< Max delay count */
0095 
0096 /**************************** Type Definitions *******************************/
0097 
0098 /***************** Macros (Inline Functions) Definitions *********************/
0099 
0100 /************************** Function Prototypes ******************************/
0101 
0102 /************************** Variable Definitions *****************************/
0103 
0104 /*****************************************************************************/
0105 /**
0106  *
0107  * Initializes a specific XQspiPsu instance as such the driver is ready to use.
0108  *
0109  *
0110  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0111  * @param   ConfigPtr is a reference to a structure containing information
0112  *      about a specific QSPIPSU device. This function initializes an
0113  *      InstancePtr object for a specific device specified by the
0114  *      contents of Config.
0115  * @param   EffectiveAddr is the device base address in the virtual memory
0116  *      address space. The caller is responsible for keeping the address
0117  *      mapping from EffectiveAddr to the device physical base address
0118  *      unchanged once this function is invoked. Unexpected errors may
0119  *      occur if the address mapping changes after this function is
0120  *      called. If address translation is not used, use
0121  *      ConfigPtr->Config.BaseAddress for this device.
0122  *
0123  * @return
0124  *      - XST_SUCCESS if successful.
0125  *      - XST_DEVICE_IS_STARTED if the device is already started.
0126  *      It must be stopped to re-initialize.
0127  *
0128  * @note    None.
0129  *
0130  ******************************************************************************/
0131 s32 XQspiPsu_CfgInitialize(XQspiPsu *InstancePtr,
0132                const XQspiPsu_Config *ConfigPtr,
0133                UINTPTR EffectiveAddr)
0134 {
0135     Xil_AssertNonvoid(InstancePtr != NULL);
0136     Xil_AssertNonvoid(ConfigPtr != NULL);
0137     s32 Status;
0138 
0139     /*
0140      * If the device is busy, disallow the initialize and return a status
0141      * indicating it is already started. This allows the user to stop the
0142      * device and re-initialize, but prevents a user from inadvertently
0143      * initializing. This assumes the busy flag is cleared at startup.
0144      */
0145     if ((InstancePtr->IsBusy == (u32)TRUE) ||
0146         (InstancePtr->IsReady == XIL_COMPONENT_IS_READY)) {
0147         Status = (s32)XST_DEVICE_IS_STARTED;
0148     } else {
0149         /* Set some default values. */
0150         InstancePtr->IsBusy = (u32)FALSE;
0151         InstancePtr->Config.BaseAddress =
0152             EffectiveAddr + XQSPIPSU_OFFSET;
0153         InstancePtr->Config.ConnectionMode = ConfigPtr->ConnectionMode;
0154         InstancePtr->StatusHandler = StubStatusHandler;
0155         InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
0156         InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
0157 #if defined  (XCLOCKING)
0158         InstancePtr->Config.RefClk = ConfigPtr->RefClk;
0159 #endif
0160         InstancePtr->Config.IsCacheCoherent =
0161             ConfigPtr->IsCacheCoherent;
0162         /* Other instance variable initializations */
0163         InstancePtr->SendBufferPtr = NULL;
0164         InstancePtr->RecvBufferPtr = NULL;
0165         InstancePtr->GenFifoBufferPtr = NULL;
0166         InstancePtr->TxBytes = 0;
0167         InstancePtr->RxBytes = 0;
0168         InstancePtr->GenFifoEntries = 0;
0169         InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
0170         InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
0171         InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
0172         InstancePtr->IsUnaligned = 0;
0173         InstancePtr->IsManualstart = (u8)TRUE;
0174 
0175         /* Select QSPIPSU */
0176         XQspiPsu_Select(InstancePtr, XQSPIPSU_SEL_GQSPI_MASK);
0177         /*
0178          * Reset the QSPIPSU device to get it into its initial state.
0179          * It is expected that device configuration will take place
0180          * after this initialization is done, but before the device
0181          * is started.
0182          */
0183         XQspiPsu_Reset(InstancePtr);
0184         /* Enable */
0185         XQspiPsu_Enable(InstancePtr);
0186 
0187         InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
0188 
0189         Status = (s32)XST_SUCCESS;
0190     }
0191 
0192     return Status;
0193 }
0194 
0195 /*****************************************************************************/
0196 /**
0197  *
0198  * Stops the transfer of data to internal DST FIFO from stream interface and
0199  * also stops the issuing of new write commands to memory.
0200  *
0201  * By calling this API, any ongoing Dma transfers will be paused and DMA will
0202  * not issue AXI write commands to memory
0203  *
0204  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0205  *
0206  * @return  None.
0207  *
0208  * @note    None.
0209  *
0210  ******************************************************************************/
0211 void XQspiPsu_Idle(const XQspiPsu *InstancePtr)
0212 {
0213     u32 RegEn;
0214     u32 DmaStatus;
0215 
0216     Xil_AssertVoid(InstancePtr != NULL);
0217     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0218 
0219     /* Check for QSPI enable */
0220     RegEn = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0221             XQSPIPSU_EN_OFFSET);
0222     if ((RegEn & XQSPIPSU_EN_MASK) != 0U) {
0223         DmaStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0224                 XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET);
0225         DmaStatus |= XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_STRM_MASK;
0226         DmaStatus |= XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_MEM_MASK;
0227         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0228                 XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET, DmaStatus);
0229     }
0230 #if defined  (XCLOCKING)
0231     Xil_ClockDisable(InstancePtr->Config.RefClk);
0232 #endif
0233 }
0234 
0235 /*****************************************************************************/
0236 /**
0237  *
0238  * Resets the QSPIPSU device. Reset must only be called after the driver has
0239  * been initialized. Any data transfer that is in progress is aborted.
0240  *
0241  * The upper layer software is responsible for re-configuring (if necessary)
0242  * and restarting the QSPIPSU device after the reset.
0243  *
0244  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0245  *
0246  * @return  None.
0247  *
0248  * @note    None.
0249  *
0250  ******************************************************************************/
0251 void XQspiPsu_Reset(XQspiPsu *InstancePtr)
0252 {
0253     Xil_AssertVoid(InstancePtr != NULL);
0254 #ifdef DEBUG
0255     xil_printf("\nXQspiPsu_Reset\r\n");
0256 #endif
0257 
0258     /* Abort any transfer that is in progress */
0259     XQspiPsu_Abort(InstancePtr);
0260 
0261     /* Default value to config register */
0262     XQspiPsu_SetDefaultConfig(InstancePtr);
0263 
0264 }
0265 
0266 /*****************************************************************************/
0267 /**
0268  *
0269  * Aborts a transfer in progress.
0270  *
0271  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0272  *
0273  * @return  None.
0274  *
0275  * @note    None.
0276  *
0277  ******************************************************************************/
0278 void XQspiPsu_Abort(XQspiPsu *InstancePtr)
0279 {
0280     u32 IntrStatus, ConfigReg, FifoStatus;
0281     u32 DelayCount = 0U;
0282 
0283 #ifdef __rtems__
0284     u32 FifoStatusMask = XQSPIPSU_ISR_RXEMPTY_MASK;
0285     FifoStatusMask |= XQSPIPSU_ISR_TXEMPTY_MASK;
0286     FifoStatusMask |= XQSPIPSU_ISR_GENFIFOEMPTY_MASK;
0287 #endif
0288 
0289     Xil_AssertVoid(InstancePtr != NULL);
0290 #ifdef DEBUG
0291     xil_printf("\nXQspiPsu_Abort\r\n");
0292 #endif
0293     IntrStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0294                     XQSPIPSU_ISR_OFFSET);
0295 
0296     /* Clear and disable interrupts */
0297     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0298         XQSPIPSU_ISR_OFFSET, IntrStatus | XQSPIPSU_ISR_WR_TO_CLR_MASK);
0299     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0300             XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
0301         XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0302                 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET));
0303     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0304             XQSPIPSU_QSPIDMA_DST_STS_OFFSET,
0305             XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0306                 XQSPIPSU_QSPIDMA_DST_STS_OFFSET) |
0307                 XQSPIPSU_QSPIDMA_DST_STS_WTC);
0308     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0309         XQSPIPSU_IDR_OFFSET, XQSPIPSU_IDR_ALL_MASK);
0310     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0311             XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
0312             XQSPIPSU_QSPIDMA_DST_INTR_ALL_MASK);
0313 
0314     /*
0315      * Clear GEN FIFO, TX FIFO & RX FIFO. Switch to IO mode to Clear
0316      * RX FIFO. This is because of DMA behaviour where it waits on
0317      * RX empty and goes busy assuming there is data to be transferred
0318      * even if there is no request.
0319      */
0320     ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0321                 XQSPIPSU_CFG_OFFSET);
0322     ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
0323     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0324             XQSPIPSU_CFG_OFFSET, ConfigReg);
0325 
0326     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0327               XQSPIPSU_FIFO_CTRL_OFFSET,
0328               XQSPIPSU_FIFO_CTRL_RST_TX_FIFO_MASK |
0329               XQSPIPSU_FIFO_CTRL_RST_GEN_FIFO_MASK |
0330               XQSPIPSU_FIFO_CTRL_RST_RX_FIFO_MASK);
0331     /*
0332      * QSPI Controller takes few clock cycles to update the RX_FIFO_Empty,
0333      * TX_FIFO_Empty and GEN_FIFO_Empty status bit. Checking the GQSPI FIFO
0334      * Control register bits gives enough time for the QSPI controller to
0335      * update the status bit. The opeartion timesout, if the status bit are
0336      * not updated after 10secs.
0337      */
0338 
0339     FifoStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0340 #ifdef __rtems__
0341                     XQSPIPSU_ISR_OFFSET) & FifoStatusMask;
0342     while(FifoStatus != FifoStatusMask) {
0343 #else
0344                     XQSPIPSU_FIFO_CTRL_OFFSET);
0345     while(FifoStatus != 0U) {
0346 #endif
0347         if (DelayCount == MAX_DELAY_CNT) {
0348 #ifdef DEBUG
0349             xil_printf("Timeout error, FIFO reset failed.\r\n");
0350 #endif
0351         } else {
0352             /* Wait for 1 usec */
0353             usleep(1);
0354             DelayCount++;
0355             FifoStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0356 #ifdef __rtems__
0357                             XQSPIPSU_ISR_OFFSET) & FifoStatusMask;
0358 #else
0359                             XQSPIPSU_FIFO_CTRL_OFFSET);
0360 #endif
0361         }
0362     }
0363 
0364     if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
0365         ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
0366         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0367                 XQSPIPSU_CFG_OFFSET, ConfigReg);
0368     }
0369 
0370 
0371     InstancePtr->TxBytes = 0;
0372     InstancePtr->RxBytes = 0;
0373     InstancePtr->GenFifoEntries = 0;
0374     InstancePtr->IsBusy = (u32)FALSE;
0375 }
0376 
0377 /*****************************************************************************/
0378 /**
0379  * This is the handler for polling functionality of controller. It reads data
0380  * from RXFIFO, since when data from the flash device (status data) matched
0381  * with configured value in poll_cfg, then controller writes the matched data
0382  * into RXFIFO.
0383  *
0384  *
0385  * @param       InstancePtr is a pointer to the XQspiPsu instance.
0386  * @param       StatusReg is the Interrupt status Register value.
0387  *
0388  * @return  None.
0389  *
0390  * @note    None.
0391  *
0392  ******************************************************************************/
0393 void XQspiPsu_PollDataHandler(XQspiPsu *InstancePtr, u32 StatusReg)
0394 {
0395 
0396     Xil_AssertVoid(InstancePtr != NULL);
0397     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0398 #ifdef DEBUG
0399     xil_printf("\nXQspiPsu_PollDataHandler\r\n");
0400 #endif
0401 
0402     if ((StatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK) != (u32)FALSE) {
0403         /*
0404          * Read data from RXFIFO, since when data from the
0405          * flash device (status data) matched with configured
0406          * value in poll_cfg, then controller writes the
0407          * matched data into RXFIFO.
0408          */
0409         (void)XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0410                 XQSPIPSU_RXD_OFFSET);
0411 
0412         InstancePtr->StatusHandler(InstancePtr->StatusRef,
0413                 XST_SPI_POLL_DONE, 0);
0414     }
0415     if ((StatusReg & XQSPIPSU_ISR_POLL_TIME_EXPIRE_MASK) != (u32)FALSE) {
0416             InstancePtr->StatusHandler(InstancePtr->StatusRef,
0417                             XST_FLASH_TIMEOUT_ERROR, 0);
0418     }
0419     XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_IDR_OFFSET,
0420             (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
0421             (u32)XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK);
0422     InstancePtr->IsBusy = (u32)FALSE;
0423     if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
0424             XQspiPsu_SetReadMode(InstancePtr, XQSPIPSU_READMODE_DMA);
0425     }
0426     /* De-select slave */
0427     XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
0428     XQspiPsu_ManualStartEnable(InstancePtr);
0429 }
0430 
0431 /*****************************************************************************/
0432 /**
0433  *
0434  * This function performs a transfer on the bus in polled mode. The messages
0435  * passed are all transferred on the bus between one CS assert and de-assert.
0436  *
0437  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0438  * @param   Msg is a pointer to the structure containing transfer data.
0439  * @param   NumMsg is the number of messages to be transferred.
0440  *
0441  * @return
0442  *      - XST_SUCCESS if successful.
0443  *      - XST_FAILURE if transfer fails.
0444  *      - XST_DEVICE_BUSY if a transfer is already in progress.
0445  *
0446  * @note    None.
0447  *
0448  ******************************************************************************/
0449 s32 XQspiPsu_PolledTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
0450                 u32 NumMsg)
0451 {
0452     s32 Index;
0453     u32 QspiPsuStatusReg;
0454     u32 IOPending = (u32)FALSE;
0455     u32 DmaIntrSts;
0456     s32 Status;
0457 
0458     Xil_AssertNonvoid(InstancePtr != NULL);
0459     Xil_AssertNonvoid(Msg != NULL);
0460     Xil_AssertNonvoid(NumMsg > 0U);
0461     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0462 
0463     for (Index = 0; Index < (s32)NumMsg; Index++) {
0464         Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
0465 #ifdef __rtems__
0466         if (Msg[Index].TxBfrPtr != NULL) {
0467             rtems_cache_flush_multiple_data_lines(Msg[Index].TxBfrPtr, Msg[Index].ByteCount);
0468         }
0469 #endif
0470     }
0471 #ifdef __rtems__
0472     rtems_cache_flush_multiple_data_lines(Msg, NumMsg * sizeof(*Msg));
0473 #endif
0474 
0475     /*
0476      * Check whether there is another transfer in progress.
0477      * Not thread-safe
0478      */
0479     if (InstancePtr->IsBusy == (u32)TRUE) {
0480         Status = (s32)XST_DEVICE_BUSY;
0481         goto END;
0482     }
0483     /* Check for ByteCount upper limit - 2^28 for DMA */
0484     for (Index = 0; Index < (s32)NumMsg; Index++) {
0485         if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
0486                 ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
0487             Status = (s32)XST_FAILURE;
0488             goto END;
0489         }
0490     }
0491     /*
0492      * Set the busy flag, which will be cleared when the transfer is
0493      * entirely done.
0494      */
0495     InstancePtr->IsBusy = (u32)TRUE;
0496 
0497 #if defined  (XCLOCKING)
0498     Xil_ClockEnable(InstancePtr->Config.RefClk);
0499 #endif
0500     /* Select slave */
0501     XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
0502 
0503     /* list */
0504     Index = 0;
0505     while (Index < (s32)NumMsg) {
0506         XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[Index]);
0507         XQspiPsu_ManualStartEnable(InstancePtr);
0508         /* Use thresholds here */
0509         /* If there is more data to be transmitted */
0510         do {
0511             QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0512                         XQSPIPSU_ISR_OFFSET);
0513             /* Transmit more data if left */
0514             if (((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != (u32)FALSE) &&
0515                 ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
0516                 (InstancePtr->TxBytes > 0)) {
0517                 XQspiPsu_FillTxFifo(InstancePtr, &Msg[Index],
0518                         (u32)XQSPIPSU_TXD_DEPTH);
0519             }
0520 
0521             if ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE) {
0522                 if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
0523                     /* Check if DMA RX is complete and update RxBytes */
0524                     DmaIntrSts = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0525                                 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
0526                     if ((DmaIntrSts &
0527                         XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != (u32)FALSE) {
0528                         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0529                                 XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET, DmaIntrSts);
0530                         /* DMA transfer done, Invalidate Data Cache */
0531                         if (!((Msg[Index].RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
0532                             (Msg[Index].Xfer64bit != (u8)0U)) &&
0533                             (InstancePtr->Config.IsCacheCoherent == 0U)) {
0534                             Xil_DCacheInvalidateRange((INTPTR)Msg[Index].RxBfrPtr,
0535                                         (INTPTR)Msg[Index].ByteCount);
0536                         }
0537                         IOPending = XQspiPsu_SetIOMode(InstancePtr, &Msg[Index]);
0538                         InstancePtr->RxBytes = 0;
0539                         if (IOPending == (u32)TRUE) {
0540                             break;
0541                         }
0542                     }
0543                 } else {
0544                     XQspiPsu_IORead(InstancePtr, &Msg[Index], QspiPsuStatusReg);
0545                 }
0546             }
0547         } while (((QspiPsuStatusReg &
0548             XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE) ||
0549             (InstancePtr->TxBytes != 0) ||
0550             ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) == (u32)FALSE) ||
0551             (InstancePtr->RxBytes != 0));
0552 
0553         if ((InstancePtr->IsUnaligned != 0) && (IOPending == (u32)FALSE)) {
0554             InstancePtr->IsUnaligned = 0;
0555             XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
0556                     (XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) |
0557                             XQSPIPSU_CFG_MODE_EN_DMA_MASK));
0558             InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
0559         }
0560         if (IOPending == (u32)TRUE) {
0561             IOPending = (u32)FALSE;
0562         } else {
0563             Index++;
0564         }
0565     }
0566     /* De-select slave */
0567     XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
0568     XQspiPsu_ManualStartEnable(InstancePtr);
0569     do {
0570         QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
0571     } while ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE);
0572 
0573     /* Clear the busy flag. */
0574     InstancePtr->IsBusy = (u32)FALSE;
0575 
0576     Status = (s32)XST_SUCCESS;
0577 
0578 #if defined  (XCLOCKING)
0579     Xil_ClockDisable(InstancePtr->Config.RefClk);
0580 #endif
0581     END:
0582     return Status;
0583 }
0584 
0585 /*****************************************************************************/
0586 /**
0587  *
0588  * This function initiates a transfer on the bus and enables interrupts.
0589  * The transfer is completed by the interrupt handler. The messages passed are
0590  * all transferred on the bus between one CS assert and de-assert.
0591  *
0592  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0593  * @param   Msg is a pointer to the structure containing transfer data.
0594  * @param   NumMsg is the number of messages to be transferred.
0595  *
0596  * @return
0597  *      - XST_SUCCESS if successful.
0598  *      - XST_FAILURE if transfer fails.
0599  *      - XST_DEVICE_BUSY if a transfer is already in progress.
0600  *
0601  * @note    None.
0602  *
0603  ******************************************************************************/
0604 s32 XQspiPsu_InterruptTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
0605                 u32 NumMsg)
0606 {
0607     s32 Index;
0608     s32 Status;
0609 
0610     Xil_AssertNonvoid(InstancePtr != NULL);
0611     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0612 
0613     for (Index = 0; Index < (s32)NumMsg; Index++)
0614 #ifdef __rtems__
0615     {
0616 #endif
0617         Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
0618 #ifdef __rtems__
0619         if (Msg[Index].TxBfrPtr != NULL) {
0620             rtems_cache_flush_multiple_data_lines(Msg[Index].TxBfrPtr, Msg[Index].ByteCount);
0621         }
0622     }
0623     rtems_cache_flush_multiple_data_lines(Msg, NumMsg * sizeof(*Msg));
0624 #endif
0625 
0626     /*
0627      * Check whether there is another transfer in progress.
0628      * Not thread-safe
0629      */
0630     if (InstancePtr->IsBusy == (u32)TRUE) {
0631             Status = (s32)XST_DEVICE_BUSY;
0632             goto END;
0633     }
0634 #if defined  (XCLOCKING)
0635     Xil_ClockEnable(InstancePtr->Config.RefClk);
0636 #endif
0637 
0638     if ((Msg[0].Flags & XQSPIPSU_MSG_FLAG_POLL) != (u32)FALSE) {
0639         InstancePtr->IsBusy = (u32)TRUE;
0640         XQspiPsu_PollDataConfig(InstancePtr, Msg);
0641     } else {
0642         /* Check for ByteCount upper limit - 2^28 for DMA */
0643         for (Index = 0; Index < (s32)NumMsg; Index++) {
0644             if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
0645                     ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
0646                 Status = (s32)XST_FAILURE;
0647                 goto END;
0648             }
0649         }
0650         /*
0651          * Set the busy flag, which will be cleared when the transfer is
0652          * entirely done.
0653          */
0654         InstancePtr->IsBusy = (u32)TRUE;
0655 
0656         InstancePtr->Msg = Msg;
0657         InstancePtr->NumMsg = (s32)NumMsg;
0658         InstancePtr->MsgCnt = 0;
0659 
0660         /* Select slave */
0661         XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
0662         /* This might not work if not manual start */
0663         /* Put first message in FIFO along with the above slave select */
0664         XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[0]);
0665         XQspiPsu_ManualStartEnable(InstancePtr);
0666 
0667         /* Enable interrupts */
0668         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_IER_OFFSET,
0669             (u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
0670             (u32)XQSPIPSU_IER_TXEMPTY_MASK |
0671             (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
0672             (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
0673             (u32)XQSPIPSU_IER_RXEMPTY_MASK);
0674 
0675         if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
0676             XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_EN_OFFSET,
0677                     XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
0678         }
0679     }
0680     Status = (s32)XST_SUCCESS;
0681 
0682     END:
0683     return Status;
0684 }
0685 
0686 /*****************************************************************************/
0687 /**
0688  *
0689  * Handles interrupt based transfers by acting on GENFIFO and DMA interurpts.
0690  *
0691  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0692  *
0693  * @return
0694  *      - XST_SUCCESS if successful.
0695  *      - XST_FAILURE if transfer fails.
0696  *
0697  * @note    None.
0698  *
0699  ******************************************************************************/
0700 s32 XQspiPsu_InterruptHandler(XQspiPsu *InstancePtr)
0701 {
0702     u32 QspiPsuStatusReg, DmaIntrStatusReg = 0;
0703     XQspiPsu_Msg *Msg;
0704     s32 NumMsg;
0705     s32 MsgCnt;
0706     u8 DeltaMsgCnt = 0;
0707     u32 TxRxFlag;
0708 
0709     Xil_AssertNonvoid(InstancePtr != NULL);
0710     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0711     Xil_AssertNonvoid(InstancePtr->NumMsg > 0);
0712     Xil_AssertNonvoid(InstancePtr->Msg != NULL);
0713 
0714     Msg = InstancePtr->Msg;
0715     NumMsg = InstancePtr->NumMsg;
0716     MsgCnt = InstancePtr->MsgCnt;
0717     TxRxFlag = Msg[MsgCnt].Flags;
0718 
0719     /* QSPIPSU Intr cleared on read */
0720     QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
0721     if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
0722         /* DMA Intr write to clear */
0723         DmaIntrStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
0724                     XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
0725         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
0726                     DmaIntrStatusReg);
0727     }
0728     if (((DmaIntrStatusReg & XQSPIPSU_QSPIDMA_DST_INTR_ERR_MASK) != (u32)FALSE)) {
0729         /* Call status handler to indicate error */
0730         InstancePtr->StatusHandler(InstancePtr->StatusRef,
0731                 XST_SPI_COMMAND_ERROR, 0);
0732     }
0733     /* Fill more data to be txed if required */
0734     if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
0735         ((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != (u32)FALSE) &&
0736         (InstancePtr->TxBytes > 0)) {
0737         XQspiPsu_FillTxFifo(InstancePtr, &Msg[MsgCnt], (u32)XQSPIPSU_TXD_DEPTH);
0738     }
0739     /*
0740      * Check if the entry is ONLY TX and increase MsgCnt.
0741      * This is to allow TX and RX together in one entry - corner case.
0742      */
0743     if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
0744         ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) != (u32)FALSE) &&
0745         ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != (u32)FALSE) &&
0746         (InstancePtr->TxBytes == 0) &&
0747         ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE)) {
0748         MsgCnt += 1;
0749         DeltaMsgCnt = 1U;
0750     }
0751 
0752     if ((MsgCnt < NumMsg) &&
0753                         ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
0754         if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
0755             if ((DmaIntrStatusReg &
0756                     XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != (u32)FALSE) {
0757                 /* DMA transfer done, Invalidate Data Cache */
0758                 if (!((Msg[MsgCnt].RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
0759                         (Msg[MsgCnt].Xfer64bit != (u8)0U)) &&
0760                         (InstancePtr->Config.IsCacheCoherent == 0U)) {
0761                     Xil_DCacheInvalidateRange((INTPTR)Msg[MsgCnt].RxBfrPtr, (INTPTR)Msg[MsgCnt].ByteCount);
0762                 }
0763                 if (XQspiPsu_SetIOMode(InstancePtr, &Msg[MsgCnt]) == (u32)TRUE) {
0764                     XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[MsgCnt]);
0765                     XQspiPsu_ManualStartEnable(InstancePtr);
0766                 } else {
0767                     InstancePtr->RxBytes = 0;
0768                     MsgCnt += 1;
0769                     DeltaMsgCnt = 1U;
0770                 }
0771             }
0772         } else {
0773             if (InstancePtr->RxBytes != 0) {
0774                 XQspiPsu_IORead(InstancePtr, &Msg[MsgCnt], QspiPsuStatusReg);
0775                 if (InstancePtr->RxBytes == 0) {
0776                     MsgCnt += 1;
0777                     DeltaMsgCnt = 1U;
0778                 }
0779             }
0780         }
0781     }
0782 
0783     /*
0784      * Dummy byte transfer
0785      * MsgCnt < NumMsg check is to ensure is it a valid dummy cycle message
0786      * If one of the above conditions increased MsgCnt, then
0787      * the new message is yet to be placed in the FIFO; hence !DeltaMsgCnt.
0788      */
0789     if ((MsgCnt < NumMsg) && (DeltaMsgCnt == (u8)FALSE) &&
0790         ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE) &&
0791         ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) == (u32)FALSE) &&
0792         ((TxRxFlag & XQSPIPSU_MSG_FLAG_POLL) == (u32)FALSE) &&
0793         ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != (u32)FALSE)) {
0794         MsgCnt += 1;
0795         DeltaMsgCnt = 1U;
0796     }
0797     InstancePtr->MsgCnt = MsgCnt;
0798     /*
0799      * DeltaMsgCnt is to handle conditions where genfifo empty can be set
0800      * while tx is still not empty or rx dma is not yet done.
0801      * MsgCnt > NumMsg indicates CS de-assert entry was also executed.
0802      */
0803     if (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != (u32)FALSE) &&
0804         ((DeltaMsgCnt != (u8)FALSE) || (MsgCnt > NumMsg))) {
0805         if (MsgCnt < NumMsg) {
0806             if (InstancePtr->IsUnaligned != 0) {
0807                 InstancePtr->IsUnaligned = 0;
0808                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0809                     XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
0810                     InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) |
0811                     XQSPIPSU_CFG_MODE_EN_DMA_MASK));
0812                 InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
0813             }
0814             /* This might not work if not manual start */
0815             XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[MsgCnt]);
0816             XQspiPsu_ManualStartEnable(InstancePtr);
0817         } else if (MsgCnt == NumMsg) {
0818             /* This is just to keep track of the de-assert entry */
0819             MsgCnt += 1;
0820             InstancePtr->MsgCnt = MsgCnt;
0821             /* De-select slave */
0822             XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
0823             XQspiPsu_ManualStartEnable(InstancePtr);
0824         } else {
0825             /* Disable interrupts */
0826             XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_IDR_OFFSET,
0827                     (u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
0828                     (u32)XQSPIPSU_IER_TXEMPTY_MASK |
0829                     (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
0830                     (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
0831                     (u32)XQSPIPSU_IER_RXEMPTY_MASK);
0832             if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
0833                 XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0834                     XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
0835                     XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
0836             }
0837             /* Clear the busy flag. */
0838             InstancePtr->IsBusy = (u32)FALSE;
0839 #if defined  (XCLOCKING)
0840             Xil_ClockDisable(InstancePtr->Config.RefClk);
0841 #endif
0842             /* Call status handler to indicate completion */
0843             InstancePtr->StatusHandler(InstancePtr->StatusRef,
0844                         XST_SPI_TRANSFER_DONE, 0);
0845         }
0846     }
0847     if ((TxRxFlag & XQSPIPSU_MSG_FLAG_POLL) != (u32)FALSE) {
0848         XQspiPsu_PollDataHandler(InstancePtr, QspiPsuStatusReg);
0849     }
0850     return (s32)XST_SUCCESS;
0851 }
0852 
0853 /*****************************************************************************/
0854 /**
0855  *
0856  * Sets the status callback function, the status handler, which the driver
0857  * calls when it encounters conditions that should be reported to upper
0858  * layer software. The handler executes in an interrupt context, so it must
0859  * minimize the amount of processing performed. One of the following status
0860  * events is passed to the status handler.
0861  *
0862  * <pre>
0863  *
0864  * XST_SPI_TRANSFER_DONE        The requested data transfer is done
0865  *
0866  * XST_SPI_TRANSMIT_UNDERRUN    As a slave device, the master clocked data
0867  *              but there were none available in the transmit
0868  *              register/FIFO. This typically means the slave
0869  *              application did not issue a transfer request
0870  *              fast enough, or the processor/driver could not
0871  *              fill the transmit register/FIFO fast enough.
0872  *
0873  * XST_SPI_RECEIVE_OVERRUN  The QSPIPSU device lost data. Data was received
0874  *              but the receive data register/FIFO was full.
0875  *
0876  * </pre>
0877  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0878  * @param   CallBackRef is the upper layer callback reference passed back
0879  *      when the callback function is invoked.
0880  * @param   FuncPointer is the pointer to the callback function.
0881  *
0882  * @return  None.
0883  *
0884  * @note
0885  *
0886  * The handler is called within interrupt context, so it should do its work
0887  * quickly and queue potentially time-consuming work to a task-level thread.
0888  *
0889  ******************************************************************************/
0890 void XQspiPsu_SetStatusHandler(XQspiPsu *InstancePtr, void *CallBackRef,
0891                 XQspiPsu_StatusHandler FuncPointer)
0892 {
0893     Xil_AssertVoid(InstancePtr != NULL);
0894     Xil_AssertVoid(FuncPointer != NULL);
0895     Xil_AssertVoid(CallBackRef != NULL);
0896     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0897 
0898     InstancePtr->StatusHandler = FuncPointer;
0899     InstancePtr->StatusRef = CallBackRef;
0900 }
0901 
0902 /*****************************************************************************/
0903 /**
0904  * @brief
0905  * This API enables/ disables Write Protect pin on the flash parts.
0906  *
0907  * @param   InstancePtr is a pointer to the QSPIPSU driver component to use.
0908  *
0909  * @param   Toggle is a value of the GPIO pin
0910  *
0911  * @return  None
0912  *
0913  * @note    By default WP pin as per the QSPI controller is driven High
0914  *      which means no write protection. Calling this function once
0915  *      will enable the protection.
0916  *
0917  ******************************************************************************/
0918 void XQspiPsu_WriteProtectToggle(const XQspiPsu *InstancePtr, u32 Toggle)
0919 {
0920     Xil_AssertVoid(InstancePtr != NULL);
0921     Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0922     /* For Single and Stacked flash configuration with x1 or x2 mode*/
0923     if (InstancePtr->Config.ConnectionMode ==
0924         XQSPIPSU_CONNECTION_MODE_SINGLE) {
0925         /* Select slave */
0926         XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
0927 
0928         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
0929             XQSPIPSU_GPIO_OFFSET, Toggle);
0930 
0931     } else {
0932 #ifdef DEBUG
0933         xil_printf("Dual Parallel/Stacked configuration ");
0934         xil_printf("is not supported by this API\r\n");
0935 #endif
0936     }
0937 }
0938 
0939 /*****************************************************************************/
0940 /**
0941 *
0942 * This function start a DMA transfer.
0943 *
0944  * @param   InstancePtr is a pointer to the XQspiPsu instance.
0945  * @param   Msg is a pointer to the structure containing transfer data.
0946  * @param   NumMsg is the number of messages to be transferred.
0947  *
0948  * @return
0949  *      - XST_SUCCESS if successful.
0950  *      - XST_FAILURE if ByteCount is greater than
0951  *        XQSPIPSU_DMA_BYTES_MAX.
0952  *      - XST_DEVICE_BUSY if a transfer is already in progress.
0953  *
0954  * @note    None.
0955  *
0956 *
0957 ******************************************************************************/
0958 s32 XQspiPsu_StartDmaTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
0959                 u32 NumMsg)
0960 {
0961     s32 Index;
0962     u32 QspiPsuStatusReg = 0;
0963 
0964     Xil_AssertNonvoid(InstancePtr != NULL);
0965     Xil_AssertNonvoid(Msg != NULL);
0966     Xil_AssertNonvoid(NumMsg > 0U);
0967     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
0968     for (Index = 0; Index < (s32)NumMsg; Index++) {
0969         Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
0970     }
0971 
0972     /*
0973      * Check whether there is another transfer in progress.
0974      * Not thread-safe
0975      */
0976     if (InstancePtr->IsBusy == (u32)TRUE) {
0977         return (s32)XST_DEVICE_BUSY;
0978     }
0979 
0980     /* Check for ByteCount upper limit - 2^28 for DMA */
0981     for (Index = 0; Index < (s32)NumMsg; Index++) {
0982         if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
0983             ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
0984             return (s32)XST_FAILURE;
0985         }
0986     }
0987 
0988     /*
0989      * Set the busy flag, which will be cleared when the transfer is
0990      * entirely done.
0991      */
0992     InstancePtr->IsBusy = (u32)TRUE;
0993 
0994     /* Select slave */
0995     XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
0996     /* list */
0997     Index = 0;
0998     while (Index < (s32)NumMsg) {
0999         InstancePtr->Msg = &Msg[Index];
1000         XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[Index]);
1001         if (InstancePtr->IsManualstart == (u32)TRUE) {
1002 #ifdef DEBUG
1003             xil_printf("\nManual Start\r\n");
1004 #endif
1005             XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
1006                       XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
1007                       XQSPIPSU_CFG_OFFSET) |
1008                       XQSPIPSU_CFG_START_GEN_FIFO_MASK);
1009         }
1010         do {
1011             if((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
1012                ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
1013                 break;
1014             }
1015             QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
1016 
1017         } while (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE) ||
1018             (InstancePtr->TxBytes != 0) ||
1019             ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) == (u32)FALSE));
1020 
1021         if(InstancePtr->ReadMode == XQSPIPSU_READMODE_IO) {
1022             XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
1023                       XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
1024                       InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) |
1025                       XQSPIPSU_CFG_MODE_EN_DMA_MASK));
1026             InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
1027         }
1028         Index++;
1029     }
1030     return (s32)XST_SUCCESS;
1031 }
1032 
1033 /*****************************************************************************/
1034 /**
1035 *
1036 * This function check for DMA transfer complete.
1037 *
1038 * @param    InstancePtr is a pointer to the XQspiPsu instance.
1039 *
1040 * @return
1041 *       - XST_SUCCESS if DMA transfer complete.
1042 *       - XST_FAILURE if DMA transfer is not completed.
1043 *
1044 * @note     None.
1045 *
1046 ******************************************************************************/
1047 s32 XQspiPsu_CheckDmaDone(XQspiPsu *InstancePtr)
1048 {
1049     u32 QspiPsuStatusReg;
1050     u32 DmaIntrSts;
1051 
1052     Xil_AssertNonvoid(InstancePtr != NULL);
1053     Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
1054 
1055     DmaIntrSts = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
1056     if ((DmaIntrSts & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != (u32)FALSE) {
1057         XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET, DmaIntrSts);
1058         /* DMA transfer done, Invalidate Data Cache */
1059         if (!((InstancePtr->Msg->RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
1060             (InstancePtr->Msg->Xfer64bit != (u8)0U)) &&
1061             (InstancePtr->Config.IsCacheCoherent == 0U)) {
1062             Xil_DCacheInvalidateRange((INTPTR)InstancePtr->Msg->RxBfrPtr, (INTPTR)InstancePtr->RxBytes);
1063         }
1064         /* De-select slave */
1065         XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
1066         if (InstancePtr->IsManualstart == (u8)TRUE) {
1067 #ifdef DEBUG
1068             xil_printf("\nManual Start\r\n");
1069 #endif
1070             XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
1071                       XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) |
1072                       XQSPIPSU_CFG_START_GEN_FIFO_MASK);
1073         }
1074         do {
1075             QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
1076         } while ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE);
1077 
1078         /* Clear the busy flag. */
1079         InstancePtr->IsBusy = (u32)FALSE;
1080 
1081         return (s32)XST_SUCCESS;
1082     }
1083     else {
1084         return (s32)XST_FAILURE;
1085     }
1086 
1087 }
1088 /** @} */