]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/qspipsu_v1_7/src/xqspipsu.c
Update Zynq, MPSoc Cortex-A53 and MPSoc Cortex-R5 demo projects to build with the...
[freertos] / FreeRTOS / Demo / CORTEX_R5_UltraScale_MPSoC / RTOSDemo_R5_bsp / psu_cortexr5_0 / libsrc / qspipsu_v1_7 / src / xqspipsu.c
diff --git a/FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/qspipsu_v1_7/src/xqspipsu.c b/FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/qspipsu_v1_7/src/xqspipsu.c
new file mode 100644 (file)
index 0000000..60eee53
--- /dev/null
@@ -0,0 +1,1554 @@
+/******************************************************************************
+*
+* Copyright (C) 2014 Xilinx, Inc.  All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* Use of the Software is limited solely to applications:
+* (a) running on a Xilinx device, or
+* (b) that interact with a Xilinx device through a bus or interconnect.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* Except as contained in this notice, the name of the Xilinx shall not be used
+* in advertising or otherwise to promote the sale, use or other dealings in
+* this Software without prior written authorization from Xilinx.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xqspipsu.c
+* @addtogroup qspipsu_v1_7
+* @{
+*
+* This file implements the functions required to use the QSPIPSU hardware to
+* perform a transfer. These are accessible to the user via xqspipsu.h.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.0   hk  08/21/14 First release
+*       sk  03/13/15 Added IO mode support.
+*       hk  03/18/15 Switch to I/O mode before clearing RX FIFO.
+*                    Clear and disbale DMA interrupts/status in abort.
+*                    Use DMA DONE bit instead of BUSY as recommended.
+*       sk  04/24/15 Modified the code according to MISRAC-2012.
+*       sk  06/17/15 Removed NULL checks for Rx/Tx buffers. As
+*                    writing/reading from 0x0 location is permitted.
+* 1.1   sk  04/12/16 Added debug message prints.
+* 1.2  nsk 07/01/16 Changed XQspiPsu_Select to support GQSPI and LQSPI
+*                   selection.
+*       rk  07/15/16 Added support for TapDelays at different frequencies.
+*      nsk 08/05/16 Added example support PollData and PollTimeout
+* 1.3  nsk 09/16/16 Update PollData and PollTimeout support for dual
+*                   parallel configurations, modified XQspiPsu_PollData()
+*                   and XQspiPsu_Create_PollConfigData()
+* 1,5  nsk 08/14/17 Added CCI support
+* 1.7  tjs     01/16/18 Removed the check for DMA MSB to be written. (CR#992560)
+* 1.7  tjs 01/17/18 Added a support to toggle WP pin of the flash.
+* 1.7  tjs     03/14/18 Added support in EL1 NS mode (CR#974882)
+*
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xqspipsu.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+static void StubStatusHandler(void *CallBackRef, u32 StatusEvent,
+                       u32 ByteCount);
+static inline u32 XQspiPsu_SelectSpiMode(u8 SpiMode);
+static inline void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+                       u32 *GenFifoEntry);
+static inline void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr,
+                       XQspiPsu_Msg *Msg, s32 Size);
+static inline void XQspiPsu_SetupRxDma(XQspiPsu *InstancePtr,
+                       XQspiPsu_Msg *Msg);
+static inline void XQspiPsu_GenFifoEntryCSAssert(XQspiPsu *InstancePtr);
+static inline void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr,
+                       XQspiPsu_Msg *Msg, s32 Index);
+static inline void XQspiPsu_GenFifoEntryCSDeAssert(XQspiPsu *InstancePtr);
+static inline void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr,
+                       XQspiPsu_Msg *Msg, s32 Size);
+static inline void XQspiPsu_PollData(XQspiPsu *QspiPsuPtr,
+               XQspiPsu_Msg *FlashMsg);
+static inline u32 XQspiPsu_Create_PollConfigData(XQspiPsu *QspiPsuPtr,
+               XQspiPsu_Msg *FlashMsg);
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+/**
+*
+* Initializes a specific XQspiPsu instance such that the driver is ready to use.
+*
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+* @param       ConfigPtr is a reference to a structure containing information
+*              about a specific QSPIPSU device. This function initializes an
+*              InstancePtr object for a specific device specified by the
+*              contents of Config.
+* @param       EffectiveAddr is the device base address in the virtual memory
+*              address space. The caller is responsible for keeping the address
+*              mapping from EffectiveAddr to the device physical base address
+*              unchanged once this function is invoked. Unexpected errors may
+*              occur if the address mapping changes after this function is
+*              called. If address translation is not used, use
+*              ConfigPtr->Config.BaseAddress for this device.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_DEVICE_IS_STARTED if the device is already started.
+*              It must be stopped to re-initialize.
+*
+* @note                None.
+*
+******************************************************************************/
+s32 XQspiPsu_CfgInitialize(XQspiPsu *InstancePtr, XQspiPsu_Config *ConfigPtr,
+                               u32 EffectiveAddr)
+{
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(ConfigPtr != NULL);
+       s32 Status;
+
+       /*
+        * If the device is busy, disallow the initialize and return a status
+        * indicating it is already started. This allows the user to stop the
+        * device and re-initialize, but prevents a user from inadvertently
+        * initializing. This assumes the busy flag is cleared at startup.
+        */
+       if (InstancePtr->IsBusy == TRUE) {
+               Status = (s32)XST_DEVICE_IS_STARTED;
+       } else {
+
+               /* Set some default values. */
+               InstancePtr->IsBusy = FALSE;
+
+               InstancePtr->Config.BaseAddress = EffectiveAddr + XQSPIPSU_OFFSET;
+               InstancePtr->Config.ConnectionMode = ConfigPtr->ConnectionMode;
+               InstancePtr->StatusHandler = StubStatusHandler;
+               InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
+               InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
+               InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
+               /* Other instance variable initializations */
+               InstancePtr->SendBufferPtr = NULL;
+               InstancePtr->RecvBufferPtr = NULL;
+               InstancePtr->GenFifoBufferPtr = NULL;
+               InstancePtr->TxBytes = 0;
+               InstancePtr->RxBytes = 0;
+               InstancePtr->GenFifoEntries = 0;
+               InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
+               InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
+               InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
+               InstancePtr->IsUnaligned = 0;
+               InstancePtr->IsManualstart = TRUE;
+
+               /* Select QSPIPSU */
+               XQspiPsu_Select(InstancePtr, XQSPIPSU_SEL_GQSPI_MASK);
+
+               /*
+                * Reset the QSPIPSU device to get it into its initial state. It is
+                * expected that device configuration will take place after this
+                * initialization is done, but before the device is started.
+                */
+               XQspiPsu_Reset(InstancePtr);
+
+               InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
+
+               Status = XST_SUCCESS;
+       }
+
+       return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* Resets the QSPIPSU device. Reset must only be called after the driver has
+* been initialized. Any data transfer that is in progress is aborted.
+*
+* The upper layer software is responsible for re-configuring (if necessary)
+* and restarting the QSPIPSU device after the reset.
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+*
+* @return      None.
+*
+* @note                None.
+*
+******************************************************************************/
+void XQspiPsu_Reset(XQspiPsu *InstancePtr)
+{
+       u32 ConfigReg;
+
+       Xil_AssertVoid(InstancePtr != NULL);
+
+       /* Abort any transfer that is in progress */
+       XQspiPsu_Abort(InstancePtr);
+
+       /* Default value to config register */
+       ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+                       XQSPIPSU_CFG_OFFSET);
+
+       /* DMA mode */
+       ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
+       ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
+       /* Manual start */
+       ConfigReg |= XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK;
+       /* Little endain by default */
+       ConfigReg &= ~XQSPIPSU_CFG_ENDIAN_MASK;
+       /* Disable poll timeout */
+       ConfigReg &= ~XQSPIPSU_CFG_EN_POLL_TO_MASK;
+       /* Set hold bit */
+       ConfigReg |= XQSPIPSU_CFG_WP_HOLD_MASK;
+       /* Clear prescalar by default */
+       ConfigReg &= (u32)(~XQSPIPSU_CFG_BAUD_RATE_DIV_MASK);
+       /* CPOL CPHA 00 */
+       ConfigReg &= (u32)(~XQSPIPSU_CFG_CLK_PHA_MASK);
+       ConfigReg &= (u32)(~XQSPIPSU_CFG_CLK_POL_MASK);
+
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+               XQSPIPSU_CFG_OFFSET, ConfigReg);
+
+       /* Set by default to allow for high frequencies */
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+               XQSPIPSU_LPBK_DLY_ADJ_OFFSET,
+               XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+                       XQSPIPSU_LPBK_DLY_ADJ_OFFSET) |
+                       XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_MASK);
+
+       /* Reset thresholds */
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+               XQSPIPSU_TX_THRESHOLD_OFFSET,
+               XQSPIPSU_TX_FIFO_THRESHOLD_RESET_VAL);
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+               XQSPIPSU_RX_THRESHOLD_OFFSET,
+               XQSPIPSU_RX_FIFO_THRESHOLD_RESET_VAL);
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+               XQSPIPSU_GF_THRESHOLD_OFFSET,
+               XQSPIPSU_GEN_FIFO_THRESHOLD_RESET_VAL);
+
+       /* DMA init */
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                       XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET,
+                       XQSPIPSU_QSPIDMA_DST_CTRL_RESET_VAL);
+
+}
+
+/*****************************************************************************/
+/**
+*
+* Aborts a transfer in progress by
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+*
+* @return      None.
+*
+* @note
+*
+******************************************************************************/
+void XQspiPsu_Abort(XQspiPsu *InstancePtr)
+{
+
+       u32 IntrStatus, ConfigReg;
+
+       IntrStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+                                       XQSPIPSU_ISR_OFFSET);
+
+       /* Clear and disable interrupts */
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+               XQSPIPSU_ISR_OFFSET, IntrStatus | XQSPIPSU_ISR_WR_TO_CLR_MASK);
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                       XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
+               XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+                               XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET));
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                       XQSPIPSU_QSPIDMA_DST_STS_OFFSET,
+                       XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+                               XQSPIPSU_QSPIDMA_DST_STS_OFFSET) |
+                               XQSPIPSU_QSPIDMA_DST_STS_WTC);
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+               XQSPIPSU_IDR_OFFSET, XQSPIPSU_IDR_ALL_MASK);
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                       XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
+                       XQSPIPSU_QSPIDMA_DST_INTR_ALL_MASK);
+
+       /* Clear FIFO */
+       if((XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+                       XQSPIPSU_ISR_OFFSET) & XQSPIPSU_ISR_RXEMPTY_MASK) != FALSE) {
+               XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                       XQSPIPSU_FIFO_CTRL_OFFSET,
+                       XQSPIPSU_FIFO_CTRL_RST_TX_FIFO_MASK |
+                       XQSPIPSU_FIFO_CTRL_RST_GEN_FIFO_MASK);
+       }
+
+       /*
+        * Switch to IO mode to Clear RX FIFO. This is becuase of DMA behaviour
+        * where it waits on RX empty and goes busy assuming there is data
+        * to be transfered even if there is no request.
+        */
+       if ((IntrStatus & XQSPIPSU_ISR_RXEMPTY_MASK) != 0U) {
+               ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+                                       XQSPIPSU_CFG_OFFSET);
+               ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
+               XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                               XQSPIPSU_CFG_OFFSET, ConfigReg);
+
+               XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                               XQSPIPSU_FIFO_CTRL_OFFSET,
+                               XQSPIPSU_FIFO_CTRL_RST_RX_FIFO_MASK);
+
+               if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+                       ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
+                       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                                       XQSPIPSU_CFG_OFFSET, ConfigReg);
+               }
+       }
+
+       /* Disable QSPIPSU */
+       XQspiPsu_Disable(InstancePtr);
+
+       InstancePtr->TxBytes = 0;
+       InstancePtr->RxBytes = 0;
+       InstancePtr->GenFifoEntries = 0;
+       InstancePtr->IsBusy = FALSE;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function performs a transfer on the bus in polled mode. The messages
+* passed are all transferred on the bus between one CS assert and de-assert.
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+* @param       Msg is a pointer to the structure containing transfer data.
+* @param       NumMsg is the number of messages to be transferred.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_FAILURE if transfer fails.
+*              - XST_DEVICE_BUSY if a transfer is already in progress.
+*
+* @note                None.
+*
+******************************************************************************/
+s32 XQspiPsu_PolledTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+                               u32 NumMsg)
+{
+
+       s32 Index;
+       u32 QspiPsuStatusReg;
+       u32 BaseAddress;
+       s32 RxThr;
+       u32 IOPending = (u32)FALSE;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+       for (Index = 0; Index < (s32)NumMsg; Index++) {
+               Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
+       }
+
+       /* Check whether there is another transfer in progress. Not thread-safe */
+       if (InstancePtr->IsBusy == TRUE) {
+               return (s32)XST_DEVICE_BUSY;
+       }
+
+       /* Check for ByteCount upper limit - 2^28 for DMA */
+       for (Index = 0; Index < (s32)NumMsg; Index++) {
+               if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
+                               ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
+                       return (s32)XST_FAILURE;
+               }
+       }
+
+       /*
+        * Set the busy flag, which will be cleared when the transfer is
+        * entirely done.
+        */
+       InstancePtr->IsBusy = TRUE;
+
+       BaseAddress = InstancePtr->Config.BaseAddress;
+
+       /* Enable */
+       XQspiPsu_Enable(InstancePtr);
+
+       /* Select slave */
+       XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
+
+       /* list */
+       Index = 0;
+       while (Index < (s32)NumMsg) {
+               XQspiPsu_GenFifoEntryData(InstancePtr, Msg, Index);
+
+               if (InstancePtr->IsManualstart == TRUE) {
+#ifdef DEBUG
+       xil_printf("\nManual Start\r\n");
+#endif
+                       XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
+                               XQspiPsu_ReadReg(BaseAddress,
+                                       XQSPIPSU_CFG_OFFSET) |
+                                       XQSPIPSU_CFG_START_GEN_FIFO_MASK);
+               }
+
+               /* Use thresholds here */
+               /* If there is more data to be transmitted */
+               do {
+                       QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress,
+                                               XQSPIPSU_ISR_OFFSET);
+
+                       /* Transmit more data if left */
+                       if (((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != FALSE) &&
+                               ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
+                               (InstancePtr->TxBytes > 0)) {
+                               XQspiPsu_FillTxFifo(InstancePtr, &Msg[Index],
+                                               XQSPIPSU_TXD_DEPTH);
+                       }
+
+                       /* Check if DMA RX is complete and update RxBytes */
+                       if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
+                               ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
+                               u32 DmaIntrSts;
+                               DmaIntrSts = XQspiPsu_ReadReg(BaseAddress,
+                                                               XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
+                               if ((DmaIntrSts & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != FALSE) {
+                                       XQspiPsu_WriteReg(BaseAddress,
+                                               XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
+                                               DmaIntrSts);
+                                       /* Read remaining bytes using IO mode */
+                                       if((InstancePtr->RxBytes % 4) != 0 ) {
+                                               XQspiPsu_WriteReg(BaseAddress,
+                                                       XQSPIPSU_CFG_OFFSET,
+                                                       (XQspiPsu_ReadReg(BaseAddress,
+                                                       XQSPIPSU_CFG_OFFSET) &
+                                                       ~XQSPIPSU_CFG_MODE_EN_MASK));
+                                               InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
+                                               Msg[Index].ByteCount =
+                                                       (InstancePtr->RxBytes % 4);
+                                               Msg[Index].RxBfrPtr += (InstancePtr->RxBytes -
+                                                               (InstancePtr->RxBytes % 4));
+                                               InstancePtr->IsUnaligned = 1;
+                                               IOPending = (u32)TRUE;
+                                               break;
+                                       }
+                                       InstancePtr->RxBytes = 0;
+                               }
+                       } else {
+                               if ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE) {
+                                       /* Check if PIO RX is complete and update RxBytes */
+                                       RxThr = (s32)XQspiPsu_ReadReg(BaseAddress,
+                                                       XQSPIPSU_RX_THRESHOLD_OFFSET);
+                                       if ((QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK)
+                                                                       != 0U) {
+                                               XQspiPsu_ReadRxFifo(InstancePtr,
+                                                               &Msg[Index], RxThr*4);
+
+                                       } else {
+                                               if ((QspiPsuStatusReg &
+                                                       XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != 0U) {
+                                                               XQspiPsu_ReadRxFifo(InstancePtr,
+                                                                       &Msg[Index], InstancePtr->RxBytes);
+                                               }
+                                       }
+                               }
+                       }
+               } while (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == FALSE) ||
+                       (InstancePtr->TxBytes != 0) ||
+                       ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) == FALSE) ||
+                       (InstancePtr->RxBytes != 0));
+
+               if((InstancePtr->IsUnaligned != 0) && (IOPending == (u32)FALSE)) {
+                       InstancePtr->IsUnaligned = 0;
+                       XQspiPsu_WriteReg(BaseAddress,
+                               XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
+                               BaseAddress,
+                               XQSPIPSU_CFG_OFFSET) |
+                               XQSPIPSU_CFG_MODE_EN_DMA_MASK));
+                       InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
+               }
+
+               if (IOPending == (u32)TRUE) {
+                       IOPending = (u32)FALSE;
+               } else {
+                       Index++;
+               }
+       }
+
+       /* De-select slave */
+       XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
+
+       if (InstancePtr->IsManualstart == TRUE) {
+#ifdef DEBUG
+       xil_printf("\nManual Start\r\n");
+#endif
+               XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
+                       XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
+                               XQSPIPSU_CFG_START_GEN_FIFO_MASK);
+       }
+
+       QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_ISR_OFFSET);
+       while ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == FALSE) {
+               QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress,
+                                               XQSPIPSU_ISR_OFFSET);
+       }
+
+       /* Clear the busy flag. */
+       InstancePtr->IsBusy = FALSE;
+
+       /* Disable the device. */
+       XQspiPsu_Disable(InstancePtr);
+
+       return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function initiates a transfer on the bus and enables interrupts.
+* The transfer is completed by the interrupt handler. The messages passed are
+* all transferred on the bus between one CS assert and de-assert.
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+* @param       Msg is a pointer to the structure containing transfer data.
+* @param       NumMsg is the number of messages to be transferred.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_FAILURE if transfer fails.
+*              - XST_DEVICE_BUSY if a transfer is already in progress.
+*
+* @note                None.
+*
+******************************************************************************/
+s32 XQspiPsu_InterruptTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+                               u32 NumMsg)
+{
+
+       s32 Index;
+       u32 BaseAddress;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+       for (Index = 0; Index < (s32)NumMsg; Index++) {
+               Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
+       }
+
+       /* Check whether there is another transfer in progress. Not thread-safe */
+       if (InstancePtr->IsBusy == TRUE) {
+               return (s32)XST_DEVICE_BUSY;
+       }
+
+       if (Msg[0].Flags & XQSPIPSU_MSG_FLAG_POLL) {
+               InstancePtr->IsBusy = TRUE;
+               XQspiPsu_PollData(InstancePtr, Msg);
+       } else {
+               /* Check for ByteCount upper limit - 2^28 for DMA */
+               for (Index = 0; Index < (s32)NumMsg; Index++) {
+                       if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
+                                       ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
+                       return (s32)XST_FAILURE;
+               }
+       }
+
+       /*
+        * Set the busy flag, which will be cleared when the transfer is
+        * entirely done.
+        */
+       InstancePtr->IsBusy = TRUE;
+
+       BaseAddress = InstancePtr->Config.BaseAddress;
+
+       InstancePtr->Msg = Msg;
+       InstancePtr->NumMsg = (s32)NumMsg;
+       InstancePtr->MsgCnt = 0;
+
+       /* Enable */
+       XQspiPsu_Enable(InstancePtr);
+
+       /* Select slave */
+       XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
+
+       /* This might not work if not manual start */
+       /* Put first message in FIFO along with the above slave select */
+       XQspiPsu_GenFifoEntryData(InstancePtr, Msg, 0);
+
+       if (InstancePtr->IsManualstart == TRUE) {
+#ifdef DEBUG
+       xil_printf("\nManual Start\r\n");
+#endif
+               XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
+                       XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) |
+                               XQSPIPSU_CFG_START_GEN_FIFO_MASK);
+       }
+
+       /* Enable interrupts */
+       XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_IER_OFFSET,
+               (u32)XQSPIPSU_IER_TXNOT_FULL_MASK | (u32)XQSPIPSU_IER_TXEMPTY_MASK |
+               (u32)XQSPIPSU_IER_RXNEMPTY_MASK | (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
+               (u32)XQSPIPSU_IER_RXEMPTY_MASK);
+
+       if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+               XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_QSPIDMA_DST_I_EN_OFFSET,
+                               XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
+       }
+       }
+       return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Handles interrupt based transfers by acting on GENFIFO and DMA interurpts.
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_FAILURE if transfer fails.
+*
+* @note                None.
+*
+******************************************************************************/
+s32 XQspiPsu_InterruptHandler(XQspiPsu *InstancePtr)
+{
+       u32 QspiPsuStatusReg, DmaIntrStatusReg = 0;
+       u32 BaseAddress;
+       XQspiPsu_Msg *Msg;
+       s32 NumMsg;
+       s32 MsgCnt;
+       u8 DeltaMsgCnt = 0;
+       s32 RxThr;
+       u32 TxRxFlag;
+
+       Xil_AssertNonvoid(InstancePtr != NULL);
+
+       BaseAddress = InstancePtr->Config.BaseAddress;
+       Msg = InstancePtr->Msg;
+       NumMsg = InstancePtr->NumMsg;
+       MsgCnt = InstancePtr->MsgCnt;
+       TxRxFlag = Msg[MsgCnt].Flags;
+
+       /* QSPIPSU Intr cleared on read */
+       QspiPsuStatusReg = XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_ISR_OFFSET);
+       if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+               /* DMA Intr write to clear */
+               DmaIntrStatusReg = XQspiPsu_ReadReg(BaseAddress,
+                                       XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
+
+               XQspiPsu_WriteReg(BaseAddress,
+                       XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET, DmaIntrStatusReg);
+       }
+       if (((DmaIntrStatusReg & XQSPIPSU_QSPIDMA_DST_INTR_ERR_MASK) != FALSE)) {
+               /* Call status handler to indicate error */
+               InstancePtr->StatusHandler(InstancePtr->StatusRef,
+                                       XST_SPI_COMMAND_ERROR, 0);
+       }
+
+       /* Fill more data to be txed if required */
+       if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
+               ((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != FALSE) &&
+               (InstancePtr->TxBytes > 0)) {
+               XQspiPsu_FillTxFifo(InstancePtr, &Msg[MsgCnt],
+                               XQSPIPSU_TXD_DEPTH);
+       }
+
+       /*
+        * Check if the entry is ONLY TX and increase MsgCnt.
+        * This is to allow TX and RX together in one entry - corner case.
+        */
+       if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
+               ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) != FALSE) &&
+               ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
+               (InstancePtr->TxBytes == 0) &&
+               ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == FALSE)) {
+               MsgCnt += 1;
+               DeltaMsgCnt = 1U;
+       }
+
+       if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
+               (MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
+               if ((DmaIntrStatusReg & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != FALSE) {
+                               /* Read remaining bytes using IO mode */
+                       if((InstancePtr->RxBytes % 4) != 0 ) {
+                               XQspiPsu_WriteReg(BaseAddress,
+                                       XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
+                                       BaseAddress, XQSPIPSU_CFG_OFFSET) &
+                                       ~XQSPIPSU_CFG_MODE_EN_MASK));
+                               InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
+                               Msg[MsgCnt].ByteCount = (InstancePtr->RxBytes % 4);
+                               Msg[MsgCnt].RxBfrPtr += (InstancePtr->RxBytes -
+                                               (InstancePtr->RxBytes % 4));
+                               InstancePtr->IsUnaligned = 1;
+                               XQspiPsu_GenFifoEntryData(InstancePtr, Msg,
+                                               MsgCnt);
+                               if(InstancePtr->IsManualstart == TRUE) {
+#ifdef DEBUG
+       xil_printf("\nManual Start\r\n");
+#endif
+                                       XQspiPsu_WriteReg(BaseAddress,
+                                               XQSPIPSU_CFG_OFFSET,
+                                               XQspiPsu_ReadReg(BaseAddress,
+                                               XQSPIPSU_CFG_OFFSET) |
+                                               XQSPIPSU_CFG_START_GEN_FIFO_MASK);
+                               }
+                       }
+                       else {
+                               InstancePtr->RxBytes = 0;
+                               MsgCnt += 1;
+                               DeltaMsgCnt = 1U;
+                       }
+               }
+       } else {
+               if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
+                       if (InstancePtr->RxBytes != 0) {
+                               if ((QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK)
+                                                               != FALSE) {
+                                       RxThr = (s32)XQspiPsu_ReadReg(BaseAddress,
+                                                               XQSPIPSU_RX_THRESHOLD_OFFSET);
+                                       XQspiPsu_ReadRxFifo(InstancePtr, &Msg[MsgCnt],
+                                               RxThr*4);
+                               } else {
+                                       if (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
+                                               ((QspiPsuStatusReg & XQSPIPSU_ISR_RXEMPTY_MASK) == FALSE)) {
+                                               XQspiPsu_ReadRxFifo(InstancePtr, &Msg[MsgCnt],
+                                                       InstancePtr->RxBytes);
+                                       }
+                               }
+                               if (InstancePtr->RxBytes == 0) {
+                                       MsgCnt += 1;
+                                       DeltaMsgCnt = 1U;
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Dummy byte transfer
+        * MsgCnt < NumMsg check is to ensure is it a valid dummy cycle message
+        * If one of the above conditions increased MsgCnt, then
+        * the new message is yet to be placed in the FIFO; hence !DeltaMsgCnt.
+        */
+       if ((MsgCnt < NumMsg) && (DeltaMsgCnt == FALSE) &&
+               ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == FALSE) &&
+               ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) == FALSE) &&
+               ((TxRxFlag & XQSPIPSU_MSG_FLAG_POLL) == FALSE) &&
+               ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE)) {
+               MsgCnt += 1;
+               DeltaMsgCnt = 1U;
+       }
+       InstancePtr->MsgCnt = MsgCnt;
+
+       /*
+        * DeltaMsgCnt is to handle conditions where genfifo empty can be set
+        * while tx is still not empty or rx dma is not yet done.
+        * MsgCnt > NumMsg indicates CS de-assert entry was also executed.
+        */
+       if (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != FALSE) &&
+               ((DeltaMsgCnt != FALSE) || (MsgCnt > NumMsg))) {
+               if (MsgCnt < NumMsg) {
+                       if(InstancePtr->IsUnaligned != 0) {
+                               InstancePtr->IsUnaligned = 0;
+                               XQspiPsu_WriteReg(InstancePtr->Config.
+                                       BaseAddress, XQSPIPSU_CFG_OFFSET,
+                                       (XQspiPsu_ReadReg(InstancePtr->Config.
+                                       BaseAddress, XQSPIPSU_CFG_OFFSET) |
+                                       XQSPIPSU_CFG_MODE_EN_DMA_MASK));
+                               InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
+                       }
+                       /* This might not work if not manual start */
+                       XQspiPsu_GenFifoEntryData(InstancePtr, Msg, MsgCnt);
+
+                       if (InstancePtr->IsManualstart == TRUE) {
+#ifdef DEBUG
+       xil_printf("\nManual Start\r\n");
+#endif
+                               XQspiPsu_WriteReg(BaseAddress,
+                                       XQSPIPSU_CFG_OFFSET,
+                                       XQspiPsu_ReadReg(BaseAddress,
+                                               XQSPIPSU_CFG_OFFSET) |
+                                               XQSPIPSU_CFG_START_GEN_FIFO_MASK);
+                       }
+               } else if (MsgCnt == NumMsg) {
+                       /* This is just to keep track of the de-assert entry */
+                       MsgCnt += 1;
+                       InstancePtr->MsgCnt = MsgCnt;
+
+                       /* De-select slave */
+                       XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
+
+                       if (InstancePtr->IsManualstart == TRUE) {
+#ifdef DEBUG
+       xil_printf("\nManual Start\r\n");
+#endif
+                               XQspiPsu_WriteReg(BaseAddress,
+                                       XQSPIPSU_CFG_OFFSET,
+                                       XQspiPsu_ReadReg(BaseAddress,
+                                               XQSPIPSU_CFG_OFFSET) |
+                                               XQSPIPSU_CFG_START_GEN_FIFO_MASK);
+                       }
+               } else {
+                       /* Disable interrupts */
+                       XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_IDR_OFFSET,
+                                       (u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
+                                       (u32)XQSPIPSU_IER_TXEMPTY_MASK |
+                                       (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
+                                       (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
+                                       (u32)XQSPIPSU_IER_RXEMPTY_MASK);
+                       if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+                               XQspiPsu_WriteReg(BaseAddress,
+                                       XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
+                                       XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
+                       }
+
+                       /* Clear the busy flag. */
+                       InstancePtr->IsBusy = FALSE;
+
+                       /* Disable the device. */
+                       XQspiPsu_Disable(InstancePtr);
+
+                       /* Call status handler to indicate completion */
+                       InstancePtr->StatusHandler(InstancePtr->StatusRef,
+                                               XST_SPI_TRANSFER_DONE, 0);
+               }
+       }
+       if ((TxRxFlag & XQSPIPSU_MSG_FLAG_POLL) != FALSE){
+                if (QspiPsuStatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK){
+                        /*
+                         * Read data from RXFIFO, since when data from the flash device
+                         * (status data) matched with configured value in poll_cfg, then
+                         * controller writes the matched data into RXFIFO.
+                         */
+                       XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_RXD_OFFSET);
+
+                       XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_IDR_OFFSET,
+                                       (u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
+                                       (u32)XQSPIPSU_IER_TXEMPTY_MASK |
+                                       (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
+                                       (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
+                                       (u32)XQSPIPSU_IER_RXEMPTY_MASK |
+                                       (u32)XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK);
+                       InstancePtr->StatusHandler(InstancePtr->StatusRef, XST_SPI_POLL_DONE, 0);
+
+                       InstancePtr->IsBusy = FALSE;
+                       /* Disable the device. */
+                       XQspiPsu_Disable(InstancePtr);
+
+                }
+                if (QspiPsuStatusReg & XQSPIPSU_ISR_POLL_TIME_EXPIRE_MASK){
+                       InstancePtr->StatusHandler(InstancePtr->StatusRef,
+                                       XST_FLASH_TIMEOUT_ERROR, 0);
+                }
+       }
+       return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Sets the status callback function, the status handler, which the driver
+* calls when it encounters conditions that should be reported to upper
+* layer software. The handler executes in an interrupt context, so it must
+* minimize the amount of processing performed. One of the following status
+* events is passed to the status handler.
+*
+* <pre>
+*
+* XST_SPI_TRANSFER_DONE                The requested data transfer is done
+*
+* XST_SPI_TRANSMIT_UNDERRUN    As a slave device, the master clocked data
+*                              but there were none available in the transmit
+*                              register/FIFO. This typically means the slave
+*                              application did not issue a transfer request
+*                              fast enough, or the processor/driver could not
+*                              fill the transmit register/FIFO fast enough.
+*
+* XST_SPI_RECEIVE_OVERRUN      The QSPIPSU device lost data. Data was received
+*                              but the receive data register/FIFO was full.
+*
+* </pre>
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+* @param       CallBackRef is the upper layer callback reference passed back
+*              when the callback function is invoked.
+* @param       FuncPointer is the pointer to the callback function.
+*
+* @return      None.
+*
+* @note
+*
+* The handler is called within interrupt context, so it should do its work
+* quickly and queue potentially time-consuming work to a task-level thread.
+*
+******************************************************************************/
+void XQspiPsu_SetStatusHandler(XQspiPsu *InstancePtr, void *CallBackRef,
+                               XQspiPsu_StatusHandler FuncPointer)
+{
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(FuncPointer != NULL);
+       Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+       InstancePtr->StatusHandler = FuncPointer;
+       InstancePtr->StatusRef = CallBackRef;
+}
+
+/*****************************************************************************/
+/**
+*
+* This is a stub for the status callback. The stub is here in case the upper
+* layers forget to set the handler.
+*
+* @param       CallBackRef is a pointer to the upper layer callback reference
+* @param       StatusEvent is the event that just occurred.
+* @param       ByteCount is the number of bytes transferred up until the event
+*              occurred.
+*
+* @return      None.
+*
+* @note                None.
+*
+******************************************************************************/
+static void StubStatusHandler(void *CallBackRef, u32 StatusEvent,
+                               u32 ByteCount)
+{
+       (void) CallBackRef;
+       (void) StatusEvent;
+       (void) ByteCount;
+
+       Xil_AssertVoidAlways();
+}
+
+/*****************************************************************************/
+/**
+*
+* Selects SPI mode - x1 or x2 or x4.
+*
+* @param       SpiMode - spi or dual or quad.
+* @return      Mask to set desired SPI mode in GENFIFO entry.
+*
+* @note                None.
+*
+******************************************************************************/
+static inline u32 XQspiPsu_SelectSpiMode(u8 SpiMode)
+{
+       u32 Mask;
+
+#ifdef DEBUG
+       xil_printf("\nXQspiPsu_SelectSpiMode\r\n");
+#endif
+
+       switch (SpiMode) {
+               case XQSPIPSU_SELECT_MODE_DUALSPI:
+                       Mask = XQSPIPSU_GENFIFO_MODE_DUALSPI;
+                       break;
+               case XQSPIPSU_SELECT_MODE_QUADSPI:
+                       Mask = XQSPIPSU_GENFIFO_MODE_QUADSPI;
+                       break;
+               case XQSPIPSU_SELECT_MODE_SPI:
+                       Mask = XQSPIPSU_GENFIFO_MODE_SPI;
+                       break;
+               default:
+                       Mask = XQSPIPSU_GENFIFO_MODE_SPI;
+                       break;
+       }
+#ifdef DEBUG
+       xil_printf("\nSPIMode is %08x\r\n", SpiMode);
+#endif
+
+       return Mask;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function checks the TX/RX buffers in the message and setups up the
+* GENFIFO entries, TX FIFO or RX DMA as required.
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+* @param       Msg is a pointer to the structure containing transfer data.
+* @param       GenFifoEntry is pointer to the variable in which GENFIFO mask
+*              is returned to calling function
+*
+* @return      None
+*
+* @note                None.
+*
+******************************************************************************/
+static inline void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+                                       u32 *GenFifoEntry)
+{
+       Xil_AssertVoid(InstancePtr != NULL);
+
+       /* Transmit */
+       if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
+                       ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == FALSE)) {
+               /* Setup data to be TXed */
+               *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
+               *GenFifoEntry |= XQSPIPSU_GENFIFO_TX;
+               InstancePtr->TxBytes = (s32)Msg->ByteCount;
+               InstancePtr->SendBufferPtr = Msg->TxBfrPtr;
+               InstancePtr->RecvBufferPtr = NULL;
+               XQspiPsu_FillTxFifo(InstancePtr, Msg, XQSPIPSU_TXD_DEPTH);
+               /* Discard RX data */
+               *GenFifoEntry &= ~XQSPIPSU_GENFIFO_RX;
+               InstancePtr->RxBytes = 0;
+       }
+
+       /* Receive */
+       if (((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE) &&
+                       ((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == FALSE)) {
+               /* TX auto fill */
+               *GenFifoEntry &= ~XQSPIPSU_GENFIFO_TX;
+               InstancePtr->TxBytes = 0;
+               /* Setup RX */
+               *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
+               *GenFifoEntry |= XQSPIPSU_GENFIFO_RX;
+               InstancePtr->RxBytes = (s32)Msg->ByteCount;
+               InstancePtr->SendBufferPtr = NULL;
+               InstancePtr->RecvBufferPtr = Msg->RxBfrPtr;
+               if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+                       XQspiPsu_SetupRxDma(InstancePtr, Msg);
+               }
+       }
+
+       /* If only dummy is requested as a separate entry */
+       if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == FALSE) &&
+                       (Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == FALSE) {
+               *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
+               *GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX);
+               InstancePtr->TxBytes = 0;
+               InstancePtr->RxBytes = 0;
+               InstancePtr->SendBufferPtr = NULL;
+               InstancePtr->RecvBufferPtr = NULL;
+       }
+
+       /* Dummy and cmd sent by upper layer to received data */
+       if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != FALSE) &&
+                       ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
+               *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
+               *GenFifoEntry |= (XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX);
+               InstancePtr->TxBytes = (s32)Msg->ByteCount;
+               InstancePtr->RxBytes = (s32)Msg->ByteCount;
+               InstancePtr->SendBufferPtr = Msg->TxBfrPtr;
+               InstancePtr->RecvBufferPtr = Msg->RxBfrPtr;
+               XQspiPsu_FillTxFifo(InstancePtr, Msg, XQSPIPSU_TXD_DEPTH);
+               /* Add check for DMA or PIO here */
+               if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+                       XQspiPsu_SetupRxDma(InstancePtr, Msg);
+               }
+       }
+}
+
+/*****************************************************************************/
+/**
+*
+* Fills the TX FIFO as long as there is room in the FIFO or the bytes required
+* to be transmitted.
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+* @param       Msg is a pointer to the structure containing transfer data.
+* @param       Size is the number of bytes to be transmitted.
+*
+* @return      None
+*
+* @note                None.
+*
+******************************************************************************/
+static inline void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr,
+                                       XQspiPsu_Msg *Msg, s32 Size)
+{
+       s32 Count = 0;
+       u32 Data;
+
+       Xil_AssertVoid(InstancePtr != NULL);
+
+#ifdef DEBUG
+       xil_printf("\nXQspiPsu_FillTxFifo\r\n");
+#endif
+
+       while ((InstancePtr->TxBytes > 0) && (Count < Size)) {
+               if (InstancePtr->TxBytes >= 4) {
+                       (void)memcpy(&Data, Msg->TxBfrPtr, 4);
+                       Msg->TxBfrPtr += 4;
+                       InstancePtr->TxBytes -= 4;
+                       Count += 4;
+               } else {
+                       (void)memcpy(&Data, Msg->TxBfrPtr, InstancePtr->TxBytes);
+                       Msg->TxBfrPtr += InstancePtr->TxBytes;
+                       Count += InstancePtr->TxBytes;
+                       InstancePtr->TxBytes = 0;
+               }
+               XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                               XQSPIPSU_TXD_OFFSET, Data);
+#ifdef DEBUG
+       xil_printf("\nData is %08x\r\n", Data);
+#endif
+
+       }
+       if (InstancePtr->TxBytes < 0) {
+               InstancePtr->TxBytes = 0;
+       }
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets up the RX DMA operation.
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+* @param       Msg is a pointer to the structure containing transfer data.
+*
+* @return      None
+*
+* @note                None.
+*
+******************************************************************************/
+static inline void XQspiPsu_SetupRxDma(XQspiPsu *InstancePtr,
+                                       XQspiPsu_Msg *Msg)
+{
+       s32 Remainder;
+       s32 DmaRxBytes;
+       u64 AddrTemp;
+
+       Xil_AssertVoid(InstancePtr != NULL);
+
+       AddrTemp = (u64)((INTPTR)(Msg->RxBfrPtr) &
+                               XQSPIPSU_QSPIDMA_DST_ADDR_MASK);
+       /* Check for RXBfrPtr to be word aligned */
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                       XQSPIPSU_QSPIDMA_DST_ADDR_OFFSET,
+                       (u32)AddrTemp);
+
+#ifdef __aarch64__
+       AddrTemp = (u64)((INTPTR)(Msg->RxBfrPtr) >> 32);
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                       XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET,
+                       (u32)AddrTemp &
+                       XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK);
+#endif
+
+       Remainder = InstancePtr->RxBytes % 4;
+       DmaRxBytes = InstancePtr->RxBytes;
+       if (Remainder != 0) {
+               /* This is done to make Dma bytes aligned */
+               DmaRxBytes = InstancePtr->RxBytes - Remainder;
+               Msg->ByteCount = (u32)DmaRxBytes;
+       }
+       if (InstancePtr->Config.IsCacheCoherent == 0) {
+               Xil_DCacheInvalidateRange((INTPTR)InstancePtr->RecvBufferPtr,
+                       Msg->ByteCount);
+       }
+
+       /* Write no. of words to DMA DST SIZE */
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+                       XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes);
+
+}
+
+/*****************************************************************************/
+/**
+*
+* This function writes the GENFIFO entry to assert CS.
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+*
+* @return      None
+*
+* @note                None.
+*
+******************************************************************************/
+static inline void XQspiPsu_GenFifoEntryCSAssert(XQspiPsu *InstancePtr)
+{
+       u32 GenFifoEntry;
+
+#ifdef DEBUG
+       xil_printf("\nXQspiPsu_GenFifoEntryCSAssert\r\n");
+#endif
+
+       GenFifoEntry = 0x0U;
+       GenFifoEntry &= ~((u32)XQSPIPSU_GENFIFO_DATA_XFER | (u32)XQSPIPSU_GENFIFO_EXP);
+       GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_MODE_MASK);
+       GenFifoEntry |= XQSPIPSU_GENFIFO_MODE_SPI;
+       GenFifoEntry |= InstancePtr->GenFifoCS;
+       GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_BUS_MASK);
+       GenFifoEntry |= InstancePtr->GenFifoBus;
+       GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX |
+                       XQSPIPSU_GENFIFO_STRIPE | XQSPIPSU_GENFIFO_POLL);
+       GenFifoEntry |= XQSPIPSU_GENFIFO_CS_SETUP;
+#ifdef DEBUG
+       xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
+#endif
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+               XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
+}
+
+/*****************************************************************************/
+/**
+*
+* This function writes the GENFIFO entries to transmit the messages requested.
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+* @param       Msg is a pointer to the structure containing transfer data.
+* @param       Index of the current message to be handled.
+*
+* @return
+*              - XST_SUCCESS if successful.
+*              - XST_FAILURE if transfer fails.
+*              - XST_DEVICE_BUSY if a transfer is already in progress.
+*
+* @note                None.
+*
+******************************************************************************/
+static inline void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr,
+                                               XQspiPsu_Msg *Msg, s32 Index)
+{
+       u32 GenFifoEntry;
+       u32 BaseAddress;
+       u32 TempCount;
+       u32 ImmData;
+
+#ifdef DEBUG
+       xil_printf("\nXQspiPsu_GenFifoEntryData\r\n");
+#endif
+
+       BaseAddress = InstancePtr->Config.BaseAddress;
+
+       GenFifoEntry = 0x0U;
+       /* Bus width */
+       GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_MODE_MASK);
+       GenFifoEntry |= XQspiPsu_SelectSpiMode((u8)Msg[Index].BusWidth);
+
+       GenFifoEntry |= InstancePtr->GenFifoCS;
+       GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_BUS_MASK);
+       GenFifoEntry |= InstancePtr->GenFifoBus;
+
+       /* Data */
+       if (((Msg[Index].Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != FALSE) {
+               GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE;
+       } else {
+               GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
+       }
+
+       /* If Byte Count is less than 8 bytes do the transfer in IO mode */
+       if ((Msg[Index].ByteCount < 8U) &&
+               (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA)) {
+                       InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
+                       XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_CFG_OFFSET,
+                               (XQspiPsu_ReadReg(BaseAddress, XQSPIPSU_CFG_OFFSET) &
+                                               ~XQSPIPSU_CFG_MODE_EN_MASK));
+                       InstancePtr->IsUnaligned = 1;
+       }
+
+       XQspiPsu_TXRXSetup(InstancePtr, &Msg[Index], &GenFifoEntry);
+
+       if (Msg[Index].ByteCount < XQSPIPSU_GENFIFO_IMM_DATA_MASK) {
+               GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_IMM_DATA_MASK);
+               GenFifoEntry |= Msg[Index].ByteCount;
+#ifdef DEBUG
+       xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
+#endif
+               XQspiPsu_WriteReg(BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
+                               GenFifoEntry);
+       } else {
+               TempCount = Msg[Index].ByteCount;
+               u32 Exponent = 8;       /* 2^8 = 256 */
+
+               ImmData = TempCount & 0xFFU;
+               /* Exponent entries */
+               GenFifoEntry |= XQSPIPSU_GENFIFO_EXP;
+               while (TempCount != 0U) {
+                       if ((TempCount & XQSPIPSU_GENFIFO_EXP_START) != FALSE) {
+                               GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_IMM_DATA_MASK);
+                               GenFifoEntry |= Exponent;
+#ifdef DEBUG
+       xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
+#endif
+                               XQspiPsu_WriteReg(BaseAddress,
+                                       XQSPIPSU_GEN_FIFO_OFFSET,
+                                       GenFifoEntry);
+                       }
+                       TempCount = TempCount >> 1;
+                       Exponent++;
+               }
+
+               /* Immediate entry */
+               GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_EXP);
+               if ((ImmData & 0xFFU) != FALSE) {
+                       GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_IMM_DATA_MASK);
+                       GenFifoEntry |= ImmData & 0xFFU;
+#ifdef DEBUG
+       xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
+#endif
+                       XQspiPsu_WriteReg(BaseAddress,
+                               XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
+               }
+       }
+
+       /* One dummy GenFifo entry in case of IO mode */
+       if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_IO) &&
+                       ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != FALSE)) {
+               GenFifoEntry = 0x0U;
+#ifdef DEBUG
+       xil_printf("\nDummy FifoEntry=%08x\r\n",GenFifoEntry);
+#endif
+               XQspiPsu_WriteReg(BaseAddress,
+                               XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
+       }
+}
+
+/*****************************************************************************/
+/**
+*
+* This function writes the GENFIFO entry to de-assert CS.
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+*
+* @return      None
+*
+* @note                None.
+*
+******************************************************************************/
+static inline void XQspiPsu_GenFifoEntryCSDeAssert(XQspiPsu *InstancePtr)
+{
+       u32 GenFifoEntry;
+
+#ifdef DEBUG
+       xil_printf("\nXQspiPsu_GenFifoEntryCSDeAssert\r\n");
+#endif
+
+       GenFifoEntry = 0x0U;
+       GenFifoEntry &= ~((u32)XQSPIPSU_GENFIFO_DATA_XFER | (u32)XQSPIPSU_GENFIFO_EXP);
+       GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_MODE_MASK);
+       GenFifoEntry |= XQSPIPSU_GENFIFO_MODE_SPI;
+       GenFifoEntry &= (u32)(~XQSPIPSU_GENFIFO_BUS_MASK);
+       GenFifoEntry |= InstancePtr->GenFifoBus;
+       GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX |
+                       XQSPIPSU_GENFIFO_STRIPE | XQSPIPSU_GENFIFO_POLL);
+       GenFifoEntry |= XQSPIPSU_GENFIFO_CS_HOLD;
+#ifdef DEBUG
+       xil_printf("\nFifoEntry=%08x\r\n",GenFifoEntry);
+#endif
+       XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+               XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
+}
+
+/*****************************************************************************/
+/**
+*
+* Read the specified number of bytes from RX FIFO
+*
+* @param       InstancePtr is a pointer to the XQspiPsu instance.
+* @param       Msg is a pointer to the structure containing transfer data.
+* @param       Size is the number of bytes to be read.
+*
+* @return      None
+*
+* @note                None.
+*
+******************************************************************************/
+static inline void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr,
+                                       XQspiPsu_Msg *Msg, s32 Size)
+{
+       s32 Count = 0;
+       u32 Data;
+
+#ifdef DEBUG
+       xil_printf("\nXQspiPsu_ReadRxFifo\r\n");
+#endif
+
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(Msg != NULL);
+
+       while ((InstancePtr->RxBytes != 0) && (Count < Size)) {
+               Data = XQspiPsu_ReadReg(InstancePtr->
+                               Config.BaseAddress, XQSPIPSU_RXD_OFFSET);
+#ifdef DEBUG
+       xil_printf("\nData is %08x\r\n", Data);
+#endif
+               if (InstancePtr->RxBytes >= 4) {
+                       (void)memcpy(Msg->RxBfrPtr, &Data, 4);
+                       InstancePtr->RxBytes -= 4;
+                       Msg->RxBfrPtr += 4;
+                       Count += 4;
+               } else {
+                       /* Read unaligned bytes (< 4 bytes) */
+                       (void)memcpy(Msg->RxBfrPtr, &Data, InstancePtr->RxBytes);
+                       Msg->RxBfrPtr += InstancePtr->RxBytes;
+                       Count += InstancePtr->RxBytes;
+                       InstancePtr->RxBytes = 0;
+               }
+       }
+}
+
+/*****************************************************************************/
+/**
+*
+* This function enables the polling functionality of controller
+*
+* @param       QspiPsuPtr is a pointer to the XQspiPsu instance.
+*
+* @param       Statuscommand is the status command which send by controller.
+*
+* @param       FlashMsg is a pointer to the structure containing transfer data
+*
+* @return      None
+*
+* @note                None.
+*
+******************************************************************************/
+void XQspiPsu_PollData(XQspiPsu *QspiPsuPtr, XQspiPsu_Msg *FlashMsg)
+{
+
+       u32 GenFifoEntry ;
+       u32 Value;
+
+       Xil_AssertVoid(QspiPsuPtr != NULL);
+       Xil_AssertVoid(FlashMsg != NULL );
+
+       Value = XQspiPsu_Create_PollConfigData(QspiPsuPtr, FlashMsg);
+       XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress,
+                       XQSPIPSU_POLL_CFG_OFFSET, Value);
+       XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress,
+                       XQSPIPSU_P_TO_OFFSET, FlashMsg->PollTimeout);
+
+       XQspiPsu_Enable(QspiPsuPtr);
+
+       GenFifoEntry = (u32)0;
+       GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_TX;
+       GenFifoEntry |= QspiPsuPtr->GenFifoBus;
+       GenFifoEntry |= QspiPsuPtr->GenFifoCS;
+       GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI;
+       GenFifoEntry |= (u32)FlashMsg->PollStatusCmd;
+
+       XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress,
+               XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
+       XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+                               (XQSPIPSU_CFG_START_GEN_FIFO_MASK
+                               | XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK));
+
+       GenFifoEntry = (u32)0;
+       GenFifoEntry = (u32)XQSPIPSU_GENFIFO_POLL;
+       GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_RX;
+       GenFifoEntry |= QspiPsuPtr->GenFifoBus;
+       GenFifoEntry |= QspiPsuPtr->GenFifoCS;
+       GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI;
+       if (((FlashMsg->Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != FALSE)
+               GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE;
+       else
+               GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
+
+       XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress,
+               XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
+
+       QspiPsuPtr->Msg = FlashMsg;
+       QspiPsuPtr->NumMsg = (s32)1;
+       QspiPsuPtr->MsgCnt = 0;
+
+       Value = XQspiPsu_ReadReg(QspiPsuPtr->Config.BaseAddress,
+                       XQSPIPSU_CFG_OFFSET);
+       Value |= (XQSPIPSU_CFG_START_GEN_FIFO_MASK |
+                       XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK |
+                       XQSPIPSU_CFG_EN_POLL_TO_MASK);
+       XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+                       Value);
+
+       /* Enable interrupts */
+       Value = ((u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
+               (u32)XQSPIPSU_IER_TXEMPTY_MASK |
+               (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
+               (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
+               (u32)XQSPIPSU_IER_RXEMPTY_MASK |
+               (u32)XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK);
+       XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress, XQSPIPSU_IER_OFFSET,
+                       Value);
+}
+
+/*****************************************************************************/
+/**
+*
+* This function creates Poll config register data to write
+*
+* @param       BusMask is mask to enable/disable upper/lower data bus masks.
+*
+* @param       DataBusMask is Data bus mask value during poll operation.
+*
+* @param       Data is the poll data value to write into config regsiter.
+*
+* @return      None
+*
+* @note                None.
+*
+******************************************************************************/
+static inline u32 XQspiPsu_Create_PollConfigData(XQspiPsu *QspiPsuPtr,
+               XQspiPsu_Msg *FlashMsg)
+{
+       u32 ConfigData = 0;
+
+       if (QspiPsuPtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_UPPER)
+               ConfigData = XQSPIPSU_SELECT_FLASH_BUS_LOWER <<
+                                  XQSPIPSU_POLL_CFG_EN_MASK_UPPER_SHIFT;
+       if (QspiPsuPtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_LOWER)
+               ConfigData |= XQSPIPSU_SELECT_FLASH_BUS_LOWER <<
+                                  XQSPIPSU_POLL_CFG_EN_MASK_LOWER_SHIFT;
+       ConfigData |= ((FlashMsg->PollBusMask << XQSPIPSU_POLL_CFG_MASK_EN_SHIFT)
+                       & XQSPIPSU_POLL_CFG_MASK_EN_MASK);
+       ConfigData |= ((FlashMsg->PollData << XQSPIPSU_POLL_CFG_DATA_VALUE_SHIFT)
+                         & XQSPIPSU_POLL_CFG_DATA_VALUE_MASK);
+       return ConfigData;
+}
+
+/*****************************************************************************/
+/**
+* @brief
+* This API enables/ disables Write Protect pin on the flash parts.
+*
+* @param       QspiPtr is a pointer to the QSPIPSU driver component to use.
+*
+* @return      None
+*
+* @note        By default WP pin as per the QSPI controller is driven High
+*              which means no write protection. Calling this function once
+*              will enable the protection.
+*
+******************************************************************************/
+void XQspiPsu_WriteProtectToggle(XQspiPsu *QspiPsuPtr, u32 Toggle)
+{
+       /* For Single and Stacked flash configuration with x1 or x2 mode*/
+       if (QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_SINGLE) {
+               /* Enable */
+               XQspiPsu_Enable(QspiPsuPtr);
+
+               /* Select slave */
+               XQspiPsu_GenFifoEntryCSAssert(QspiPsuPtr);
+
+               XQspiPsu_WriteReg(QspiPsuPtr->Config.BaseAddress, XQSPIPSU_GPIO_OFFSET,
+                               Toggle);
+
+       } else if (QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_PARALLEL ||
+                       QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_STACKED) {
+               xil_printf("Dual Parallel/Stacked configuration is not supported by this API\r\n");
+       }
+}
+/** @} */