[PATCH 1/3] bsps: Import Xilinx GQSPI driver

Alex White alex.white at oarcorp.com
Mon Jan 23 19:52:05 UTC 2023


This adds Xilinx's driver for the Xilinx GQSPI controller embedded in
the ZynqMP SoC. Within that device alone, it is possible to access this
peripheral from MicroBlaze, ARMv7, and ARMv8 cores. The imported files
are and should be able to remain unmodified. Import information is kept
in bsps/shared/dev/spi/VERSION.
---
 bsps/include/dev/spi/xqspipsu.h              |  567 ++++++++++
 bsps/include/dev/spi/xqspipsu_control.h      |  102 ++
 bsps/include/dev/spi/xqspipsu_flash_config.h |  355 ++++++
 bsps/include/dev/spi/xqspipsu_hw.h           | 1006 +++++++++++++++++
 bsps/shared/dev/spi/VERSION                  |   29 +
 bsps/shared/dev/spi/xqspipsu.c               | 1048 ++++++++++++++++++
 bsps/shared/dev/spi/xqspipsu_control.c       |  282 +++++
 bsps/shared/dev/spi/xqspipsu_hw.c            |  768 +++++++++++++
 bsps/shared/dev/spi/xqspipsu_options.c       |  532 +++++++++
 9 files changed, 4689 insertions(+)
 create mode 100644 bsps/include/dev/spi/xqspipsu.h
 create mode 100644 bsps/include/dev/spi/xqspipsu_control.h
 create mode 100644 bsps/include/dev/spi/xqspipsu_flash_config.h
 create mode 100644 bsps/include/dev/spi/xqspipsu_hw.h
 create mode 100644 bsps/shared/dev/spi/VERSION
 create mode 100644 bsps/shared/dev/spi/xqspipsu.c
 create mode 100644 bsps/shared/dev/spi/xqspipsu_control.c
 create mode 100644 bsps/shared/dev/spi/xqspipsu_hw.c
 create mode 100644 bsps/shared/dev/spi/xqspipsu_options.c

diff --git a/bsps/include/dev/spi/xqspipsu.h b/bsps/include/dev/spi/xqspipsu.h
new file mode 100644
index 0000000000..7d9b662464
--- /dev/null
+++ b/bsps/include/dev/spi/xqspipsu.h
@@ -0,0 +1,567 @@
+/******************************************************************************
+* Copyright (C) 2014 - 2022 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+
+/*****************************************************************************/
+/**
+ *
+ * @file xqspipsu.h
+ * @addtogroup Overview
+ * @{
+ * @details
+ *
+ * This section explains the implementation the functions required to use the
+ * QSPIPSU hardware to perform a transfer. These are accessible to the user
+ * via xqspipsu.h.
+ *
+ * Generic QSPI interface allows for communication to any QSPI slave device.
+ * GQSPI contains a GENFIFO into which the bus transfers required are to be
+ * pushed with appropriate configuration. The controller provides TX and RX
+ * FIFO's and a DMA to be used for RX transfers. The controller executes each
+ * GENFIFO entry noting the configuration and places data on the bus as required
+ *
+ * The different options in GENFIFO are as follows:
+ * - IMM_DATA : Can be one byte of data to be transmitted, number of clocks or
+ *              number of bytes in transfer.
+ * - DATA_XFER : Indicates that data/clocks need to be transmitted or received.
+ * - EXPONENT : e when 2^e bytes are involved in transfer.
+ * - SPI_MODE : SPI/Dual SPI/Quad SPI
+ * - CS : Lower or Upper CS or Both
+ * - Bus : Lower or Upper Bus or Both
+ * - TX : When selected, controller transmits data in IMM or fetches number of
+ *        bytes mentioned form TX FIFO. If not selected, dummies are pumped.
+ * - RX : When selected, controller receives and fills the RX FIFO/allows RX DMA
+ *        of requested number of bytes. If not selected, RX data is discarded.
+ * - Stripe : Byte stripe over lower and upper bus or not.
+ * - Poll : Polls response to match for to a set value (used along with POLL_CFG
+ *          registers) and then proceeds to next GENFIFO entry.
+ *          This feature is not currently used in the driver.
+ *
+ * GENFIFO has manual and auto start options.
+ * All DMA requests need a 4-byte aligned destination address buffer and
+ * size of transfer should also be a multiple of 4.
+ * This driver supports DMA RX and IO RX.
+ *
+ * <b>Initialization & Configuration</b>
+ *
+ * This driver uses the GQSPI controller with RX DMA. It supports both
+ * interrupt and polled transfers. Manual start of GENFIFO is used.
+ * XQspiPsu_CfgInitialize() initializes the instance variables.
+ * Additional setting can be done using SetOptions/ClearOptions functions
+ * and SelectSlave function.
+ *
+ * <b>Transfer</b>
+ *
+ * Polled or Interrupt transfers can be done. The transfer function needs the
+ * message(s) to be transmitted in the form of an array of type XQspiPsu_Msg.
+ * This is supposed to contain the byte count and any TX/RX buffers as required.
+ * Flags can be used indicate further information such as whether the message
+ * should be striped. The transfer functions form and write GENFIFO entries,
+ * check the status of the transfer and report back to the application
+ * when done.
+ *
+ * <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 disable 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 Added LQSPI support
+ *                  Modified XQspiPsu_Select() macro in xqspipsu.h
+ *                  Added XQspiPsu_GetLqspiConfigReg() in xqspipsu.h
+ *                  Added required macros in xqspipsu_hw.h
+ *                  Modified XQspiPsu_SetOptions() to support
+ *                  LQSPI options and updated OptionsTable in
+ *                  xqspipsu_options.c
+ *       rk  07/15/16 Added support for TapDelays at different frequencies.
+ *     nsk 08/05/16 Added example support PollData and PollTimeout
+ *                  Added  XQSPIPSU_MSG_FLAG_POLL macro in xqspipsu.h
+ *                  Added XQspiPsu_Create_PollConfigData and
+ *                  XQspiPsu_PollData() functions in xqspipsu.c
+ * 1.3 nsk 09/16/16 Update PollData and Polltimeout support for dual parallel
+ *                  configuration. Updated XQspiPsu_PollData() and
+ *                  XQspiPsu_Create_PollConfigData() functions in xqspipsu.c
+ *                    and also modified the polldata example
+ *       ms  03/17/17 Added readme.txt file in examples folder for doxygen
+ *                    generation.
+ *       ms  04/05/17 Modified Comment lines in functions of qspipsu
+ *                    examples to recognize it as documentation block
+ *                    and modified filename tag to include them in
+ *                    doxygen examples.
+ * 1.4 tjs 05/26/17 Added support for accessing upper DDR (0x800000000)
+ *                  while booting images from QSPI
+ * 1.5 tjs 08/08/17 Added index.html file for importing examples
+ *                  from system.mss
+ * 1.5 nsk 08/14/17 Added CCI support
+ * 1.5 tjs 09/14/17 Modified the checks for 4 byte addressing and commands.
+ * 1.6 tjs 10/16/17 Flow for accessing flash is made similar to u-boot
+ *                  and linux For CR-984966
+ * 1.6   tjs 11/02/17 Resolved the compilation errors for ICCARM. CR-988625
+ * 1.7   tjs 11/16/17 Removed the unsupported 4 Byte write and sector erase
+ *                    commands.
+ * 1.7 tjs 12/01/17 Added support for MT25QL02G Flash from Micron. CR-990642
+ * 1.7 tjs 12/19/17 Added support for S25FL064L from Spansion. CR-990724
+ * 1.7 tjs 01/11/18 Added support for MX66L1G45G flash from Macronix CR-992367
+ * 1.7 tjs 01/16/18 Removed the check for DMA MSB to be written. (CR#992560)
+ * 1.7 tjs 01/17/18 Added support to toggle the WP pin of flash. (PR#2448)
+ *                    Added XQspiPsu_SetWP() in xqspipsu_options.c
+ *                    Added XQspiPsu_WriteProtectToggle() in xqspipsu.c and
+ *                    also added write protect example.
+ * 1.7 tjs 03/14/18 Added support in EL1 NS mode (CR#974882)
+ * 1.7 tjs 26/03/18 In dual parallel mode enable both CS when issuing Write
+ *                     enable command. CR-998478
+ * 1.8 tjs 05/02/18 Added support for IS25LP064 and IS25WP064.
+ * 1.8 tjs 06/26/18 Added an example for accessing 64bit dma within
+ *                  32 bit application. CR#1004701
+ * 1.8 tjs 06/26/18 Removed checkpatch warnings
+ * 1.8 tjs 07/09/19 Fixed cppcheck, doxygen and gcc warnings.
+ * 1.8 tjs 07/18/18 Setup64BRxDma() should be called only if the RxAddress is
+ *                  greater than 32 bit address space. (CR#1006862)
+ * 1.8 tjs 07/18/18 Added support for the low density ISSI flash parts.
+ * 1.8 tjs 09/06/18 Fixed the code in XQspiPsu_GenFifoEntryData() for data
+ *                  transfer length up to 255 for reducing the extra loop.
+ * 1.9 tjs 11/22/17 Added the check for A72 and R5 processors (CR-987075)
+ * 1.9 tjs 04/17/18 Updated register addresses as per the latest revision
+ *		    of versal (CR#999610)
+ * 1.9  aru 01/17/19 Fixed the violations for  MISRAC-2012
+ *                  in safety mode .Done changes such as added U suffix,
+ *                  Declared pointer param as const.
+ * 1.9  nsk 02/01/19 Clear DMA_DST_ADDR_MSB register on 32bit machine, if the
+ *		     address is of only 32bit (CR#1020031)
+ * 1.9  nsk 02/01/19 Added QSPI idling support
+ *
+ * 1.9 akm 03/08/19 Set recommended clock and data tap delay values for 40MHZ,
+ *                  100MHZ and 150MHZ frequencies(CR#1023187)
+ * 1.9  nsk 03/27/19 Update 64bit dma support
+ *		     (CR#1018102).
+ * 1.9  akm 04/03/19 Fixed data alignment warnings on IAR compiler.
+ * 1.9  akm 04/03/19 Fixed compilation error in XQspiPsu_LqspiRead()
+ *                     function on IAR compiler.
+ * 1.10 sk  08/20/19 Fixed issues in poll timeout feature.
+ * 1.10 akm 08/22/19 Set recommended tap delay values for 37.5MHZ, 100MHZ and
+ *		     150MHZ frequencies in Versal.
+ * 1.10 akm 09/05/19 Added Multi Die Erase and Muti Die Read support.
+ * 1.11 akm 11/07/19 Removed LQSPI register access in Versal.
+ * 1.11	akm 11/15/19 Fixed Coverity deadcode warning in
+ * 				XQspipsu_Calculate_Tapdelay().
+ * 1.11 akm 02/19/20 Added XQspiPsu_StartDmaTransfer() and XQspiPsu_CheckDmaDone()
+ * 		     APIs for non-blocking transfer.
+ * 1.11 sd  01/02/20 Added clocking support
+ * 1.11 akm 03/09/20 Reorganize the source code, enable qspi controller and
+ *		     interrupts in XQspiPsu_CfgInitialize() API.
+ * 1.11 akm 03/26/20 Fixed issue by updating XQspiPsu_CfgInitialize to return
+ *		     XST_DEVICE_IS_STARTED instead of asserting, when the
+ *		     instance is already configured(CR#1058525).
+ * 1.12	akm 09/02/20 Updated the Makefile to support parallel make execution.
+ * 1.13 akm 01/04/21 Fix MISRA-C violations.
+ * 1.13 sne 04/23/21 Fixed doxygen warnings.
+ * 1.14 akm 06/24/21 Allow enough time for the controller to reset the FIFOs.
+ * 1.14 akm 08/12/21 Perform Dcache invalidate at the end of the DMA transfer.
+ *
+ * </pre>
+ *
+ ******************************************************************************/
+
+#ifndef XQSPIPSU_H_		/**< prevent circular inclusions */
+#define XQSPIPSU_H_		/**< by using protection macros */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************** Include Files *********************************/
+
+#include "xstatus.h"
+#include "xqspipsu_hw.h"
+#include "xil_cache.h"
+#include "xil_mem.h"
+#if defined  (XCLOCKING)
+#include "xil_clocking.h"
+#endif
+
+/**************************** Type Definitions *******************************/
+/**
+ * The handler data type allows the user to define a callback function to
+ * handle the asynchronous processing for the QSPIPSU device.  The application
+ * using this driver is expected to define a handler of this type to support
+ * interrupt driven mode.  The handler executes in an interrupt context, so
+ * only minimal processing should be performed.
+ *
+ * @param	CallBackRef is the callback reference passed in by the upper
+ *		layer when setting the callback functions, and passed back to
+ *		the upper layer when the callback is invoked. Its type is
+ *		not important to the driver, so it is a void pointer.
+ * @param	StatusEvent holds one or more status events that have occurred.
+ *		See the XQspiPsu_SetStatusHandler() for details on the status
+ *		events that can be passed in the callback.
+ * @param	ByteCount indicates how many bytes of data were successfully
+ *		transferred.  This may be less than the number of bytes
+ *		requested if the status event indicates an error.
+ */
+typedef void (*XQspiPsu_StatusHandler) (const void *CallBackRef, u32 StatusEvent,
+					u32 ByteCount);
+
+/**
+ * This typedef contains configuration information for a flash message.
+ */
+typedef struct {
+	u8 *TxBfrPtr;	/**< Tx Buffer pointer */
+	u8 *RxBfrPtr;	/**< Rx Buffer pointer */
+	u32 ByteCount;	/**< Byte Count */
+	u32 BusWidth;	/**< Bus Width */
+	u32 Flags;	/**< Flags */
+	u8 PollData;	/**< Poll Data */
+	u32 PollTimeout;/**< Poll Timeout */
+	u8 PollStatusCmd; /**< Poll Status command */
+	u8 PollBusMask;	  /**< Poll Bus mask */
+	u64 RxAddr64bit;  /**< 64 bit Rx address */
+	u8 Xfer64bit;	  /**< 64 bit Tx address */
+} XQspiPsu_Msg;
+
+/**
+ * This typedef contains configuration information for the device.
+ */
+typedef struct {
+	u16 DeviceId;		/**< Unique ID  of device */
+	UINTPTR BaseAddress;	/**< Base address of the device */
+	u32 InputClockHz;	/**< Input clock frequency */
+	u8  ConnectionMode;	/**< Single, Stacked and Parallel mode */
+	u8  BusWidth;		/**< Bus width available on board */
+	u8 IsCacheCoherent;	/**< Describes whether Cache Coherent or not */
+#if defined  (XCLOCKING)
+	u32 RefClk;		/**< Input clocks */
+#endif
+} XQspiPsu_Config;
+
+/**
+ * The XQspiPsu driver instance data. The user is required to allocate a
+ * variable of this type for every QSPIPSU device in the system. A pointer
+ * to a variable of this type is then passed to the driver API functions.
+ */
+typedef struct {
+	XQspiPsu_Config Config;	 /**< Configuration structure */
+	u32 IsReady;		 /**< Device is initialized and ready */
+
+	u8 *SendBufferPtr;	 /**< Buffer to send (state) */
+	u8 *RecvBufferPtr;	 /**< Buffer to receive (state) */
+	u64 RecvBuffer;		 /**< Buffer Address to receive (state) */
+	u8 *GenFifoBufferPtr;	 /**< Gen FIFO entries */
+	s32 TxBytes;	 /**< Number of bytes to transfer (state) */
+	s32 RxBytes;	 /**< Number of bytes left to transfer(state) */
+	s32 GenFifoEntries;	 /**< Number of Gen FIFO entries remaining */
+	u32 IsBusy;		 /**< A transfer is in progress (state) */
+	u32 ReadMode;		 /**< DMA or IO mode */
+	u32 GenFifoCS;		/**< Gen FIFO chip selection */
+	u32 GenFifoBus;		/**< Gen FIFO bus */
+	s32 NumMsg;		/**< Number of messages */
+	s32 MsgCnt;		/**< Message Count */
+	s32 IsUnaligned;	/**< Unaligned information */
+	u8 IsManualstart;	/**< Manual start information */
+	XQspiPsu_Msg *Msg;	/**< Message */
+	XQspiPsu_StatusHandler StatusHandler;	/**< Status Handler */
+	void *StatusRef;	/**< Callback reference for status handler */
+} XQspiPsu;
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/**
+ * Definitions for Intel, STM, Winbond and Spansion Serial Flash Device
+ * geometry.
+ */
+#define BYTES256_PER_PAGE	256U		/**< 256 Bytes per Page */
+#define BYTES512_PER_PAGE	512U		/**< 512 Bytes per Page */
+#define BYTES1024_PER_PAGE	1024U		/**< 1024 Bytes per Page */
+#define PAGES16_PER_SECTOR	16U		/**< 16 Pages per Sector */
+#define PAGES128_PER_SECTOR	128U		/**< 128 Pages per Sector */
+#define PAGES256_PER_SECTOR	256U		/**< 256 Pages per Sector */
+#define PAGES512_PER_SECTOR	512U		/**< 512 Pages per Sector */
+#define PAGES1024_PER_SECTOR	1024U		/**< 1024 Pages per Sector */
+#define NUM_OF_SECTORS2		2U		/**< 2 Sectors */
+#define NUM_OF_SECTORS4		4U		/**< 4 Sectors */
+#define NUM_OF_SECTORS8		8U		/**< 8 Sector */
+#define NUM_OF_SECTORS16	16U		/**< 16 Sectors */
+#define NUM_OF_SECTORS32	32U		/**< 32 Sectors */
+#define NUM_OF_SECTORS64	64U		/**< 64 Sectors */
+#define NUM_OF_SECTORS128	128U		/**< 128 Sectors */
+#define NUM_OF_SECTORS256	256U		/**< 256 Sectors */
+#define NUM_OF_SECTORS512	512U		/**< 512 Sectors */
+#define NUM_OF_SECTORS1024	1024U		/**< 1024 Sectors */
+#define NUM_OF_SECTORS2048	2048U		/**< 2048 Sectors */
+#define NUM_OF_SECTORS4096	4096U		/**< 4096 Sectors */
+#define NUM_OF_SECTORS8192	8192U		/**< 8192 Sectors */
+#define SECTOR_SIZE_64K		0X10000U	/**< 64K Sector */
+#define SECTOR_SIZE_128K	0X20000U	/**< 128K Sector */
+#define SECTOR_SIZE_256K	0X40000U	/**< 256K Sector */
+#define SECTOR_SIZE_512K	0X80000U	/**< 512K Sector */
+
+
+#define XQSPIPSU_READMODE_DMA	0x0U	/**< DMA read mode */
+#define XQSPIPSU_READMODE_IO	0x1U	/**< IO read mode */
+
+#define XQSPIPSU_SELECT_FLASH_CS_LOWER	0x1U	/**< Select lower flash */
+#define XQSPIPSU_SELECT_FLASH_CS_UPPER	0x2U	/**< Select upper flash */
+#define XQSPIPSU_SELECT_FLASH_CS_BOTH	0x3U	/**< Select both flash */
+
+#define XQSPIPSU_SELECT_FLASH_BUS_LOWER	0x1U	/**< Select lower bus flash */
+#define XQSPIPSU_SELECT_FLASH_BUS_UPPER	0x2U	/**< Select upper bus flash */
+#define XQSPIPSU_SELECT_FLASH_BUS_BOTH	0x3U	/**< Select both bus flash */
+
+#define XQSPIPSU_SELECT_MODE_SPI	0x1U	/**< Select SPI mode */
+#define XQSPIPSU_SELECT_MODE_DUALSPI	0x2U	/**< Select dual SPI mode */
+#define XQSPIPSU_SELECT_MODE_QUADSPI	0x4U	/**< Select quad SPI mode */
+
+#define XQSPIPSU_GENFIFO_CS_SETUP	0x05U	/**< Chip select setup in GENFIO */
+#define XQSPIPSU_GENFIFO_CS_HOLD	0x04U	/**< Chip select hold in GENFIFO */
+
+#define XQSPIPSU_CLK_ACTIVE_LOW_OPTION	0x2U	/**< Clk Active low option */
+#define XQSPIPSU_CLK_PHASE_1_OPTION	0x4U	/**< Clk phase 1 option */
+#define XQSPIPSU_MANUAL_START_OPTION	0x8U	/**< Manual start option */
+#if !defined (versal)
+#define XQSPIPSU_LQSPI_MODE_OPTION	0x20U	/**< LQSPI mode option */
+
+#define XQSPIPSU_LQSPI_LESS_THEN_SIXTEENMB	1U /**< LQSPI less Than 16 MB */
+#endif
+
+#define XQSPIPSU_GENFIFO_EXP_START	0x100U /**< Genfifo start */
+
+#define XQSPIPSU_DMA_BYTES_MAX		0x10000000U /**< DMA bytes max */
+
+#define XQSPIPSU_CLK_PRESCALE_2		0x00U	/**< Clock prescale 2 */
+#define XQSPIPSU_CLK_PRESCALE_4		0x01U	/**< Clock prescale 4 */
+#define XQSPIPSU_CLK_PRESCALE_8		0x02U	/**< Clock prescale 8 */
+#define XQSPIPSU_CLK_PRESCALE_16	0x03U	/**< Clock prescale 16 */
+#define XQSPIPSU_CLK_PRESCALE_32	0x04U	/**< Clock prescale 32 */
+#define XQSPIPSU_CLK_PRESCALE_64	0x05U	/**< Clock prescale 64 */
+#define XQSPIPSU_CLK_PRESCALE_128	0x06U	/**< Clock prescale 128 */
+#define XQSPIPSU_CLK_PRESCALE_256	0x07U	/**< Clock prescale 256 */
+#define XQSPIPSU_CR_PRESC_MAXIMUM	7U	/**< Prescale max */
+
+#define XQSPIPSU_CONNECTION_MODE_SINGLE		0U /**< Single mode connection */
+#define XQSPIPSU_CONNECTION_MODE_STACKED	1U /**< Stacked mode connection */
+#define XQSPIPSU_CONNECTION_MODE_PARALLEL	2U /**< Parallel mode connection */
+
+/*QSPI Frequencies*/
+#define XQSPIPSU_FREQ_37_5MHZ 37500000U	/**< Frequency 375 Mhz */
+#define XQSPIPSU_FREQ_40MHZ 40000000U	/**< Frequency 40 Mhz */
+#define XQSPIPSU_FREQ_100MHZ 100000000U	/**< Frequency 100 Mhz */
+#define XQSPIPSU_FREQ_150MHZ 150000000U	/**< Frequency 150 Mhz */
+
+/* Add more flags as required */
+#define XQSPIPSU_MSG_FLAG_STRIPE	0x1U /**< Stripe Msg flag */
+#define XQSPIPSU_MSG_FLAG_RX		0x2U /**< Rx Msg flag */
+#define XQSPIPSU_MSG_FLAG_TX		0x4U /**< Tx Msg flag */
+#define XQSPIPSU_MSG_FLAG_POLL		0x8U /**< POLL Msg flag */
+
+#define XQSPIPSU_RXADDR_OVER_32BIT	0x100000000U /**< Rx address over 32 bit */
+
+#define XQSPIPSU_SET_WP		1 /**< GQSPI configuration to toggle WP of flash */
+
+/**
+ * select QSPI controller
+ */
+#define XQspiPsu_Select(InstancePtr, Mask)	\
+	XQspiPsu_Out32(((InstancePtr)->Config.BaseAddress) + \
+			XQSPIPSU_SEL_OFFSET, (Mask))
+
+/**
+ * Enable QSPI Controller
+ */
+#define XQspiPsu_Enable(InstancePtr)	\
+	XQspiPsu_Out32(((InstancePtr)->Config.BaseAddress) + \
+			XQSPIPSU_EN_OFFSET, XQSPIPSU_EN_MASK)
+
+/**
+ * Disable QSPI controller  */
+#define XQspiPsu_Disable(InstancePtr)	\
+	XQspiPsu_Out32(((InstancePtr)->Config.BaseAddress) + \
+			XQSPIPSU_EN_OFFSET, 0x0U)
+
+/**
+ * Read Configuration register of LQSPI Controller
+ */
+#if !defined (versal)
+#define XQspiPsu_GetLqspiConfigReg(InstancePtr)	\
+	XQspiPsu_In32((XQSPIPS_BASEADDR) + \
+			XQSPIPSU_LQSPI_CR_OFFSET)
+#endif
+
+/*****************************************************************************/
+/**
+ *
+ * This function enables the manual start option
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @return	None
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+static inline void XQspiPsu_ManualStartEnable(XQspiPsu *InstancePtr)
+{
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_ManualStartEnable\r\n");
+#endif
+
+	if (InstancePtr->IsManualstart == (u8)TRUE) {
+#ifdef DEBUG
+		xil_printf("\nManual Start\r\n");
+#endif
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+		XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) |
+			XQSPIPSU_CFG_START_GEN_FIFO_MASK);
+	}
+}
+/*****************************************************************************/
+/**
+ *
+ * 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(const XQspiPsu *InstancePtr)
+{
+	u32 GenFifoEntry;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_GenFifoEntryCSAssert\r\n");
+#endif
+
+	GenFifoEntry = 0x0U;
+	GenFifoEntry |= (XQSPIPSU_GENFIFO_MODE_SPI | InstancePtr->GenFifoCS |
+					 InstancePtr->GenFifoBus | 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 entry to de-assert CS.
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @return	None
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+static inline void XQspiPsu_GenFifoEntryCSDeAssert(const XQspiPsu *InstancePtr)
+{
+	u32 GenFifoEntry;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_GenFifoEntryCSDeAssert\r\n");
+#endif
+
+	GenFifoEntry = 0x0U;
+	GenFifoEntry |= (XQSPIPSU_GENFIFO_MODE_SPI | InstancePtr->GenFifoBus |
+					XQSPIPSU_GENFIFO_CS_HOLD);
+#ifdef DEBUG
+	xil_printf("\nFifoEntry=%08x\r\n", GenFifoEntry);
+#endif
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+		XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
+}
+
+/*****************************************************************************/
+/**
+ *
+ * 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 inline void StubStatusHandler(const void *CallBackRef, u32 StatusEvent,
+				u32 ByteCount)
+{
+	(const void) CallBackRef;
+	(void) StatusEvent;
+	(void) ByteCount;
+
+	Xil_AssertVoidAlways();
+}
+/************************** Function Prototypes ******************************/
+
+/* Initialization and reset */
+XQspiPsu_Config *XQspiPsu_LookupConfig(u16 DeviceId);
+s32 XQspiPsu_CfgInitialize(XQspiPsu *InstancePtr,
+			   const XQspiPsu_Config *ConfigPtr,
+			   UINTPTR EffectiveAddr);
+void XQspiPsu_Reset(XQspiPsu *InstancePtr);
+void XQspiPsu_Abort(XQspiPsu *InstancePtr);
+
+/* Transfer functions and handlers */
+s32 XQspiPsu_PolledTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+				u32 NumMsg);
+s32 XQspiPsu_InterruptTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+				u32 NumMsg);
+s32 XQspiPsu_InterruptHandler(XQspiPsu *InstancePtr);
+void XQspiPsu_SetStatusHandler(XQspiPsu *InstancePtr, void *CallBackRef,
+				XQspiPsu_StatusHandler FuncPointer);
+
+/* Non blocking Transfer functions */
+s32 XQspiPsu_StartDmaTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+				u32 NumMsg);
+s32 XQspiPsu_CheckDmaDone(XQspiPsu *InstancePtr);
+
+/* Configuration functions */
+s32 XQspiPsu_SetClkPrescaler(const XQspiPsu *InstancePtr, u8 Prescaler);
+void XQspiPsu_SelectFlash(XQspiPsu *InstancePtr, u8 FlashCS, u8 FlashBus);
+s32 XQspiPsu_SetOptions(XQspiPsu *InstancePtr, u32 Options);
+s32 XQspiPsu_ClearOptions(XQspiPsu *InstancePtr, u32 Options);
+u32 XQspiPsu_GetOptions(const XQspiPsu *InstancePtr);
+s32 XQspiPsu_SetReadMode(XQspiPsu *InstancePtr, u32 Mode);
+void XQspiPsu_SetWP(const XQspiPsu *InstancePtr, u8 Value);
+void XQspiPsu_WriteProtectToggle(const XQspiPsu *InstancePtr, u32 Toggle);
+void XQspiPsu_Idle(const XQspiPsu *InstancePtr);
+
+/************************** Variable Prototypes ******************************/
+
+/**
+ * This table contains configuration information for each QSPIPSU device
+ * in the system.
+ */
+#ifndef __rtems__
+extern XQspiPsu_Config XQspiPsu_ConfigTable[XPAR_XQSPIPSU_NUM_INSTANCES];
+#endif /* __rtems__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* XQSPIPSU_H_ */
+/** @} */
diff --git a/bsps/include/dev/spi/xqspipsu_control.h b/bsps/include/dev/spi/xqspipsu_control.h
new file mode 100644
index 0000000000..76b0a8ce7c
--- /dev/null
+++ b/bsps/include/dev/spi/xqspipsu_control.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+* Copyright (C) 2020 - 2022 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+
+/*****************************************************************************/
+/**
+ *
+ * @file xqspipsu_control.h
+ * @addtogroup Overview
+ * @{
+ *
+ * This is the header file for the implementation of QSPIPSU driver.
+ * Generic QSPI interface allows for communication to any QSPI slave device.
+ * GQSPI contains a GENFIFO into which the bus transfers required are to be
+ * pushed with appropriate configuration. The controller provides TX and RX
+ * FIFO's and a DMA to be used for RX transfers. The controller executes each
+ * GENFIFO entry noting the configuration and places data on the bus as required
+ *
+ *
+ * <pre>
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who Date     Changes
+ * ----- --- -------- -----------------------------------------------.
+ * 1.11   akm  03/09/20 First release
+ * 1.13   akm  01/04/21 Fix MISRA-C violations.
+ * 1.15   akm  03/03/22 Enable tapdelay settings for applications on
+ * 			 Microblaze platform.
+ *
+ * </pre>
+ *
+ ******************************************************************************/
+
+/** @cond INTERNAL */
+#ifndef XQSPIPSU_CONTROL_H_		/**< prevent circular inclusions */
+#define XQSPIPSU_CONTROL_H_		/**< by using protection macros */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************** Include Files *********************************/
+
+#include "xqspipsu.h"
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+#if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__)
+#define TAPDLY_BYPASS_VALVE_40MHZ 0x01U
+#define TAPDLY_BYPASS_VALVE_100MHZ 0x01U
+#define USE_DLY_LPBK  0x01U
+#define USE_DATA_DLY_ADJ 0x01U
+#define DATA_DLY_ADJ_DLY 0X02U
+#define LPBK_DLY_ADJ_DLY0 0X02U
+#define LPBK_DLY_ADJ_DLY1 0X02U
+#endif
+
+#ifdef __MICROBLAZE__
+#define XPS_SYS_CTRL_BASEADDR   0xFF180000U     /**< System controller Baseaddress */
+#endif
+/************************** Function Prototypes ******************************/
+void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg);
+u32 XQspiPsu_SetIOMode(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg);
+void XQspiPsu_IORead(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+		u32 StatusReg);
+void XQspiPsu_PollDataConfig(XQspiPsu *InstancePtr, XQspiPsu_Msg *FlashMsg);
+void XQspiPsu_TXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg);
+void XQspiPsu_SetupRxDma(const XQspiPsu *InstancePtr,
+					XQspiPsu_Msg *Msg);
+void XQspiPsu_Setup64BRxDma(const XQspiPsu *InstancePtr,
+					XQspiPsu_Msg *Msg);
+void XQspiPsu_RXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg);
+void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+					u32 *GenFifoEntry);
+void XQspiPsu_GenFifoEntryDataLen(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+		u32 *GenFifoEntry);
+u32 XQspiPsu_CreatePollDataConfig(const XQspiPsu *InstancePtr,
+		const XQspiPsu_Msg *FlashMsg);
+void XQspiPsu_PollDataHandler(XQspiPsu *InstancePtr, u32 StatusReg);
+u32 XQspiPsu_SelectSpiMode(u8 SpiMode);
+void XQspiPsu_SetDefaultConfig(XQspiPsu *InstancePtr);
+void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg, u32 Size);
+void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr,	XQspiPsu_Msg *Msg, s32 Size);
+
+#if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__)
+s32 XQspipsu_Set_TapDelay(const XQspiPsu *InstancePtr, u32 TapdelayBypass,
+						u32 LPBKDelay, u32 Datadelay);
+s32 XQspipsu_Calculate_Tapdelay(const XQspiPsu *InstancePtr, u8 Prescaler);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* XQSPIPSU_CONTROL_H_ */
+/** @endcond */
+/** @} */
diff --git a/bsps/include/dev/spi/xqspipsu_flash_config.h b/bsps/include/dev/spi/xqspipsu_flash_config.h
new file mode 100644
index 0000000000..323b223ee3
--- /dev/null
+++ b/bsps/include/dev/spi/xqspipsu_flash_config.h
@@ -0,0 +1,355 @@
+/******************************************************************************
+* Copyright (C) 2020 - 2022 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xqspipsu_flash_config.h
+*
+*
+* This file contains flash configuration table and flash related defines.
+* This file should be included in the example files and compiled along with
+* the examples (*.c).
+*
+* @note
+*
+* None.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.12  akm 07/07/20 First release
+* 1.12	akm 07/07/20 Add support for Macronix flash(MX66U2G45G, MX66L2G45G)
+*                    and ISSI flash(IS25LP01G, IS25WP01G) parts.
+* 1.13  akm 12/10/20 Set Read command as per the qspi bus width.
+* 1.14  akm 07/16/21 Enable Quad Mode for Winbond flashes.
+* 1.15  akm 11/19/21 Fix read/write failures on Spansion flash parts.
+*
+*</pre>
+*
+ ******************************************************************************/
+
+#ifndef XQSPIPSU_FLASH_CONFIG_H_		/* prevent circular inclusions */
+#define XQSPIPSU_FLASH_CONFIG_H_		/* by using protection macros */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************** Include Files *********************************/
+
+#include "xparameters.h"	/* SDK generated parameters */
+#include "xqspipsu.h"		/* QSPIPSU device driver */
+
+/************************** Constant Definitions *****************************/
+
+/*
+ * The following constants define the commands which may be sent to the Flash
+ * device.
+ */
+#define WRITE_STATUS_CMD	0x01
+#define WRITE_CMD		0x02
+#define READ_CMD		0x03
+#define WRITE_DISABLE_CMD	0x04
+#define READ_STATUS_CMD		0x05
+#define WRITE_ENABLE_CMD	0x06
+#define VOLATILE_WRITE_ENABLE_CMD	0x50
+#define QUAD_MODE_ENABLE_BIT	0x06
+#define FAST_READ_CMD		0x0B
+#define DUAL_READ_CMD		0x3B
+#define QUAD_READ_CMD		0x6B
+#define BULK_ERASE_CMD		0xC7
+#define	SEC_ERASE_CMD		0xD8
+#define READ_ID			0x9F
+#define READ_CONFIG_CMD		0x35
+#define WRITE_CONFIG_CMD	0x01
+#define ENTER_4B_ADDR_MODE	0xB7
+#define EXIT_4B_ADDR_MODE	0xE9
+#define EXIT_4B_ADDR_MODE_ISSI	0x29
+/* 4-byte address opcodes */
+#define READ_CMD_4B			0x13
+#define FAST_READ_CMD_4B		0x0C
+#define DUAL_READ_CMD_4B		0x3C
+#define QUAD_READ_CMD_4B		0x6C
+#define WRITE_CMD_4B			0x12
+#define SEC_ERASE_CMD_4B		0xDC
+
+#define BANK_REG_RD		0x16
+#define BANK_REG_WR		0x17
+/* Bank register is called Extended Address Register in Micron */
+#define EXTADD_REG_RD		0xC8
+#define EXTADD_REG_WR		0xC5
+#define	DIE_ERASE_CMD		0xC4
+#define READ_FLAG_STATUS_CMD	0x70
+
+#define WRITE_STATUS_REG_2_CMD	0x31
+#define READ_STATUS_REG_2_CMD	0x35
+#define WB_QUAD_MODE_ENABLE_BIT	0x01
+
+/*
+ * The following constants define the offsets within a FlashBuffer data
+ * type for each kind of data.  Note that the read data offset is not the
+ * same as the write data because the QSPIPSU driver is designed to allow full
+ * duplex transfers such that the number of bytes received is the number
+ * sent and received.
+ */
+#define COMMAND_OFFSET		0 /* Flash instruction */
+#define ADDRESS_1_OFFSET	1 /* MSB byte of address to read or write */
+#define ADDRESS_2_OFFSET	2 /* Middle byte of address to read or write */
+#define ADDRESS_3_OFFSET	3 /* LSB byte of address to read or write */
+#define ADDRESS_4_OFFSET	4 /* LSB byte of address to read or write
+				   * when 4 byte address
+				   */
+#define DATA_OFFSET		5 /* Start of Data for Read/Write */
+#define DUMMY_OFFSET		4 /* Dummy byte offset for fast, dual and quad
+				   * reads
+				   */
+#define DUMMY_SIZE		1 /* Number of dummy bytes for fast, dual and
+				   * quad reads
+				   */
+#define DUMMY_CLOCKS		8 /* Number of dummy bytes for fast, dual and
+				   * quad reads
+				   */
+#define RD_ID_SIZE		4 /* Read ID command + 3 bytes ID response */
+#define BULK_ERASE_SIZE		1 /* Bulk Erase command size */
+#define SEC_ERASE_SIZE		4 /* Sector Erase command + Sector address */
+#define BANK_SEL_SIZE		2 /* BRWR or EARWR command + 1 byte bank
+				   * value
+				   */
+#define RD_CFG_SIZE		2 /* 1 byte Configuration register + RD CFG
+				   * command
+				   */
+#define WR_CFG_SIZE		3 /* WRR command + 1 byte each Status and
+				   * Config Reg
+				   */
+#define DIE_ERASE_SIZE	4	/* Die Erase command + Die address */
+
+/*
+ * The following constants specify the extra bytes which are sent to the
+ * Flash on the QSPIPSu interface, that are not data, but control information
+ * which includes the command and address
+ */
+#define OVERHEAD_SIZE		4
+
+/*
+ * Base address of Flash1
+ */
+#define FLASH1BASE 0x0000000
+
+/*
+ * Sixteen MB
+ */
+#define SIXTEENMB 0x1000000
+
+
+/*
+ * Mask for quad enable bit in Flash configuration register
+ */
+#define FLASH_QUAD_EN_MASK 0x02
+
+#define FLASH_SRWD_MASK 0x80
+
+/*
+ * Bank mask
+ */
+#define BANKMASK 0xF000000
+
+/*
+ * Bus width
+ */
+#define BUSWIDTH_SINGLE	0
+#define BUSWIDTH_DOUBLE	1
+
+/*
+ * Identification of Flash
+ * Micron:
+ * Byte 0 is Manufacturer ID;
+ * Byte 1 is first byte of Device ID - 0xBB or 0xBA
+ * Byte 2 is second byte of Device ID describes flash size:
+ * 128Mbit : 0x18; 256Mbit : 0x19; 512Mbit : 0x20
+ * Spansion:
+ * Byte 0 is Manufacturer ID;
+ * Byte 1 is Device ID - Memory Interface type - 0x20 or 0x02
+ * Byte 2 is second byte of Device ID describes flash size:
+ * 128Mbit : 0x18; 256Mbit : 0x19; 512Mbit : 0x20
+ */
+#define MICRON_ID_BYTE0		0x20
+#define SPANSION_ID_BYTE0	0x01
+#define WINBOND_ID_BYTE0	0xEF
+#define MACRONIX_ID_BYTE0	0xC2
+#define ISSI_ID_BYTE0		0x9D
+
+/**************************** Type Definitions *******************************/
+
+typedef struct{
+	u32 jedec_id;	/* JEDEC ID */
+
+	u32 SectSize;		/* Individual sector size or combined sector
+				 * size in case of parallel config
+				 */
+	u32 NumSect;		/* Total no. of sectors in one/two
+				 * flash devices
+				 */
+	u32 PageSize;		/* Individual page size or
+				 * combined page size in case of parallel
+				 * config
+				 */
+	u32 NumPage;		/* Total no. of pages in one/two flash
+				 * devices
+				 */
+	u32 FlashDeviceSize;	/* This is the size of one flash device
+				 * NOT the combination of both devices,
+				 * if present
+				 */
+	u32 SectMask;		/* Mask to get sector start address */
+	u8 NumDie;		/* No. of die forming a single flash */
+} FlashInfo;
+
+/************************** Variable Definitions *****************************/
+FlashInfo Flash_Config_Table[] = {
+	/* Spansion */
+	/*s25fl064l*/
+	{0x016017, SECTOR_SIZE_64K, NUM_OF_SECTORS128, BYTES256_PER_PAGE,
+		0x8000, 0x800000, 0xFFFF0000, 1},
+	/*s25fl128l*/
+	{0x016018, SECTOR_SIZE_64K, NUM_OF_SECTORS256, BYTES256_PER_PAGE,
+		0x10000, 0x1000000, 0xFFFF0000, 1},
+	/*s25fl256l*/
+	{0x016019, SECTOR_SIZE_64K, NUM_OF_SECTORS512, BYTES256_PER_PAGE,
+		0x20000, 0x2000000, 0xFFFF0000, 1},
+	/*s25fl512s*/
+	{0x010220, SECTOR_SIZE_64K, NUM_OF_SECTORS1024, BYTES256_PER_PAGE,
+		0x40000, 0x4000000, 0xFFFF0000, 1},
+	/* Spansion 1Gbit is handled as 512Mbit stacked */
+	/* Micron */
+	/*n25q128a11*/
+	{0x20bb18, SECTOR_SIZE_64K, NUM_OF_SECTORS256, BYTES256_PER_PAGE,
+		0x10000, 0x1000000, 0xFFFF0000, 1},
+	/*n25q128a13*/
+	{0x20ba18, SECTOR_SIZE_64K, NUM_OF_SECTORS256, BYTES256_PER_PAGE,
+		0x10000, 0x1000000, 0xFFFF0000, 1},
+	/*n25q256ax1*/
+	{0x20bb19, SECTOR_SIZE_64K, NUM_OF_SECTORS512, BYTES256_PER_PAGE,
+		0x20000, 0x2000000, 0xFFFF0000, 1},
+	/*n25q256a*/
+	{0x20ba19, SECTOR_SIZE_64K, NUM_OF_SECTORS512, BYTES256_PER_PAGE,
+		0x20000, 0x2000000, 0xFFFF0000, 1},
+	/*mt25qu512a*/
+	{0x20bb20, SECTOR_SIZE_64K, NUM_OF_SECTORS1024, BYTES256_PER_PAGE,
+		0x40000, 0x4000000, 0xFFFF0000, 2},
+	/*n25q512ax3*/
+	{0x20ba20, SECTOR_SIZE_64K, NUM_OF_SECTORS1024, BYTES256_PER_PAGE,
+		0x40000, 0x4000000, 0xFFFF0000, 2},
+	/*n25q00a*/
+	{0x20bb21, SECTOR_SIZE_64K, NUM_OF_SECTORS2048, BYTES256_PER_PAGE,
+		0x80000, 0x8000000, 0xFFFF0000, 4},
+	/*n25q00*/
+	{0x20ba21, SECTOR_SIZE_64K, NUM_OF_SECTORS2048, BYTES256_PER_PAGE,
+		0x80000, 0x8000000, 0xFFFF0000, 4},
+	/*mt25qu02g*/
+	{0x20bb22, SECTOR_SIZE_64K, NUM_OF_SECTORS4096, BYTES256_PER_PAGE,
+		0x100000, 0x10000000, 0xFFFF0000, 4},
+	/*mt25ql02g*/
+	{0x20ba22, SECTOR_SIZE_64K, NUM_OF_SECTORS4096, BYTES256_PER_PAGE,
+		0x100000, 0x10000000, 0xFFFF0000, 4},
+	/* Winbond */
+	/*w25q128fw*/
+	{0xef6018, SECTOR_SIZE_64K, NUM_OF_SECTORS256, BYTES256_PER_PAGE,
+		0x10000, 0x1000000, 0xFFFF0000, 1},
+	/*w25q128jv*/
+	{0xef7018, SECTOR_SIZE_64K, NUM_OF_SECTORS256, BYTES256_PER_PAGE,
+		0x10000, 0x1000000, 0xFFFF0000, 1},
+	/*w25h02jv*/
+	{0xef9022, SECTOR_SIZE_64K, NUM_OF_SECTORS4096, BYTES256_PER_PAGE,
+		0x100000, 0x10000000, 0xFFFF0000, 4},
+	/* Macronix */
+	/*mx66l1g45g*/
+	{0xc2201b, SECTOR_SIZE_64K, NUM_OF_SECTORS2048, BYTES256_PER_PAGE,
+		0x80000, 0x8000000, 0xFFFF0000, 4},
+	/*mx66l1g55g*/
+	{0xc2261b, SECTOR_SIZE_64K, NUM_OF_SECTORS2048, BYTES256_PER_PAGE,
+		0x80000, 0x8000000, 0xFFFF0000, 4},
+	/*mx66u1g45g*/
+	{0xc2253b, SECTOR_SIZE_64K, NUM_OF_SECTORS2048, BYTES256_PER_PAGE,
+		0x80000, 0x8000000, 0xFFFF0000, 4},
+	/*mx66l2g45g*/
+	{0xc2201c, SECTOR_SIZE_64K, NUM_OF_SECTORS4096, BYTES256_PER_PAGE,
+		0x100000, 0x10000000, 0xFFFF0000, 1},
+	/*mx66u2g45g*/
+	{0xc2253c, SECTOR_SIZE_64K, NUM_OF_SECTORS4096, BYTES256_PER_PAGE,
+		0x100000, 0x10000000, 0xFFFF0000, 1},
+	/* ISSI */
+	/*is25wp080d*/
+	{0x9d7014, SECTOR_SIZE_64K, NUM_OF_SECTORS16, BYTES256_PER_PAGE,
+		0x1000, 0x100000, 0xFFFF0000, 1},
+	/*is25lp080d*/
+	{0x9d6014, SECTOR_SIZE_64K, NUM_OF_SECTORS16, BYTES256_PER_PAGE,
+		0x1000, 0x100000, 0xFFFF0000, 1},
+	/*is25wp016d*/
+	{0x9d7015, SECTOR_SIZE_64K, NUM_OF_SECTORS32, BYTES256_PER_PAGE,
+		0x2000, 0x200000, 0xFFFF0000, 1},
+	/*is25lp016d*/
+	{0x9d6015, SECTOR_SIZE_64K, NUM_OF_SECTORS32, BYTES256_PER_PAGE,
+		0x2000, 0x200000, 0xFFFF0000, 1},
+	/*is25wp032*/
+	{0x9d7016, SECTOR_SIZE_64K, NUM_OF_SECTORS64, BYTES256_PER_PAGE,
+		0x4000, 0x400000, 0xFFFF0000, 1},
+	/*is25lp032*/
+	{0x9d6016, SECTOR_SIZE_64K, NUM_OF_SECTORS64, BYTES256_PER_PAGE,
+		0x4000, 0x400000, 0xFFFF0000, 1},
+	/*is25wp064*/
+	{0x9d7017, SECTOR_SIZE_64K, NUM_OF_SECTORS128, BYTES256_PER_PAGE,
+		0x8000, 0x800000, 0xFFFF0000, 1},
+	/*is25lp064*/
+	{0x9d6017, SECTOR_SIZE_64K, NUM_OF_SECTORS128, BYTES256_PER_PAGE,
+		0x8000, 0x800000, 0xFFFF0000, 1},
+	/*is25wp128*/
+	{0x9d7018, SECTOR_SIZE_64K, NUM_OF_SECTORS256, BYTES256_PER_PAGE,
+		0x10000, 0x1000000, 0xFFFF0000, 1},
+	/*is25lp128*/
+	{0x9d6018, SECTOR_SIZE_64K, NUM_OF_SECTORS256, BYTES256_PER_PAGE,
+		0x10000, 0x1000000, 0xFFFF0000, 1},
+	/*is25lp256d*/
+	{0x9d6019, SECTOR_SIZE_64K, NUM_OF_SECTORS512, BYTES256_PER_PAGE,
+		0x20000, 0x2000000, 0xFFFF0000, 1},
+	/*is25wp256d*/
+	{0x9d7019, SECTOR_SIZE_64K, NUM_OF_SECTORS512, BYTES256_PER_PAGE,
+		0x20000, 0x2000000, 0xFFFF0000, 1},
+	/*is25lp512m*/
+	{0x9d601a, SECTOR_SIZE_64K, NUM_OF_SECTORS1024, BYTES256_PER_PAGE,
+		0x40000, 0x4000000, 0xFFFF0000, 2},
+	/*is25wp512m*/
+	{0x9d701a, SECTOR_SIZE_64K, NUM_OF_SECTORS1024, BYTES256_PER_PAGE,
+		0x40000, 0x4000000, 0xFFFF0000, 2},
+	/*is25lp01g*/
+	{0x9d601b, SECTOR_SIZE_64K, NUM_OF_SECTORS2048, BYTES256_PER_PAGE,
+		0x80000, 0x8000000, 0xFFFF0000, 1},
+	/*is25wp01g*/
+	{0x9d701b, SECTOR_SIZE_64K, NUM_OF_SECTORS2048, BYTES256_PER_PAGE,
+		0x80000, 0x8000000, 0xFFFF0000, 1}
+};
+
+static INLINE u32 CalculateFCTIndex(u32 ReadId, u32 *FCTIndex)
+{
+	u32 Index;
+
+	for (Index = 0; Index < sizeof(Flash_Config_Table)/sizeof(Flash_Config_Table[0]);
+				Index++) {
+		if (ReadId == Flash_Config_Table[Index].jedec_id) {
+			*FCTIndex = Index;
+			return XST_SUCCESS;
+		}
+	}
+
+	return XST_FAILURE;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* XQSPIPSU_FLASH_CONFIG_H_ */
+/** @} */
diff --git a/bsps/include/dev/spi/xqspipsu_hw.h b/bsps/include/dev/spi/xqspipsu_hw.h
new file mode 100644
index 0000000000..a798f9bb89
--- /dev/null
+++ b/bsps/include/dev/spi/xqspipsu_hw.h
@@ -0,0 +1,1006 @@
+/******************************************************************************
+* Copyright (C) 2014 - 2022 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xqspipsu_hw.h
+* @addtogroup Overview
+* @{
+*
+* This file contains low level access functions using the base address
+* directly without an instance.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------.
+* 1.0   hk  08/21/14 First release
+*       hk  03/18/15 Add DMA status register masks required.
+*       sk  04/24/15 Modified the code according to MISRAC-2012.
+* 1.2	nsk 07/01/16 Added LQSPI supported Masks
+*       rk  07/15/16 Added support for TapDelays at different frequencies.
+* 1.7	tjs	03/14/18 Added support in EL1 NS mode.
+* 1.9	tjs	04/17/18 Updated register addresses as per the latest revision
+* 					 of versal (CR#999610)
+* 1.9  aru 01/17/19 Fixed the violations for  MISRAC-2012
+*                  in safety mode .Done changes such as added U suffix
+* 1.11	akm 11/07/19 Removed LQSPI register access in Versal.
+* 1.15	akm 12/02/21 Fix Doxygen warnings.
+*
+* </pre>
+*
+******************************************************************************/
+#ifndef XQSPIPSU_HW_H		/**< prevent circular inclusions */
+#define XQSPIPSU_HW_H		/**< by using protection macros */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************** Include Files *********************************/
+
+#include "xil_types.h"
+#include "xil_assert.h"
+#include "xil_io.h"
+#include "xparameters.h"
+
+/************************** Constant Definitions *****************************/
+/**
+ * @name Device Base Address
+ * Below macros gives QSPI, QSPIPSU base address.
+ * @{
+ */
+/**
+ * QSPI Base Address
+ */
+#if defined (versal)
+#define XQSPIPS_BASEADDR      0XF1030000U
+#else
+#define XQSPIPS_BASEADDR      0XFF0F0000U
+#endif
+
+#if defined (versal)
+#define XQSPIPSU_BASEADDR     0XF1030100U
+#else
+#define XQSPIPSU_BASEADDR     0xFF0F0100U
+#endif
+#define XQSPIPSU_OFFSET     0x100U
+/** @} */
+
+/**
+ * @name XQSPIPS Enable Register information
+ * QSPIPSU Enable Register
+ * @{
+ */
+/**
+ * Register: XQSPIPS_EN_REG
+ */
+#define XQSPIPS_EN_REG    ( ( XQSPIPS_BASEADDR ) + 0X00000014U )
+#define XQSPIPS_EN_SHIFT   0U
+#define XQSPIPS_EN_WIDTH   1U
+#define XQSPIPS_EN_MASK    0X00000001U
+/** @} */
+
+/**
+ * @name XQSPIPSU configuration Register information
+ * This register contains bits for configuring GQSPI controller
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_CFG
+ */
+#define XQSPIPSU_CFG_OFFSET    0X00000000U
+
+#define XQSPIPSU_CFG_MODE_EN_SHIFT   30U
+#define XQSPIPSU_CFG_MODE_EN_WIDTH   2U
+#define XQSPIPSU_CFG_MODE_EN_MASK    0XC0000000U
+#define XQSPIPSU_CFG_MODE_EN_DMA_MASK	0X80000000U
+
+#define XQSPIPSU_CFG_GEN_FIFO_START_MODE_SHIFT   29U
+#define XQSPIPSU_CFG_GEN_FIFO_START_MODE_WIDTH   1U
+#define XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK    0X20000000U
+
+#define XQSPIPSU_CFG_START_GEN_FIFO_SHIFT   28U
+#define XQSPIPSU_CFG_START_GEN_FIFO_WIDTH   1U
+#define XQSPIPSU_CFG_START_GEN_FIFO_MASK    0X10000000U
+
+#define XQSPIPSU_CFG_ENDIAN_SHIFT   26U
+#define XQSPIPSU_CFG_ENDIAN_WIDTH   1U
+#define XQSPIPSU_CFG_ENDIAN_MASK    0X04000000U
+
+#define XQSPIPSU_CFG_EN_POLL_TO_SHIFT   20U
+#define XQSPIPSU_CFG_EN_POLL_TO_WIDTH   1U
+#define XQSPIPSU_CFG_EN_POLL_TO_MASK    0X00100000U
+
+#define XQSPIPSU_CFG_WP_HOLD_SHIFT   19U
+#define XQSPIPSU_CFG_WP_HOLD_WIDTH   1U
+#define XQSPIPSU_CFG_WP_HOLD_MASK    0X00080000U
+
+#define XQSPIPSU_CFG_BAUD_RATE_DIV_SHIFT   3U
+#define XQSPIPSU_CFG_BAUD_RATE_DIV_WIDTH   3U
+#define XQSPIPSU_CFG_BAUD_RATE_DIV_MASK    0X00000038U
+
+#define XQSPIPSU_CFG_CLK_PHA_SHIFT   2U
+#define XQSPIPSU_CFG_CLK_PHA_WIDTH   1U
+#define XQSPIPSU_CFG_CLK_PHA_MASK    0X00000004U
+
+#define XQSPIPSU_CFG_CLK_POL_SHIFT   1U
+#define XQSPIPSU_CFG_CLK_POL_WIDTH   1U
+#define XQSPIPSU_CFG_CLK_POL_MASK    0X00000002U
+/** @} */
+
+/**
+ * @name XQSPIPSU LQSPI Register information
+ * This register contains bits for configuring LQSPI
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_LQSPI
+ */
+#if !defined (versal)
+#define XQSPIPSU_LQSPI_CR_OFFSET	0X000000A0U
+#define XQSPIPSU_LQSPI_CR_LINEAR_MASK     0x80000000U /**< LQSPI mode enable */
+#define XQSPIPSU_LQSPI_CR_TWO_MEM_MASK    0x40000000U /**< Both memories or one */
+#define XQSPIPSU_LQSPI_CR_SEP_BUS_MASK    0x20000000U /**< Separate memory bus */
+#define XQSPIPSU_LQSPI_CR_U_PAGE_MASK     0x10000000U /**< Upper memory page */
+#define XQSPIPSU_LQSPI_CR_ADDR_32BIT_MASK     0x01000000U /**< Upper memory page */
+#define XQSPIPSU_LQSPI_CR_MODE_EN_MASK    0x02000000U /**< Enable mode bits */
+#define XQSPIPSU_LQSPI_CR_MODE_ON_MASK    0x01000000U /**< Mode on */
+#define XQSPIPSU_LQSPI_CR_MODE_BITS_MASK  0x00FF0000U /**< Mode value for dual I/O
+                                                         or quad I/O */
+#define XQSPIPS_LQSPI_CR_INST_MASK       0x000000FFU /**< Read instr code */
+#define XQSPIPS_LQSPI_CR_RST_STATE       0x80000003U /**< Default LQSPI CR value */
+#define XQSPIPS_LQSPI_CR_4_BYTE_STATE       0x88000013U /**< Default 4 Byte LQSPI CR value */
+#define XQSPIPS_LQSPI_CFG_RST_STATE       0x800238C1U /**< Default LQSPI CFG value */
+#endif
+/** @} */
+
+/**
+ * @name XQSPIPSU Interrupt Status Register information
+ * QSPIPSU Interrupt Status Register
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_ISR
+ */
+#define XQSPIPSU_ISR_OFFSET	0X00000004U
+
+#define XQSPIPSU_ISR_RXEMPTY_SHIFT   11U
+#define XQSPIPSU_ISR_RXEMPTY_WIDTH   1U
+#define XQSPIPSU_ISR_RXEMPTY_MASK    0X00000800U
+
+#define XQSPIPSU_ISR_GENFIFOFULL_SHIFT   10U
+#define XQSPIPSU_ISR_GENFIFOFULL_WIDTH   1U
+#define XQSPIPSU_ISR_GENFIFOFULL_MASK    0X00000400U
+
+#define XQSPIPSU_ISR_GENFIFONOT_FULL_SHIFT   9U
+#define XQSPIPSU_ISR_GENFIFONOT_FULL_WIDTH   1U
+#define XQSPIPSU_ISR_GENFIFONOT_FULL_MASK    0X00000200U
+
+#define XQSPIPSU_ISR_TXEMPTY_SHIFT   8U
+#define XQSPIPSU_ISR_TXEMPTY_WIDTH   1U
+#define XQSPIPSU_ISR_TXEMPTY_MASK    0X00000100U
+
+#define XQSPIPSU_ISR_GENFIFOEMPTY_SHIFT   7U
+#define XQSPIPSU_ISR_GENFIFOEMPTY_WIDTH   1U
+#define XQSPIPSU_ISR_GENFIFOEMPTY_MASK    0X00000080U
+
+#define XQSPIPSU_ISR_RXFULL_SHIFT   5U
+#define XQSPIPSU_ISR_RXFULL_WIDTH   1U
+#define XQSPIPSU_ISR_RXFULL_MASK    0X00000020U
+
+#define XQSPIPSU_ISR_RXNEMPTY_SHIFT   4U
+#define XQSPIPSU_ISR_RXNEMPTY_WIDTH   1U
+#define XQSPIPSU_ISR_RXNEMPTY_MASK    0X00000010U
+
+#define XQSPIPSU_ISR_TXFULL_SHIFT   3U
+#define XQSPIPSU_ISR_TXFULL_WIDTH   1U
+#define XQSPIPSU_ISR_TXFULL_MASK    0X00000008U
+
+#define XQSPIPSU_ISR_TXNOT_FULL_SHIFT   2U
+#define XQSPIPSU_ISR_TXNOT_FULL_WIDTH   1U
+#define XQSPIPSU_ISR_TXNOT_FULL_MASK    0X00000004U
+
+#define XQSPIPSU_ISR_POLL_TIME_EXPIRE_SHIFT   1U
+#define XQSPIPSU_ISR_POLL_TIME_EXPIRE_WIDTH   1U
+#define XQSPIPSU_ISR_POLL_TIME_EXPIRE_MASK    0X00000002U
+
+#define XQSPIPSU_ISR_WR_TO_CLR_MASK 0X00000002U
+/** @} */
+
+/**
+ * @name XQSPIPSU Interrupt Enable Register information
+ * This register bits for enabling interrupts
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_IER
+ */
+#define XQSPIPSU_IER_OFFSET    0X00000008U
+
+#define XQSPIPSU_IER_RXEMPTY_SHIFT   11U
+#define XQSPIPSU_IER_RXEMPTY_WIDTH   1U
+#define XQSPIPSU_IER_RXEMPTY_MASK    0X00000800U
+
+#define XQSPIPSU_IER_GENFIFOFULL_SHIFT   10U
+#define XQSPIPSU_IER_GENFIFOFULL_WIDTH   1U
+#define XQSPIPSU_IER_GENFIFOFULL_MASK    0X00000400U
+
+#define XQSPIPSU_IER_GENFIFONOT_FULL_SHIFT   9U
+#define XQSPIPSU_IER_GENFIFONOT_FULL_WIDTH   1U
+#define XQSPIPSU_IER_GENFIFONOT_FULL_MASK    0X00000200U
+
+#define XQSPIPSU_IER_TXEMPTY_SHIFT   8U
+#define XQSPIPSU_IER_TXEMPTY_WIDTH   1U
+#define XQSPIPSU_IER_TXEMPTY_MASK    0X00000100U
+
+#define XQSPIPSU_IER_GENFIFOEMPTY_SHIFT   7U
+#define XQSPIPSU_IER_GENFIFOEMPTY_WIDTH   1U
+#define XQSPIPSU_IER_GENFIFOEMPTY_MASK    0X00000080U
+
+#define XQSPIPSU_IER_RXFULL_SHIFT   5U
+#define XQSPIPSU_IER_RXFULL_WIDTH   1U
+#define XQSPIPSU_IER_RXFULL_MASK    0X00000020U
+
+#define XQSPIPSU_IER_RXNEMPTY_SHIFT   4U
+#define XQSPIPSU_IER_RXNEMPTY_WIDTH   1U
+#define XQSPIPSU_IER_RXNEMPTY_MASK    0X00000010U
+
+#define XQSPIPSU_IER_TXFULL_SHIFT   3U
+#define XQSPIPSU_IER_TXFULL_WIDTH   1U
+#define XQSPIPSU_IER_TXFULL_MASK    0X00000008U
+
+#define XQSPIPSU_IER_TXNOT_FULL_SHIFT   2U
+#define XQSPIPSU_IER_TXNOT_FULL_WIDTH   1U
+#define XQSPIPSU_IER_TXNOT_FULL_MASK    0X00000004U
+
+#define XQSPIPSU_IER_POLL_TIME_EXPIRE_SHIFT   1U
+#define XQSPIPSU_IER_POLL_TIME_EXPIRE_WIDTH   1U
+#define XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK    0X00000002U
+/** @} */
+
+/**
+ * @name XQSPIPSU Interrupt Disable Register information
+ * This register bits for disabling interrupts
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_IDR
+ */
+#define XQSPIPSU_IDR_OFFSET    0X0000000CU
+
+#define XQSPIPSU_IDR_RXEMPTY_SHIFT   11U
+#define XQSPIPSU_IDR_RXEMPTY_WIDTH   1U
+#define XQSPIPSU_IDR_RXEMPTY_MASK    0X00000800U
+
+#define XQSPIPSU_IDR_GENFIFOFULL_SHIFT   10U
+#define XQSPIPSU_IDR_GENFIFOFULL_WIDTH   1U
+#define XQSPIPSU_IDR_GENFIFOFULL_MASK    0X00000400U
+
+#define XQSPIPSU_IDR_GENFIFONOT_FULL_SHIFT   9U
+#define XQSPIPSU_IDR_GENFIFONOT_FULL_WIDTH   1U
+#define XQSPIPSU_IDR_GENFIFONOT_FULL_MASK    0X00000200U
+
+#define XQSPIPSU_IDR_TXEMPTY_SHIFT   8U
+#define XQSPIPSU_IDR_TXEMPTY_WIDTH   1U
+#define XQSPIPSU_IDR_TXEMPTY_MASK    0X00000100U
+
+#define XQSPIPSU_IDR_GENFIFOEMPTY_SHIFT   7U
+#define XQSPIPSU_IDR_GENFIFOEMPTY_WIDTH   1U
+#define XQSPIPSU_IDR_GENFIFOEMPTY_MASK    0X00000080U
+
+#define XQSPIPSU_IDR_RXFULL_SHIFT   5U
+#define XQSPIPSU_IDR_RXFULL_WIDTH   1U
+#define XQSPIPSU_IDR_RXFULL_MASK    0X00000020U
+
+#define XQSPIPSU_IDR_RXNEMPTY_SHIFT   4U
+#define XQSPIPSU_IDR_RXNEMPTY_WIDTH   1U
+#define XQSPIPSU_IDR_RXNEMPTY_MASK    0X00000010U
+
+#define XQSPIPSU_IDR_TXFULL_SHIFT   3U
+#define XQSPIPSU_IDR_TXFULL_WIDTH   1U
+#define XQSPIPSU_IDR_TXFULL_MASK    0X00000008U
+
+#define XQSPIPSU_IDR_TXNOT_FULL_SHIFT   2U
+#define XQSPIPSU_IDR_TXNOT_FULL_WIDTH   1U
+#define XQSPIPSU_IDR_TXNOT_FULL_MASK    0X00000004U
+
+#define XQSPIPSU_IDR_POLL_TIME_EXPIRE_SHIFT   1U
+#define XQSPIPSU_IDR_POLL_TIME_EXPIRE_WIDTH   1U
+#define XQSPIPSU_IDR_POLL_TIME_EXPIRE_MASK    0X00000002U
+
+#define XQSPIPSU_IDR_ALL_MASK    0X0FBEU
+/** @} */
+
+/**
+ * @name XQSPIPSU Interrupt Mask Register information
+ * This register bits for masking interrupts
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_IMR
+ */
+#define XQSPIPSU_IMR_OFFSET    0X00000010U
+
+#define XQSPIPSU_IMR_RXEMPTY_SHIFT   11U
+#define XQSPIPSU_IMR_RXEMPTY_WIDTH   1U
+#define XQSPIPSU_IMR_RXEMPTY_MASK    0X00000800U
+
+#define XQSPIPSU_IMR_GENFIFOFULL_SHIFT   10U
+#define XQSPIPSU_IMR_GENFIFOFULL_WIDTH   1U
+#define XQSPIPSU_IMR_GENFIFOFULL_MASK    0X00000400U
+
+#define XQSPIPSU_IMR_GENFIFONOT_FULL_SHIFT   9U
+#define XQSPIPSU_IMR_GENFIFONOT_FULL_WIDTH   1U
+#define XQSPIPSU_IMR_GENFIFONOT_FULL_MASK    0X00000200U
+
+#define XQSPIPSU_IMR_TXEMPTY_SHIFT   8U
+#define XQSPIPSU_IMR_TXEMPTY_WIDTH   1U
+#define XQSPIPSU_IMR_TXEMPTY_MASK    0X00000100U
+
+#define XQSPIPSU_IMR_GENFIFOEMPTY_SHIFT   7U
+#define XQSPIPSU_IMR_GENFIFOEMPTY_WIDTH   1U
+#define XQSPIPSU_IMR_GENFIFOEMPTY_MASK    0X00000080U
+
+#define XQSPIPSU_IMR_RXFULL_SHIFT   5U
+#define XQSPIPSU_IMR_RXFULL_WIDTH   1U
+#define XQSPIPSU_IMR_RXFULL_MASK    0X00000020U
+
+#define XQSPIPSU_IMR_RXNEMPTY_SHIFT   4U
+#define XQSPIPSU_IMR_RXNEMPTY_WIDTH   1U
+#define XQSPIPSU_IMR_RXNEMPTY_MASK    0X00000010U
+
+#define XQSPIPSU_IMR_TXFULL_SHIFT   3U
+#define XQSPIPSU_IMR_TXFULL_WIDTH   1U
+#define XQSPIPSU_IMR_TXFULL_MASK    0X00000008U
+
+#define XQSPIPSU_IMR_TXNOT_FULL_SHIFT   2U
+#define XQSPIPSU_IMR_TXNOT_FULL_WIDTH   1U
+#define XQSPIPSU_IMR_TXNOT_FULL_MASK    0X00000004U
+
+#define XQSPIPSU_IMR_POLL_TIME_EXPIRE_SHIFT   1U
+#define XQSPIPSU_IMR_POLL_TIME_EXPIRE_WIDTH   1U
+#define XQSPIPSU_IMR_POLL_TIME_EXPIRE_MASK    0X00000002U
+/** @} */
+
+/**
+ * @name XQSPIPSU Enable Register information
+ * This register bits for enabling QSPI controller
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_EN_REG
+ */
+#define XQSPIPSU_EN_OFFSET    0X00000014U
+
+#define XQSPIPSU_EN_SHIFT   0U
+#define XQSPIPSU_EN_WIDTH   1U
+#define XQSPIPSU_EN_MASK    0X00000001U
+/** @} */
+
+/**
+ * @name XQSPIPSU TX Data Register information
+ * This register bits for configuring TXFIFO
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_TXD
+ */
+#define XQSPIPSU_TXD_OFFSET    0X0000001CU
+
+#define XQSPIPSU_TXD_SHIFT   0U
+#define XQSPIPSU_TXD_WIDTH   32U
+#define XQSPIPSU_TXD_MASK    0XFFFFFFFFU
+
+#define XQSPIPSU_TXD_DEPTH    64
+/** @} */
+
+/**
+ * @name XQSPIPSU RX Data Register information
+ * This register bits for configuring RXFIFO
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_RXD
+ */
+#define XQSPIPSU_RXD_OFFSET    0X00000020U
+
+#define XQSPIPSU_RXD_SHIFT   0U
+#define XQSPIPSU_RXD_WIDTH   32U
+#define XQSPIPSU_RXD_MASK    0XFFFFFFFFU
+/** @} */
+
+/**
+ * @name XQSPIPSU TX/RX Threshold Register information
+ * This register bits for configuring TX/RX Threshold
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_TX_THRESHOLD
+ */
+#define XQSPIPSU_TX_THRESHOLD_OFFSET    0X00000028U
+
+#define XQSPIPSU_TX_FIFO_THRESHOLD_SHIFT   0U
+#define XQSPIPSU_TX_FIFO_THRESHOLD_WIDTH   6U
+#define XQSPIPSU_TX_FIFO_THRESHOLD_MASK    0X0000003FU
+#define XQSPIPSU_TX_FIFO_THRESHOLD_RESET_VAL    0X01U
+
+#define XQSPIPSU_RX_THRESHOLD_OFFSET    0X0000002CU
+
+#define XQSPIPSU_RX_FIFO_THRESHOLD_SHIFT   0U
+#define XQSPIPSU_RX_FIFO_THRESHOLD_WIDTH   6U
+#define XQSPIPSU_RX_FIFO_THRESHOLD_MASK    0X0000003FU
+#define XQSPIPSU_RX_FIFO_THRESHOLD_RESET_VAL    0X01U
+
+#define XQSPIPSU_RXFIFO_THRESHOLD_OPT 32U
+/** @} */
+
+/**
+ * @name XQSPIPSU GPIO Register information
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_GPIO
+ */
+#define XQSPIPSU_GPIO_OFFSET    0X00000030U
+
+#define XQSPIPSU_GPIO_WP_N_SHIFT   0U
+#define XQSPIPSU_GPIO_WP_N_WIDTH   1U
+#define XQSPIPSU_GPIO_WP_N_MASK    0X00000001U
+/** @} */
+
+/**
+ * @name XQSPIPSU Loopback Master Clock Delay Adjustment Register information
+ * This register contains bits for configuring loopback
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_LPBK_DLY_ADJ
+ */
+#define XQSPIPSU_LPBK_DLY_ADJ_OFFSET    0X00000038U
+
+#define XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT   5U
+#define XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_WIDTH   1U
+#define XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_MASK    0X00000020U
+
+#define XQSPIPSU_LPBK_DLY_ADJ_DLY1_SHIFT   3U
+#define XQSPIPSU_LPBK_DLY_ADJ_DLY1_WIDTH   2U
+#define XQSPIPSU_LPBK_DLY_ADJ_DLY1_MASK    0X00000018U
+
+#define XQSPIPSU_LPBK_DLY_ADJ_DLY0_SHIFT   0U
+#define XQSPIPSU_LPBK_DLY_ADJ_DLY0_WIDTH   3U
+#define XQSPIPSU_LPBK_DLY_ADJ_DLY0_MASK    0X00000007U
+/** @} */
+
+/**
+ * @name XQSPIPSU GEN_FIFO Register information
+ * This register contains bits for configuring GENFIFO
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_GEN_FIFO
+ */
+#define XQSPIPSU_GEN_FIFO_OFFSET    0X00000040U
+
+#define XQSPIPSU_GEN_FIFO_DATA_SHIFT   0U
+#define XQSPIPSU_GEN_FIFO_DATA_WIDTH   20U
+#define XQSPIPSU_GEN_FIFO_DATA_MASK    0X000FFFFFU
+/** @} */
+
+/**
+ * @name XQSPIPSU Select Register information
+ * This register contains bits for selection GQSPI/LQSPI controller
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_SEL
+ */
+#define XQSPIPSU_SEL_OFFSET    0X00000044U
+
+#define XQSPIPSU_SEL_SHIFT   0U
+#define XQSPIPSU_SEL_WIDTH   1U
+#if !defined (versal)
+#define XQSPIPSU_SEL_LQSPI_MASK    0X0U
+#endif
+#define XQSPIPSU_SEL_GQSPI_MASK    0X00000001U
+/** @} */
+
+/**
+ * @name XQSPIPSU FIFO Control Register information
+ * This register contains bits for controlling TXFIFO and RXFIFO
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_FIFO_CTRL
+ */
+#define XQSPIPSU_FIFO_CTRL_OFFSET    0X0000004CU
+
+#define XQSPIPSU_FIFO_CTRL_RST_RX_FIFO_SHIFT   2U
+#define XQSPIPSU_FIFO_CTRL_RST_RX_FIFO_WIDTH   1U
+#define XQSPIPSU_FIFO_CTRL_RST_RX_FIFO_MASK    0X00000004U
+
+#define XQSPIPSU_FIFO_CTRL_RST_TX_FIFO_SHIFT   1U
+#define XQSPIPSU_FIFO_CTRL_RST_TX_FIFO_WIDTH   1U
+#define XQSPIPSU_FIFO_CTRL_RST_TX_FIFO_MASK    0X00000002U
+
+#define XQSPIPSU_FIFO_CTRL_RST_GEN_FIFO_SHIFT   0U
+#define XQSPIPSU_FIFO_CTRL_RST_GEN_FIFO_WIDTH   1U
+#define XQSPIPSU_FIFO_CTRL_RST_GEN_FIFO_MASK    0X00000001U
+/** @} */
+
+/**
+ * @name XQSPIPSU GENFIFO Threshold Register information
+ * This register contains bits for configuring GENFIFO threshold
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_GF_THRESHOLD
+ */
+#define XQSPIPSU_GF_THRESHOLD_OFFSET    0X00000050U
+
+#define XQSPIPSU_GEN_FIFO_THRESHOLD_SHIFT   0U
+#define XQSPIPSU_GEN_FIFO_THRESHOLD_WIDTH   5U
+#define XQSPIPSU_GEN_FIFO_THRESHOLD_MASK    0X0000001FU
+#define XQSPIPSU_GEN_FIFO_THRESHOLD_RESET_VAL    0X10U
+/** @} */
+
+/**
+ * @name XQSPIPSU Poll configuration Register information
+ * This register contains bits for configuring Poll feature
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_POLL_CFG
+ */
+#define XQSPIPSU_POLL_CFG_OFFSET    0X00000054U
+
+#define XQSPIPSU_POLL_CFG_EN_MASK_UPPER_SHIFT   31U
+#define XQSPIPSU_POLL_CFG_EN_MASK_UPPER_WIDTH   1U
+#define XQSPIPSU_POLL_CFG_EN_MASK_UPPER_MASK    0X80000000U
+
+#define XQSPIPSU_POLL_CFG_EN_MASK_LOWER_SHIFT   30U
+#define XQSPIPSU_POLL_CFG_EN_MASK_LOWER_WIDTH   1U
+#define XQSPIPSU_POLL_CFG_EN_MASK_LOWER_MASK    0X40000000U
+
+#define XQSPIPSU_POLL_CFG_MASK_EN_SHIFT   8U
+#define XQSPIPSU_POLL_CFG_MASK_EN_WIDTH   8U
+#define XQSPIPSU_POLL_CFG_MASK_EN_MASK    0X0000FF00U
+
+#define XQSPIPSU_POLL_CFG_DATA_VALUE_SHIFT   0U
+#define XQSPIPSU_POLL_CFG_DATA_VALUE_WIDTH   8U
+#define XQSPIPSU_POLL_CFG_DATA_VALUE_MASK    0X000000FFU
+
+#define XQSPIPSU_P_TO_OFFSET    0X00000058U
+
+#define XQSPIPSU_P_TO_VALUE_SHIFT   0U
+#define XQSPIPSU_P_TO_VALUE_WIDTH   32U
+#define XQSPIPSU_P_TO_VALUE_MASK    0XFFFFFFFFU
+/** @} */
+
+/**
+ * @name XQSPIPSU Transfer Status Register information
+ * This register contains bits for transfer status
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_XFER_STS
+ */
+#define XQSPIPSU_XFER_STS_OFFSET	0X0000005CU
+
+#define XQSPIPSU_XFER_STS_PEND_BYTES_SHIFT   0U
+#define XQSPIPSU_XFER_STS_PEND_BYTES_WIDTH   32U
+#define XQSPIPSU_XFER_STS_PEND_BYTES_MASK    0XFFFFFFFFU
+/** @} */
+
+/**
+ * @name XQSPIPSU GEN_FIFO Snapshot Register information
+ * This register contains bits for configuring GENFIFO
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_GF_SNAPSHOT
+ */
+#define XQSPIPSU_GF_SNAPSHOT_OFFSET    0X00000060U
+
+#define XQSPIPSU_GF_SNAPSHOT_SHIFT   0U
+#define XQSPIPSU_GF_SNAPSHOT_WIDTH   20U
+#define XQSPIPSU_GF_SNAPSHOT_MASK    0X000FFFFFU
+/** @} */
+
+/**
+ * @name XQSPIPSU Receive Data Copy Register information
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_RX_COPY
+ */
+#define XQSPIPSU_RX_COPY_OFFSET    0X00000064U
+
+#define XQSPIPSU_RX_COPY_UPPER_SHIFT   8U
+#define XQSPIPSU_RX_COPY_UPPER_WIDTH   8U
+#define XQSPIPSU_RX_COPY_UPPER_MASK    0X0000FF00U
+
+#define XQSPIPSU_RX_COPY_LOWER_SHIFT   0U
+#define XQSPIPSU_RX_COPY_LOWER_WIDTH   8U
+#define XQSPIPSU_RX_COPY_LOWER_MASK    0X000000FFU
+/** @} */
+
+/**
+ * @name XQSPIPSU Module Identification Register information
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_MOD_ID
+ */
+#define XQSPIPSU_MOD_ID_OFFSET    0X000000FCU
+
+#define XQSPIPSU_MOD_ID_SHIFT   0U
+#define XQSPIPSU_MOD_ID_WIDTH   32U
+#define XQSPIPSU_MOD_ID_MASK    0XFFFFFFFFU
+/** @} */
+
+/**
+ * @name XQSPIPSU DMA Transfer Register information
+ * This register contains bits for configuring DMA
+ * @{
+ */
+/**
+ * Register: XQSPIPSU_QSPIDMA_DST_ADDR
+ */
+#define XQSPIPSU_QSPIDMA_DST_ADDR_OFFSET    0X00000700U
+
+#define XQSPIPSU_QSPIDMA_DST_ADDR_SHIFT   2U
+#define XQSPIPSU_QSPIDMA_DST_ADDR_WIDTH   30U
+#define XQSPIPSU_QSPIDMA_DST_ADDR_MASK    0XFFFFFFFCU
+
+#define XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET    0X00000704U
+
+#define XQSPIPSU_QSPIDMA_DST_SIZE_SHIFT   2U
+#define XQSPIPSU_QSPIDMA_DST_SIZE_WIDTH   27U
+#define XQSPIPSU_QSPIDMA_DST_SIZE_MASK    0X1FFFFFFCU
+
+#define XQSPIPSU_QSPIDMA_DST_STS_OFFSET    0X00000708U
+
+#define XQSPIPSU_QSPIDMA_DST_STS_DONE_CNT_SHIFT   13U
+#define XQSPIPSU_QSPIDMA_DST_STS_DONE_CNT_WIDTH   3U
+#define XQSPIPSU_QSPIDMA_DST_STS_DONE_CNT_MASK    0X0000E000U
+
+#define XQSPIPSU_QSPIDMA_DST_STS_DST_FIFO_LEVEL_SHIFT   5U
+#define XQSPIPSU_QSPIDMA_DST_STS_DST_FIFO_LEVEL_WIDTH   8U
+#define XQSPIPSU_QSPIDMA_DST_STS_DST_FIFO_LEVEL_MASK    0X00001FE0U
+
+#define XQSPIPSU_QSPIDMA_DST_STS_WR_OUTSTANDING_SHIFT   1U
+#define XQSPIPSU_QSPIDMA_DST_STS_WR_OUTSTANDING_WIDTH   4U
+#define XQSPIPSU_QSPIDMA_DST_STS_WR_OUTSTANDING_MASK    0X0000001EU
+
+#define XQSPIPSU_QSPIDMA_DST_STS_BUSY_SHIFT   0U
+#define XQSPIPSU_QSPIDMA_DST_STS_BUSY_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_STS_BUSY_MASK    0X00000001U
+
+#define XQSPIPSU_QSPIDMA_DST_STS_WTC	0xE000U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET    0X0000070CU
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL_FIFO_LVL_HIT_THRESHOLD_SHIFT   25U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_FIFO_LVL_HIT_THRESHOLD_WIDTH   7U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_FIFO_LVL_HIT_THRESHOLD_MASK    0XFE000000U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL_APB_ERR_RESP_SHIFT   24U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_APB_ERR_RESP_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_APB_ERR_RESP_MASK    0X01000000U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL_ENDIAN_SHIFT   23U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_ENDIAN_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_ENDIAN_MASK    0X00800000U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL_AXI_BRST_TYPE_SHIFT   22U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_AXI_BRST_TYPE_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_AXI_BRST_TYPE_MASK    0X00400000U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL_TO_VAL_SHIFT   10U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_TO_VAL_WIDTH   12U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_TO_VAL_MASK    0X003FFC00U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL_FIFO_THRESHOLD_SHIFT   2U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_FIFO_THRESHOLD_WIDTH   8U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_FIFO_THRESHOLD_MASK    0X000003FCU
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_STRM_SHIFT   1U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_STRM_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_STRM_MASK    0X00000002U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_MEM_SHIFT   0U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_MEM_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_MEM_MASK    0X00000001U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL_RESET_VAL	0x403FFA00U
+
+#define XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET    0X00000714U
+
+#define XQSPIPSU_QSPIDMA_DST_I_STS_FIFO_OF_SHIFT   7U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_FIFO_OF_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_FIFO_OF_MASK    0X00000080U
+
+#define XQSPIPSU_QSPIDMA_DST_I_STS_INVALID_APB_SHIFT   6U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_INVALID_APB_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_INVALID_APB_MASK    0X00000040U
+
+#define XQSPIPSU_QSPIDMA_DST_I_STS_THRESHOLD_HIT_SHIFT   5U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_THRESHOLD_HIT_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_THRESHOLD_HIT_MASK    0X00000020U
+
+#define XQSPIPSU_QSPIDMA_DST_I_STS_TO_MEM_SHIFT   4U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_TO_MEM_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_TO_MEM_MASK    0X00000010U
+
+#define XQSPIPSU_QSPIDMA_DST_I_STS_TO_STRM_SHIFT   3U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_TO_STRM_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_TO_STRM_MASK    0X00000008U
+
+#define XQSPIPSU_QSPIDMA_DST_I_STS_AXI_BRESP_ERR_SHIFT   2U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_AXI_BRESP_ERR_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_AXI_BRESP_ERR_MASK    0X00000004U
+
+#define XQSPIPSU_QSPIDMA_DST_I_STS_DONE_SHIFT   1U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_DONE_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK    0X00000002U
+
+#define XQSPIPSU_QSPIDMA_DST_INTR_ERR_MASK    0X000000FCU
+#define XQSPIPSU_QSPIDMA_DST_INTR_ALL_MASK    0X000000FEU
+
+#define XQSPIPSU_QSPIDMA_DST_I_EN_OFFSET    0X00000718U
+
+#define XQSPIPSU_QSPIDMA_DST_I_EN_FIFO_OF_SHIFT   7U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_FIFO_OF_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_FIFO_OF_MASK    0X00000080U
+
+#define XQSPIPSU_QSPIDMA_DST_I_EN_INVALID_APB_SHIFT   6U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_INVALID_APB_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_INVALID_APB_MASK    0X00000040U
+
+#define XQSPIPSU_QSPIDMA_DST_I_EN_THRESHOLD_HIT_SHIFT   5U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_THRESHOLD_HIT_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_THRESHOLD_HIT_MASK    0X00000020U
+
+#define XQSPIPSU_QSPIDMA_DST_I_EN_TO_MEM_SHIFT   4U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_TO_MEM_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_TO_MEM_MASK    0X00000010U
+
+#define XQSPIPSU_QSPIDMA_DST_I_EN_TO_STRM_SHIFT   3U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_TO_STRM_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_TO_STRM_MASK    0X00000008U
+
+#define XQSPIPSU_QSPIDMA_DST_I_EN_AXI_BRESP_ERR_SHIFT   2U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_AXI_BRESP_ERR_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_AXI_BRESP_ERR_MASK    0X00000004U
+
+#define XQSPIPSU_QSPIDMA_DST_I_EN_DONE_SHIFT   1U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_DONE_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK    0X00000002U
+
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET    0X0000071CU
+
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_FIFO_OF_SHIFT   7U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_FIFO_OF_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_FIFO_OF_MASK    0X00000080U
+
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_INVALID_APB_SHIFT   6U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_INVALID_APB_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_INVALID_APB_MASK    0X00000040U
+
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_THRESHOLD_HIT_SHIFT   5U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_THRESHOLD_HIT_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_THRESHOLD_HIT_MASK    0X00000020U
+
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_TO_MEM_SHIFT   4U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_TO_MEM_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_TO_MEM_MASK    0X00000010U
+
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_TO_STRM_SHIFT   3U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_TO_STRM_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_TO_STRM_MASK    0X00000008U
+
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_AXI_BRESP_ERR_SHIFT   2U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_AXI_BRESP_ERR_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_AXI_BRESP_ERR_MASK    0X00000004U
+
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_DONE_SHIFT   1U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_DONE_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_I_DIS_DONE_MASK    0X00000002U
+
+#define XQSPIPSU_QSPIDMA_DST_IMR_OFFSET    0X00000720U
+
+#define XQSPIPSU_QSPIDMA_DST_IMR_FIFO_OF_SHIFT   7U
+#define XQSPIPSU_QSPIDMA_DST_IMR_FIFO_OF_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_IMR_FIFO_OF_MASK    0X00000080U
+
+#define XQSPIPSU_QSPIDMA_DST_IMR_INVALID_APB_SHIFT   6U
+#define XQSPIPSU_QSPIDMA_DST_IMR_INVALID_APB_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_IMR_INVALID_APB_MASK    0X00000040U
+
+#define XQSPIPSU_QSPIDMA_DST_IMR_THRESHOLD_HIT_SHIFT   5U
+#define XQSPIPSU_QSPIDMA_DST_IMR_THRESHOLD_HIT_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_IMR_THRESHOLD_HIT_MASK    0X00000020U
+
+#define XQSPIPSU_QSPIDMA_DST_IMR_TO_MEM_SHIFT   4U
+#define XQSPIPSU_QSPIDMA_DST_IMR_TO_MEM_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_IMR_TO_MEM_MASK    0X00000010U
+
+#define XQSPIPSU_QSPIDMA_DST_IMR_TO_STRM_SHIFT   3U
+#define XQSPIPSU_QSPIDMA_DST_IMR_TO_STRM_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_IMR_TO_STRM_MASK    0X00000008U
+
+#define XQSPIPSU_QSPIDMA_DST_IMR_AXI_BRESP_ERR_SHIFT   2U
+#define XQSPIPSU_QSPIDMA_DST_IMR_AXI_BRESP_ERR_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_IMR_AXI_BRESP_ERR_MASK    0X00000004U
+
+#define XQSPIPSU_QSPIDMA_DST_IMR_DONE_SHIFT   1U
+#define XQSPIPSU_QSPIDMA_DST_IMR_DONE_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_IMR_DONE_MASK    0X00000002U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_OFFSET    0X00000724U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_RAM_EMASA_SHIFT   27U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_RAM_EMASA_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_RAM_EMASA_MASK    0X08000000U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_AWCACHE_SHIFT   24U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_AWCACHE_WIDTH   3U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_AWCACHE_MASK    0X07000000U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_TO_EN_SHIFT   22U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_TO_EN_WIDTH   1U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_TO_EN_MASK    0X00400000U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_RAM_EMAB_SHIFT   19U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_RAM_EMAB_WIDTH   3U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_RAM_EMAB_MASK    0X00380000U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_RAM_EMAA_SHIFT   16U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_RAM_EMAA_WIDTH   3U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_RAM_EMAA_MASK    0X00070000U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_TO_PRE_SHIFT   4U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_TO_PRE_WIDTH   12U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_TO_PRE_MASK    0X0000FFF0U
+
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_MAX_OUTS_CMDS_SHIFT   0U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_MAX_OUTS_CMDS_WIDTH   4U
+#define XQSPIPSU_QSPIDMA_DST_CTRL2_MAX_OUTS_CMDS_MASK    0X0000000FU
+
+#define XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET    0X00000728U
+
+#define XQSPIPSU_QSPIDMA_DST_ADDR_MSB_SHIFT   0U
+#define XQSPIPSU_QSPIDMA_DST_ADDR_MSB_WIDTH   12U
+#define XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK    0X00000FFFU
+
+#define XQSPIPSU_QSPIDMA_FUTURE_ECO_OFFSET    0X00000EFCU
+
+#define XQSPIPSU_QSPIDMA_FUTURE_ECO_VAL_SHIFT   0U
+#define XQSPIPSU_QSPIDMA_FUTURE_ECO_VAL_WIDTH   32U
+#define XQSPIPSU_QSPIDMA_FUTURE_ECO_VAL_MASK    0XFFFFFFFFU
+/** @} */
+
+/**
+ * @name XQSPIPSU Generic FIFO masks information
+ * Generic FIFO masks information
+ * @{
+ */
+/**
+ * Generic FIFO masks
+ */
+#define XQSPIPSU_GENFIFO_IMM_DATA_MASK	0xFFU
+#define XQSPIPSU_GENFIFO_DATA_XFER	0x100U
+#define XQSPIPSU_GENFIFO_EXP		0x200U
+#define XQSPIPSU_GENFIFO_MODE_SPI	0x400U
+#define XQSPIPSU_GENFIFO_MODE_DUALSPI	0x800U
+#define XQSPIPSU_GENFIFO_MODE_QUADSPI	0xC00U
+#define XQSPIPSU_GENFIFO_MODE_MASK	0xC00U	/* And with ~MASK first */
+#define XQSPIPSU_GENFIFO_CS_LOWER	0x1000U
+#define XQSPIPSU_GENFIFO_CS_UPPER	0x2000U
+#define XQSPIPSU_GENFIFO_BUS_LOWER	0x4000U
+#define XQSPIPSU_GENFIFO_BUS_UPPER	0x8000U
+#define XQSPIPSU_GENFIFO_BUS_BOTH	0xC000U	/* inverse is no bus */
+#define XQSPIPSU_GENFIFO_BUS_MASK	0xC000U	/* And with ~MASK first */
+#define XQSPIPSU_GENFIFO_TX		0x10000U	/* inverse is zero pump */
+#define XQSPIPSU_GENFIFO_RX		0x20000U	/* inverse is RX discard */
+#define XQSPIPSU_GENFIFO_STRIPE		0x40000U
+#define XQSPIPSU_GENFIFO_POLL		0x80000U
+/** @} */
+
+/**
+ * @name XQSPIPSU RX Data Delay Register information
+ * @{
+ */
+/**
+ * QSPI Data delay register
+ */
+#define XQSPIPSU_DATA_DLY_ADJ_OFFSET    0X000000F8U
+
+#define XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_SHIFT   31U
+#define XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_WIDTH   1U
+#define XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_MASK    0X80000000U
+
+#define XQSPIPSU_DATA_DLY_ADJ_DLY_SHIFT   28U
+#define XQSPIPSU_DATA_DLY_ADJ_DLY_WIDTH   3U
+#define XQSPIPSU_DATA_DLY_ADJ_DLY_MASK    0X70000000U
+/** @} */
+
+/**
+ * @name TAPDLY Bypass register  information
+ * @{
+ */
+/**
+ * Tapdelay Bypass register
+ */
+
+#if defined versal
+#define IOU_TAPDLY_BYPASS_OFFSET 0X0000003CU
+#else
+#define IOU_TAPDLY_BYPASS_OFFSET 0X00000390U
+#endif
+
+#define IOU_TAPDLY_BYPASS_LQSPI_RX_SHIFT 0X02U
+#if !defined (versal)
+#define IOU_TAPDLY_BYPASS_LQSPI_RX_WIDTH 0X01U
+#define IOU_TAPDLY_BYPASS_LQSPI_RX_MASK 0x00000004U
+#endif
+
+#if defined versal
+#define IOU_TAPDLY_RESET_STATE 0x4U
+#else
+#define IOU_TAPDLY_RESET_STATE 0x7U
+#endif
+/** @} */
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+#define XQspiPsu_In32 Xil_In32   /**< Read the  32 bit register value */
+#define XQspiPsu_Out32 Xil_Out32 /**< Write the 32 bit register value */
+
+/****************************************************************************/
+/**
+* Read a register.
+*
+* @param	BaseAddress contains the base address of the device.
+* @param	RegOffset contains the offset from the 1st register of the
+*		device to the target register.
+*
+* @return	The value read from the register.
+*
+* @note		C-Style signature:
+*		u32 XQspiPsu_ReadReg(u32 BaseAddress. s32 RegOffset)
+*
+******************************************************************************/
+#define XQspiPsu_ReadReg(BaseAddress, RegOffset) XQspiPsu_In32((BaseAddress) + (RegOffset))
+
+/***************************************************************************/
+/**
+* Write to a register.
+*
+* @param	BaseAddress contains the base address of the device.
+* @param	RegOffset contains the offset from the 1st register of the
+*		device to target register.
+* @param	RegisterValue is the value to be written to the register.
+*
+* @return	None.
+*
+* @note		C-Style signature:
+*		void XQspiPsu_WriteReg(u32 BaseAddress, s32 RegOffset,
+*		u32 RegisterValue)
+*
+******************************************************************************/
+#define XQspiPsu_WriteReg(BaseAddress, RegOffset, RegisterValue) XQspiPsu_Out32((BaseAddress) + (RegOffset), (RegisterValue))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /**< XQSPIPSU_H */
+/** @} */
diff --git a/bsps/shared/dev/spi/VERSION b/bsps/shared/dev/spi/VERSION
new file mode 100644
index 0000000000..a0acb181b6
--- /dev/null
+++ b/bsps/shared/dev/spi/VERSION
@@ -0,0 +1,29 @@
+The information in this file describes the source of the following files in
+bsps/shared/dev/spi/ and bsps/include/dev/spi/:
+
+- xqspipsu_control.c
+- xqspipsu_control.h
+- xqspipsu_flash_config.h
+- xqspipsu_hw.c
+- xqspipsu_hw.h
+- xqspipsu_options.c
+- xqspipsu.c
+- xqspipsu.h
+
+Import from:
+
+https://github.com/Xilinx/embeddedsw.git
+
+commit 8a89579489c88ea5acd23d7d439ac928659c26cf
+Author:     msreeram <manikanta.sreeram at xilinx.com>
+AuthorDate: Wed Apr 6 23:24:38 2022 -0600
+Commit:     Siva Addepalli <sivaprasad.addepalli at xilinx.com>
+CommitDate: Fri Apr 8 16:47:15 2022 +0530
+
+    update license file for EmbeddedSW 2022.1 release
+
+    Update license file for EmbeddedSW 2022.1 release
+
+    Signed-off-by: Manikanta Sreeram <msreeram at xilinx.com>
+
+    Acked-by : Meena Paleti <meena.paleti at xilinx.com>
diff --git a/bsps/shared/dev/spi/xqspipsu.c b/bsps/shared/dev/spi/xqspipsu.c
new file mode 100644
index 0000000000..1286efd359
--- /dev/null
+++ b/bsps/shared/dev/spi/xqspipsu.c
@@ -0,0 +1,1048 @@
+/******************************************************************************
+* Copyright (C) 2014 - 2022 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+
+/*****************************************************************************/
+/**
+ *
+ * @file xqspipsu.c
+ * @addtogroup Overview
+ * @{
+ *
+ * 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 disable 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)
+ * 1.8 tjs 06/26/18 Added an example for accessing 64bit dma within
+ *                  32 bit application. CR#1004701
+ * 1.8 tjs 06/26/18 Removed checkpatch warnings.
+ * 1.8 tjs 07/09/18 Fixed cppcheck and doxygen warnings. (CR#1006336)
+ * 1.8 tjs 07/18/18 Setup64BRxDma() should be called only if the RxAddress is
+ *                  greater than 32 bit address space. (CR#1006862)
+ * 1.8 tjs 09/06/18 Fixed the code in XQspiPsu_GenFifoEntryData() for data
+ *                  transfer length up to 255 for reducing the extra loop.
+ * 1.8  mus 11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
+ * 1.9 tjs 11/22/17 Added the check for A72 and R5 processors (CR-987075)
+ * 1.9 tjs 04/17/18 Updated register addresses as per the latest revision
+ *		    of versal (CR#999610)
+ * 1.9  aru 01/17/19 Fixes violations according to MISRAC-2012
+ *                  in safety mode and modified the code such as
+ *                  Added UNITPTR inplace of INTPTR,Declared the pointer param
+ *		    as Pointer to const .
+ * 1.9  nsk 02/01/19 Clear DMA_DST_ADDR_MSB register on 32bit machine, if the
+ *		     address is of only 32bit (CR#1020031)
+ * 1.9  nsk 02/01/19 Added QSPI idling support.
+ * 1.9  rama 03/13/19 Fixed MISRA violations related to UR data anamoly,
+ *					  expression is not a boolean
+ * 1.9  nsk 03/27/19 Update 64bit dma support
+ * 1.10 sk  08/20/19 Fixed issues in poll timeout feature.
+ * 1.11 akm 02/19/20 Added XQspiPsu_StartDmaTransfer() and XQspiPsu_CheckDmaDone()
+ * 		     APIs for non-blocking transfer.
+ * 1.11 sd  01/02/20 Added clocking support
+ * 1.11 akm 03/09/20 Reorganize the source code, enable qspi controller and
+ *		     interrupts in XQspiPsu_CfgInitialize() API.
+ * 1.11 akm 03/26/20 Fixed issue by updating XQspiPsu_CfgInitialize to return
+ *		     XST_DEVICE_IS_STARTED instead of asserting, when the
+ *		     instance is already configured.
+ * 1.13 akm 01/04/21 Fix MISRA-C violations.
+ * 1.14 akm 06/24/21 Allow enough time for the controller to reset the FIFOs.
+ * 1.14 akm 08/12/21 Perform Dcache invalidate at the end of the DMA transfer.
+ * 1.15 akm 10/21/21 Fix MISRA-C violations.
+ *
+ * </pre>
+ *
+ ******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xqspipsu.h"
+#include "xqspipsu_control.h"
+#include "sleep.h"
+
+/************************** Constant Definitions *****************************/
+#define MAX_DELAY_CNT	10000000U	/**< Max delay count */
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+/**
+ *
+ * Initializes a specific XQspiPsu instance as such 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,
+			   const XQspiPsu_Config *ConfigPtr,
+			   UINTPTR 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 == (u32)TRUE) ||
+	    (InstancePtr->IsReady == XIL_COMPONENT_IS_READY)) {
+		Status = (s32)XST_DEVICE_IS_STARTED;
+	} else {
+		/* Set some default values. */
+		InstancePtr->IsBusy = (u32)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;
+#if defined  (XCLOCKING)
+		InstancePtr->Config.RefClk = ConfigPtr->RefClk;
+#endif
+		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 = (u8)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);
+		/* Enable */
+		XQspiPsu_Enable(InstancePtr);
+
+		InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
+
+		Status = (s32)XST_SUCCESS;
+	}
+
+	return Status;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Stops the transfer of data to internal DST FIFO from stream interface and
+ * also stops the issuing of new write commands to memory.
+ *
+ * By calling this API, any ongoing Dma transfers will be paused and DMA will
+ * not issue AXI write commands to memory
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @return	None.
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+void XQspiPsu_Idle(const XQspiPsu *InstancePtr)
+{
+	u32 RegEn;
+	u32 DmaStatus;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+	/* Check for QSPI enable */
+	RegEn = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_EN_OFFSET);
+	if ((RegEn & XQSPIPSU_EN_MASK) != 0U) {
+		DmaStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+				XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET);
+		DmaStatus |= XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_STRM_MASK;
+		DmaStatus |= XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_MEM_MASK;
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+				XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET, DmaStatus);
+	}
+#if defined  (XCLOCKING)
+	Xil_ClockDisable(InstancePtr->Config.RefClk);
+#endif
+}
+
+/*****************************************************************************/
+/**
+ *
+ * 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)
+{
+	Xil_AssertVoid(InstancePtr != NULL);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_Reset\r\n");
+#endif
+
+	/* Abort any transfer that is in progress */
+	XQspiPsu_Abort(InstancePtr);
+
+	/* Default value to config register */
+	XQspiPsu_SetDefaultConfig(InstancePtr);
+
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Aborts a transfer in progress.
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @return	None.
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+void XQspiPsu_Abort(XQspiPsu *InstancePtr)
+{
+	u32 IntrStatus, ConfigReg, FifoStatus;
+	u32 DelayCount = 0U;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_Abort\r\n");
+#endif
+	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 GEN FIFO, TX FIFO & RX FIFO. Switch to IO mode to Clear
+	 * RX FIFO. This is because of DMA behaviour where it waits on
+	 * RX empty and goes busy assuming there is data to be transferred
+	 * even if there is no request.
+	 */
+	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_TX_FIFO_MASK |
+			  XQSPIPSU_FIFO_CTRL_RST_GEN_FIFO_MASK |
+			  XQSPIPSU_FIFO_CTRL_RST_RX_FIFO_MASK);
+	/*
+	 * QSPI Controller takes few clock cycles to update the RX_FIFO_Empty,
+	 * TX_FIFO_Empty and GEN_FIFO_Empty status bit. Checking the GQSPI FIFO
+	 * Control register bits gives enough time for the QSPI controller to
+	 * update the status bit. The opeartion timesout, if the status bit are
+	 * not updated after 10secs.
+	 */
+
+	FifoStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+					XQSPIPSU_FIFO_CTRL_OFFSET);
+	while(FifoStatus != 0U) {
+		if (DelayCount == MAX_DELAY_CNT) {
+#ifdef DEBUG
+			xil_printf("Timeout error, FIFO reset failed.\r\n");
+#endif
+		} else {
+			/* Wait for 1 usec */
+			usleep(1);
+			DelayCount++;
+			FifoStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+							XQSPIPSU_FIFO_CTRL_OFFSET);
+		}
+	}
+
+	if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+		ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+				XQSPIPSU_CFG_OFFSET, ConfigReg);
+	}
+
+
+	InstancePtr->TxBytes = 0;
+	InstancePtr->RxBytes = 0;
+	InstancePtr->GenFifoEntries = 0;
+	InstancePtr->IsBusy = (u32)FALSE;
+}
+
+/*****************************************************************************/
+/**
+ * This is the handler for polling functionality of controller. It reads 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.
+ *
+ *
+ * @param       InstancePtr is a pointer to the XQspiPsu instance.
+ * @param       StatusReg is the Interrupt status Register value.
+ *
+ * @return	None.
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+void XQspiPsu_PollDataHandler(XQspiPsu *InstancePtr, u32 StatusReg)
+{
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_PollDataHandler\r\n");
+#endif
+
+	if ((StatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK) != (u32)FALSE) {
+		/*
+		 * 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.
+		 */
+		(void)XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+				XQSPIPSU_RXD_OFFSET);
+
+		InstancePtr->StatusHandler(InstancePtr->StatusRef,
+				XST_SPI_POLL_DONE, 0);
+	}
+	if ((StatusReg & XQSPIPSU_ISR_POLL_TIME_EXPIRE_MASK) != (u32)FALSE) {
+			InstancePtr->StatusHandler(InstancePtr->StatusRef,
+							XST_FLASH_TIMEOUT_ERROR, 0);
+	}
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_IDR_OFFSET,
+			(u32)XQSPIPSU_IER_RXNEMPTY_MASK |
+			(u32)XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK);
+	InstancePtr->IsBusy = (u32)FALSE;
+	if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+			XQspiPsu_SetReadMode(InstancePtr, XQSPIPSU_READMODE_DMA);
+	}
+	/* De-select slave */
+	XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
+	XQspiPsu_ManualStartEnable(InstancePtr);
+}
+
+/*****************************************************************************/
+/**
+ *
+ * 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 IOPending = (u32)FALSE;
+	u32 DmaIntrSts;
+	s32 Status;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(Msg != NULL);
+	Xil_AssertNonvoid(NumMsg > 0U);
+	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 == (u32)TRUE) {
+		Status = (s32)XST_DEVICE_BUSY;
+		goto END;
+	}
+	/* 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) != (u32)FALSE)) {
+			Status = (s32)XST_FAILURE;
+			goto END;
+		}
+	}
+	/*
+	 * Set the busy flag, which will be cleared when the transfer is
+	 * entirely done.
+	 */
+	InstancePtr->IsBusy = (u32)TRUE;
+
+#if defined  (XCLOCKING)
+	Xil_ClockEnable(InstancePtr->Config.RefClk);
+#endif
+	/* Select slave */
+	XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
+
+	/* list */
+	Index = 0;
+	while (Index < (s32)NumMsg) {
+		XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[Index]);
+		XQspiPsu_ManualStartEnable(InstancePtr);
+		/* Use thresholds here */
+		/* If there is more data to be transmitted */
+		do {
+			QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+						XQSPIPSU_ISR_OFFSET);
+			/* Transmit more data if left */
+			if (((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != (u32)FALSE) &&
+				((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
+				(InstancePtr->TxBytes > 0)) {
+				XQspiPsu_FillTxFifo(InstancePtr, &Msg[Index],
+						(u32)XQSPIPSU_TXD_DEPTH);
+			}
+
+			if ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE) {
+				if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+					/* Check if DMA RX is complete and update RxBytes */
+					DmaIntrSts = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+								XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
+					if ((DmaIntrSts &
+						XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != (u32)FALSE) {
+						XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+								XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET, DmaIntrSts);
+						/* DMA transfer done, Invalidate Data Cache */
+						if (!((Msg[Index].RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
+							(Msg[Index].Xfer64bit != (u8)0U)) &&
+							(InstancePtr->Config.IsCacheCoherent == 0U)) {
+							Xil_DCacheInvalidateRange((INTPTR)Msg[Index].RxBfrPtr,
+										(INTPTR)Msg[Index].ByteCount);
+						}
+						IOPending = XQspiPsu_SetIOMode(InstancePtr, &Msg[Index]);
+						InstancePtr->RxBytes = 0;
+						if (IOPending == (u32)TRUE) {
+							break;
+						}
+					}
+				} else {
+					XQspiPsu_IORead(InstancePtr, &Msg[Index], QspiPsuStatusReg);
+				}
+			}
+		} while (((QspiPsuStatusReg &
+			XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE) ||
+			(InstancePtr->TxBytes != 0) ||
+			((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) == (u32)FALSE) ||
+			(InstancePtr->RxBytes != 0));
+
+		if ((InstancePtr->IsUnaligned != 0) && (IOPending == (u32)FALSE)) {
+			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;
+		}
+		if (IOPending == (u32)TRUE) {
+			IOPending = (u32)FALSE;
+		} else {
+			Index++;
+		}
+	}
+	/* De-select slave */
+	XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
+	XQspiPsu_ManualStartEnable(InstancePtr);
+	do {
+		QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
+	} while ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE);
+
+	/* Clear the busy flag. */
+	InstancePtr->IsBusy = (u32)FALSE;
+
+	Status = (s32)XST_SUCCESS;
+
+#if defined  (XCLOCKING)
+	Xil_ClockDisable(InstancePtr->Config.RefClk);
+#endif
+	END:
+	return Status;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * 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;
+	s32 Status;
+
+	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 == (u32)TRUE) {
+			Status = (s32)XST_DEVICE_BUSY;
+			goto END;
+	}
+#if defined  (XCLOCKING)
+	Xil_ClockEnable(InstancePtr->Config.RefClk);
+#endif
+
+	if ((Msg[0].Flags & XQSPIPSU_MSG_FLAG_POLL) != (u32)FALSE) {
+		InstancePtr->IsBusy = (u32)TRUE;
+		XQspiPsu_PollDataConfig(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) != (u32)FALSE)) {
+				Status = (s32)XST_FAILURE;
+				goto END;
+			}
+		}
+		/*
+		 * Set the busy flag, which will be cleared when the transfer is
+		 * entirely done.
+		 */
+		InstancePtr->IsBusy = (u32)TRUE;
+
+		InstancePtr->Msg = Msg;
+		InstancePtr->NumMsg = (s32)NumMsg;
+		InstancePtr->MsgCnt = 0;
+
+		/* 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]);
+		XQspiPsu_ManualStartEnable(InstancePtr);
+
+		/* Enable interrupts */
+		XQspiPsu_WriteReg(InstancePtr->Config.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(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_EN_OFFSET,
+					XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
+		}
+	}
+	Status = (s32)XST_SUCCESS;
+
+	END:
+	return Status;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * 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;
+	XQspiPsu_Msg *Msg;
+	s32 NumMsg;
+	s32 MsgCnt;
+	u8 DeltaMsgCnt = 0;
+	u32 TxRxFlag;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+	Xil_AssertNonvoid(InstancePtr->NumMsg > 0);
+	Xil_AssertNonvoid(InstancePtr->Msg != NULL);
+
+	Msg = InstancePtr->Msg;
+	NumMsg = InstancePtr->NumMsg;
+	MsgCnt = InstancePtr->MsgCnt;
+	TxRxFlag = Msg[MsgCnt].Flags;
+
+	/* QSPIPSU Intr cleared on read */
+	QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
+	if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+		/* DMA Intr write to clear */
+		DmaIntrStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+					XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
+					DmaIntrStatusReg);
+	}
+	if (((DmaIntrStatusReg & XQSPIPSU_QSPIDMA_DST_INTR_ERR_MASK) != (u32)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) != (u32)FALSE) &&
+		((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != (u32)FALSE) &&
+		(InstancePtr->TxBytes > 0)) {
+		XQspiPsu_FillTxFifo(InstancePtr, &Msg[MsgCnt], (u32)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) != (u32)FALSE) &&
+		((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) != (u32)FALSE) &&
+		((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != (u32)FALSE) &&
+		(InstancePtr->TxBytes == 0) &&
+		((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE)) {
+		MsgCnt += 1;
+		DeltaMsgCnt = 1U;
+	}
+
+	if ((MsgCnt < NumMsg) &&
+                        ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
+		if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+			if ((DmaIntrStatusReg &
+					XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != (u32)FALSE) {
+				/* DMA transfer done, Invalidate Data Cache */
+				if (!((Msg[MsgCnt].RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
+						(Msg[MsgCnt].Xfer64bit != (u8)0U)) &&
+						(InstancePtr->Config.IsCacheCoherent == 0U)) {
+					Xil_DCacheInvalidateRange((INTPTR)Msg[MsgCnt].RxBfrPtr, (INTPTR)Msg[MsgCnt].ByteCount);
+				}
+				if (XQspiPsu_SetIOMode(InstancePtr, &Msg[MsgCnt]) == (u32)TRUE) {
+					XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[MsgCnt]);
+					XQspiPsu_ManualStartEnable(InstancePtr);
+				} else {
+					InstancePtr->RxBytes = 0;
+					MsgCnt += 1;
+					DeltaMsgCnt = 1U;
+				}
+			}
+		} else {
+			if (InstancePtr->RxBytes != 0) {
+				XQspiPsu_IORead(InstancePtr, &Msg[MsgCnt], QspiPsuStatusReg);
+				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 == (u8)FALSE) &&
+		((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE) &&
+		((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) == (u32)FALSE) &&
+		((TxRxFlag & XQSPIPSU_MSG_FLAG_POLL) == (u32)FALSE) &&
+		((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != (u32)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) != (u32)FALSE) &&
+		((DeltaMsgCnt != (u8)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]);
+			XQspiPsu_ManualStartEnable(InstancePtr);
+		} 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);
+			XQspiPsu_ManualStartEnable(InstancePtr);
+		} else {
+			/* Disable interrupts */
+			XQspiPsu_WriteReg(InstancePtr->Config.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(InstancePtr->Config.BaseAddress,
+					XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
+					XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
+			}
+			/* Clear the busy flag. */
+			InstancePtr->IsBusy = (u32)FALSE;
+#if defined  (XCLOCKING)
+			Xil_ClockDisable(InstancePtr->Config.RefClk);
+#endif
+			/* Call status handler to indicate completion */
+			InstancePtr->StatusHandler(InstancePtr->StatusRef,
+						XST_SPI_TRANSFER_DONE, 0);
+		}
+	}
+	if ((TxRxFlag & XQSPIPSU_MSG_FLAG_POLL) != (u32)FALSE) {
+		XQspiPsu_PollDataHandler(InstancePtr, QspiPsuStatusReg);
+	}
+	return (s32)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(CallBackRef != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+	InstancePtr->StatusHandler = FuncPointer;
+	InstancePtr->StatusRef = CallBackRef;
+}
+
+/*****************************************************************************/
+/**
+ * @brief
+ * This API enables/ disables Write Protect pin on the flash parts.
+ *
+ * @param	InstancePtr is a pointer to the QSPIPSU driver component to use.
+ *
+ * @param	Toggle is a value of the GPIO pin
+ *
+ * @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(const XQspiPsu *InstancePtr, u32 Toggle)
+{
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+	/* For Single and Stacked flash configuration with x1 or x2 mode*/
+	if (InstancePtr->Config.ConnectionMode ==
+		XQSPIPSU_CONNECTION_MODE_SINGLE) {
+		/* Select slave */
+		XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
+
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_GPIO_OFFSET, Toggle);
+
+	} else {
+#ifdef DEBUG
+		xil_printf("Dual Parallel/Stacked configuration ");
+		xil_printf("is not supported by this API\r\n");
+#endif
+	}
+}
+
+/*****************************************************************************/
+/**
+*
+* This function start a DMA transfer.
+*
+ * @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 ByteCount is greater than
+ *		  XQSPIPSU_DMA_BYTES_MAX.
+ *		- XST_DEVICE_BUSY if a transfer is already in progress.
+ *
+ * @note	None.
+ *
+*
+******************************************************************************/
+s32 XQspiPsu_StartDmaTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+				u32 NumMsg)
+{
+	s32 Index;
+	u32 QspiPsuStatusReg = 0;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(Msg != NULL);
+	Xil_AssertNonvoid(NumMsg > 0U);
+	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 == (u32)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) != (u32)FALSE)) {
+			return (s32)XST_FAILURE;
+		}
+	}
+
+	/*
+	 * Set the busy flag, which will be cleared when the transfer is
+	 * entirely done.
+	 */
+	InstancePtr->IsBusy = (u32)TRUE;
+
+	/* Select slave */
+	XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
+	/* list */
+	Index = 0;
+	while (Index < (s32)NumMsg) {
+		InstancePtr->Msg = &Msg[Index];
+		XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[Index]);
+		if (InstancePtr->IsManualstart == (u32)TRUE) {
+#ifdef DEBUG
+			xil_printf("\nManual Start\r\n");
+#endif
+			XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+					  XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+					  XQSPIPSU_CFG_OFFSET) |
+					  XQSPIPSU_CFG_START_GEN_FIFO_MASK);
+		}
+		do {
+			if((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
+			   ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
+				break;
+			}
+			QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
+
+		} while (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE) ||
+			(InstancePtr->TxBytes != 0) ||
+			((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) == (u32)FALSE));
+
+		if(InstancePtr->ReadMode == XQSPIPSU_READMODE_IO) {
+			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;
+		}
+		Index++;
+	}
+	return (s32)XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function check for DMA transfer complete.
+*
+* @param	InstancePtr is a pointer to the XQspiPsu instance.
+*
+* @return
+*		- XST_SUCCESS if DMA transfer complete.
+*		- XST_FAILURE if DMA transfer is not completed.
+*
+* @note		None.
+*
+******************************************************************************/
+s32 XQspiPsu_CheckDmaDone(XQspiPsu *InstancePtr)
+{
+	u32 QspiPsuStatusReg;
+	u32 DmaIntrSts;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+	DmaIntrSts = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
+	if ((DmaIntrSts & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK)	!= (u32)FALSE) {
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET, DmaIntrSts);
+		/* DMA transfer done, Invalidate Data Cache */
+		if (!((InstancePtr->Msg->RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
+		    (InstancePtr->Msg->Xfer64bit != (u8)0U)) &&
+		    (InstancePtr->Config.IsCacheCoherent == 0U)) {
+			Xil_DCacheInvalidateRange((INTPTR)InstancePtr->Msg->RxBfrPtr, (INTPTR)InstancePtr->RxBytes);
+		}
+		/* De-select slave */
+		XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
+		if (InstancePtr->IsManualstart == (u8)TRUE) {
+#ifdef DEBUG
+			xil_printf("\nManual Start\r\n");
+#endif
+			XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+					  XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) |
+					  XQSPIPSU_CFG_START_GEN_FIFO_MASK);
+		}
+		do {
+			QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
+		} while ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE);
+
+		/* Clear the busy flag. */
+		InstancePtr->IsBusy = (u32)FALSE;
+
+		return (s32)XST_SUCCESS;
+	}
+	else {
+		return (s32)XST_FAILURE;
+	}
+
+}
+/** @} */
diff --git a/bsps/shared/dev/spi/xqspipsu_control.c b/bsps/shared/dev/spi/xqspipsu_control.c
new file mode 100644
index 0000000000..af2400bf4c
--- /dev/null
+++ b/bsps/shared/dev/spi/xqspipsu_control.c
@@ -0,0 +1,282 @@
+/******************************************************************************
+* Copyright (C) 2020 - 2022 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+
+/*****************************************************************************/
+/**
+ *
+ * @file xqspipsu_control.c
+ * @addtogroup Overview
+ * @{
+ *
+ * This file contains intermediate control functions used by functions
+ * in xqspipsu.c and xqspipsu_options.c files.
+ *
+ * <pre>
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who Date     Changes
+ * ----- --- -------- -----------------------------------------------
+ * 1.11   akm  03/09/20 First release
+ * 1.13   akm  01/04/21 Fix MISRA-C violations.
+ * 1.15   akm  10/21/21 Fix MISRA-C violations.
+ * 1.15   akm  03/03/22 Enable tapdelay settings for applications on
+ * 			 Microblaze platform.
+ * </pre>
+ *
+ ******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xqspipsu_control.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+
+/*****************************************************************************/
+/**
+ *
+ * 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.
+ *
+ * @return
+ *		- XST_SUCCESS if successful.
+ *		- XST_FAILURE if transfer fails.
+ *		- XST_DEVICE_BUSY if a transfer is already in progress.
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
+{
+	u32 GenFifoEntry;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(Msg != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_GenFifoEntryData\r\n");
+#endif
+
+	GenFifoEntry = 0x0U;
+	/* Bus width */
+	GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_MODE_MASK;
+	GenFifoEntry |= XQspiPsu_SelectSpiMode((u8)Msg->BusWidth);
+
+	GenFifoEntry |= InstancePtr->GenFifoCS;
+	GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_BUS_MASK;
+	GenFifoEntry |= InstancePtr->GenFifoBus;
+
+	/* Data */
+	if (((Msg->Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != (u32)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->ByteCount < 8U) &&
+		(InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA)) {
+		InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+			(XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) &
+					~XQSPIPSU_CFG_MODE_EN_MASK));
+		InstancePtr->IsUnaligned = 1;
+	}
+
+	XQspiPsu_TXRXSetup(InstancePtr, Msg, &GenFifoEntry);
+
+	XQspiPsu_GenFifoEntryDataLen(InstancePtr, Msg, &GenFifoEntry);
+
+	/* One dummy GenFifo entry in case of IO mode */
+	if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_IO) &&
+			((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
+		GenFifoEntry = 0x0U;
+#ifdef DEBUG
+		xil_printf("\nDummy FifoEntry=%08x\r\n", GenFifoEntry);
+#endif
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
+	}
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function enables the polling functionality of controller
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ *
+ * @param	FlashMsg is a pointer to the structure containing transfer data
+ *
+ * @return	None
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+void XQspiPsu_PollDataConfig(XQspiPsu *InstancePtr, XQspiPsu_Msg *FlashMsg)
+{
+
+	u32 GenFifoEntry;
+	u32 Value;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(FlashMsg != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_PollDataConfig\r\n");
+#endif
+
+	Value = XQspiPsu_CreatePollDataConfig(InstancePtr, FlashMsg);
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_POLL_CFG_OFFSET, Value);
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_P_TO_OFFSET, FlashMsg->PollTimeout);
+
+	XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
+
+	GenFifoEntry = (u32)0;
+	GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_TX;
+	GenFifoEntry |= InstancePtr->GenFifoBus;
+	GenFifoEntry |= InstancePtr->GenFifoCS;
+	GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI;
+	GenFifoEntry |= (u32)FlashMsg->PollStatusCmd;
+
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+		XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
+
+	GenFifoEntry = (u32)0;
+	GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_POLL;
+	GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_RX;
+	GenFifoEntry |= InstancePtr->GenFifoBus;
+	GenFifoEntry |= InstancePtr->GenFifoCS;
+	GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI;
+	if (((FlashMsg->Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != (u32)FALSE) {
+		GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE;
+	} else {
+		GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
+	}
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
+			GenFifoEntry);
+
+	/* One Dummy entry required for IO mode */
+	GenFifoEntry = 0x0U;
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
+			GenFifoEntry);
+
+	InstancePtr->Msg = FlashMsg;
+	InstancePtr->NumMsg = (s32)1;
+	InstancePtr->MsgCnt = 0;
+
+	Value = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_CFG_OFFSET);
+	Value &= ~XQSPIPSU_CFG_MODE_EN_MASK;
+	Value |= (XQSPIPSU_CFG_START_GEN_FIFO_MASK |
+			XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK |
+			XQSPIPSU_CFG_EN_POLL_TO_MASK);
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+			Value);
+
+	/* Enable interrupts */
+	Value = ((u32)XQSPIPSU_IER_RXNEMPTY_MASK |
+		(u32)XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK);
+
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_IER_OFFSET,
+			Value);
+
+}
+
+#if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__)
+/*****************************************************************************/
+/**
+*
+* Configures the clock according to the prescaler passed.
+*
+*
+* @param	InstancePtr is a pointer to the XQspiPsu instance.
+* @param	Prescaler - clock prescaler.
+*
+* @return
+*		- XST_SUCCESS if successful.
+*		- XST_DEVICE_BUSY if the device is currently transferring data.
+*		The transfer must complete or be aborted before setting Tapdelay.
+*
+* @note		None.
+*
+******************************************************************************/
+s32 XQspipsu_Calculate_Tapdelay(const XQspiPsu *InstancePtr, u8 Prescaler)
+{
+	u32 FreqDiv, Divider;
+	u32 Tapdelay = 0;
+	u32 LBkModeReg = 0;
+	u32 delayReg = 0;
+	s32 Status;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+	Xil_AssertNonvoid(Prescaler <= XQSPIPSU_CR_PRESC_MAXIMUM);
+
+	/*
+	 * Do not allow the slave select to change while a transfer is in
+	 * progress. Not thread-safe.
+	 */
+	if (InstancePtr->IsBusy == (u32)TRUE) {
+		Status = (s32)XST_DEVICE_BUSY;
+		goto END;
+	} else {
+
+		Divider = (u32)1U << (Prescaler+1U);
+
+		FreqDiv = (InstancePtr->Config.InputClockHz)/Divider;
+
+#if defined (versal)
+		if (FreqDiv <= XQSPIPSU_FREQ_37_5MHZ) {
+#else
+		if (FreqDiv <= XQSPIPSU_FREQ_40MHZ) {
+#endif
+			Tapdelay |= (TAPDLY_BYPASS_VALVE_40MHZ <<
+					 IOU_TAPDLY_BYPASS_LQSPI_RX_SHIFT);
+		} else if (FreqDiv <= XQSPIPSU_FREQ_100MHZ) {
+			Tapdelay |= (TAPDLY_BYPASS_VALVE_100MHZ <<
+					 IOU_TAPDLY_BYPASS_LQSPI_RX_SHIFT);
+			LBkModeReg |= (USE_DLY_LPBK << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT);
+#if defined (versal)
+			delayReg |= (u32)USE_DATA_DLY_ADJ  <<
+					XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_SHIFT;
+#else
+			delayReg |= ((u32)USE_DATA_DLY_ADJ  <<
+					XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_SHIFT) |
+							((u32)DATA_DLY_ADJ_DLY  << XQSPIPSU_DATA_DLY_ADJ_DLY_SHIFT);
+#endif
+		} else if (FreqDiv <= XQSPIPSU_FREQ_150MHZ) {
+#if defined (versal)
+			LBkModeReg |= (USE_DLY_LPBK  << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT) |
+					(LPBK_DLY_ADJ_DLY1 << XQSPIPSU_LPBK_DLY_ADJ_DLY1_SHIFT);
+#else
+			LBkModeReg |= USE_DLY_LPBK  << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT;
+#endif
+		} else {
+			Status = (s32)XST_FAILURE;
+			goto END;
+		}
+
+		Status =  XQspipsu_Set_TapDelay(InstancePtr, Tapdelay, LBkModeReg, delayReg);
+	}
+
+	END:
+	return Status;
+}
+#endif
+/** @} */
diff --git a/bsps/shared/dev/spi/xqspipsu_hw.c b/bsps/shared/dev/spi/xqspipsu_hw.c
new file mode 100644
index 0000000000..6f7708893f
--- /dev/null
+++ b/bsps/shared/dev/spi/xqspipsu_hw.c
@@ -0,0 +1,768 @@
+/******************************************************************************
+* Copyright (C) 2020 - 2022 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+
+/*****************************************************************************/
+/**
+ *
+ * @file xqspipsu_hw.c
+ * @addtogroup Overview
+ * @{
+ *
+ * This file contains functions to reads RXFifo, writes TXFifo and setup
+ * RX DMA operation, used by xqspipsu_control.c and xqspipsu_lowlevel.c files.
+ *
+ * <pre>
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who Date     Changes
+ * ----- --- -------- -----------------------------------------------
+ * 1.11   akm  03/09/20 First release
+ *         mn  03/30/20 Add xil_smc.h include for Xil_Smc calls
+ * 1.13   akm  01/04/21 Fix MISRA-C violations.
+ * 1.15   akm  10/21/21 Fix MISRA-C violations.
+ * 1.15   akm  11/16/21 Typecast function parameter with appropriate
+ * 			data type.
+ * 1.15   akm  11/30/21 Fix compilation warnings reported with -Wundef flag
+ * 1.15   akm  03/03/22 Enable tapdelay settings for applications on
+ * 			 Microblaze platform.
+ *
+ * </pre>
+ ******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xqspipsu.h"
+#include "xqspipsu_control.h"
+#if defined (__aarch64__)
+#include "xil_smc.h"
+#endif
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+
+/*****************************************************************************/
+/**
+ *
+ * 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.
+ *
+ ******************************************************************************/
+void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg, u32 Size)
+{
+	u32 Count = 0;
+	u32 Data = 0U;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(Msg != NULL);
+	Xil_AssertVoid(Size != 0U);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_FillTxFifo\r\n");
+#endif
+	while ((InstancePtr->TxBytes > 0) && (Count < Size)) {
+		if (InstancePtr->TxBytes >= 4) {
+			(void)Xil_MemCpy((u8 *)&Data, Msg->TxBfrPtr, 4);
+			Msg->TxBfrPtr += 4;
+			InstancePtr->TxBytes -= 4;
+			Count += 4U;
+		} else {
+			(void)Xil_MemCpy((u8 *)&Data, Msg->TxBfrPtr,
+				(u32)InstancePtr->TxBytes);
+			Msg->TxBfrPtr += InstancePtr->TxBytes;
+			Count += (u32)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 checks the TX buffer in the message and setup the
+ * TX FIFO as required.
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ * @param	Msg is a pointer to the structure containing transfer data.
+ *
+ * @return	None
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+void XQspiPsu_TXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
+{
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(Msg != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_TXSetup\r\n");
+#endif
+	InstancePtr->TxBytes = (s32)Msg->ByteCount;
+	InstancePtr->SendBufferPtr = Msg->TxBfrPtr;
+
+	XQspiPsu_FillTxFifo(InstancePtr, Msg, (u32)XQSPIPSU_TXD_DEPTH);
+}
+
+/*****************************************************************************/
+/**
+ *
+ * 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.
+ *
+ ******************************************************************************/
+void XQspiPsu_SetupRxDma(const XQspiPsu *InstancePtr,
+					XQspiPsu_Msg *Msg)
+{
+	s32 Remainder;
+	s32 DmaRxBytes;
+	UINTPTR AddrTemp;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(Msg != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_SetupRxDma\r\n");
+#endif
+
+	AddrTemp = ((UINTPTR)(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);
+
+#if defined(__aarch64__) || defined(__arch64__)
+	AddrTemp = ((UINTPTR)(Msg->RxBfrPtr) >> 32U);
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, (u32)AddrTemp &
+			XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK);
+#else
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, 0U);
+#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 == 0U) {
+		Xil_DCacheInvalidateRange((INTPTR)Msg->RxBfrPtr, (INTPTR)Msg->ByteCount);
+	}
+	/* Write no. of words to DMA DST SIZE */
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes);
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function sets up the RX DMA operation on a 32bit Machine
+ * For 64bit Dma transfers.
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ * @param	Msg is a pointer to the structure containing transfer data.
+ *
+ * @return	None
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+void XQspiPsu_Setup64BRxDma(const XQspiPsu *InstancePtr,
+					XQspiPsu_Msg *Msg)
+{
+	s32 Remainder;
+	s32 DmaRxBytes;
+	u64 AddrTemp;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(Msg != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_Setup64BRxDma\r\n");
+#endif
+	AddrTemp = Msg->RxAddr64bit & XQSPIPSU_QSPIDMA_DST_ADDR_MASK;
+
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_QSPIDMA_DST_ADDR_OFFSET, (u32)AddrTemp);
+
+	AddrTemp = (Msg->RxAddr64bit >> 32);
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, (u32)AddrTemp &
+			XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK);
+
+	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;
+	}
+
+	/* Write no. of words to DMA DST SIZE */
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes);
+
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function reads remaining bytes, after the completion of a DMA transfer,
+ * using IO mode
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ * @param	Msg is a pointer to the structure containing transfer data.
+ *
+ * @return
+ *		- XST_SUCCESS if successful.
+ *		- XST_FAILURE if transfer fails.
+ *		- XST_DEVICE_BUSY if a transfer is already in progress.
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+u32 XQspiPsu_SetIOMode(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
+{
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(Msg != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_DMARXComplete\r\n");
+#endif
+
+	/* Read remaining bytes using IO mode */
+	if ((InstancePtr->RxBytes % 4) != 0) {
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,	XQSPIPSU_CFG_OFFSET,
+				(XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) &
+						~XQSPIPSU_CFG_MODE_EN_MASK));
+		InstancePtr->ReadMode =	XQSPIPSU_READMODE_IO;
+		Msg->ByteCount = (u32)InstancePtr->RxBytes % 4U;
+		Msg->RxBfrPtr += (InstancePtr->RxBytes - (InstancePtr->RxBytes % 4));
+		InstancePtr->IsUnaligned = 1;
+		return (u32) TRUE;
+	}
+	return (u32) FALSE;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function checks the RX buffers in the message and setup the
+ * RX DMA as required.
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ * @param	Msg is a pointer to the structure containing transfer data.
+ *
+ * @return	None
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+void XQspiPsu_RXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
+{
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(Msg != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_RXSetup\r\n");
+#endif
+	InstancePtr->RxBytes = (s32)Msg->ByteCount;
+
+	if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+		if ((Msg->RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
+			(Msg->Xfer64bit != (u8)0U)) {
+			XQspiPsu_Setup64BRxDma(InstancePtr, Msg);
+		} else {
+			XQspiPsu_SetupRxDma(InstancePtr, Msg);
+		}
+	}
+}
+
+/*****************************************************************************/
+/**
+ *
+ * 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.
+ *
+ ******************************************************************************/
+void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+					u32 *GenFifoEntry)
+{
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(Msg != NULL);
+	Xil_AssertVoid(GenFifoEntry != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_TXRXSetup\r\n");
+#endif
+	/* Transmit */
+	if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
+			((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE)) {
+
+		*GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
+		*GenFifoEntry |= XQSPIPSU_GENFIFO_TX;
+		/* Discard RX data */
+		*GenFifoEntry &= ~XQSPIPSU_GENFIFO_RX;
+
+		/* Setup data to be TXed */
+		XQspiPsu_TXSetup(InstancePtr, Msg);
+
+		InstancePtr->RecvBufferPtr = NULL;
+		InstancePtr->RxBytes = 0;
+	}
+	/*Receive*/
+	if (((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE) &&
+			((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == (u32)FALSE)) {
+
+		/* TX auto fill */
+		*GenFifoEntry &= ~XQSPIPSU_GENFIFO_TX;
+		/* Setup RX */
+		*GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
+		*GenFifoEntry |= XQSPIPSU_GENFIFO_RX;
+
+		/* Setup DMA for data to be RXed */
+		XQspiPsu_RXSetup(InstancePtr, Msg);
+
+		InstancePtr->SendBufferPtr = NULL;
+		InstancePtr->TxBytes = 0;
+	}
+	/* If only dummy is requested as a separate entry */
+	if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == (u32)FALSE) &&
+			((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == (u32)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) != (u32)FALSE) &&
+			((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
+		*GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
+		*GenFifoEntry |= (XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX);
+
+		/* Setup data to be TXed */
+		XQspiPsu_TXSetup(InstancePtr, Msg);
+		/* Setup DMA for data to be RXed */
+		XQspiPsu_RXSetup(InstancePtr, Msg);
+	}
+}
+/*****************************************************************************/
+/**
+ *
+ * This function writes the Data length to GENFIFO entries that need to be
+ * transmitted or received.
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ * @param	Msg is a pointer to the structure containing transfer data.
+ * @param	GenFifoEntry is 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.
+ *
+ ******************************************************************************/
+void XQspiPsu_GenFifoEntryDataLen(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+		u32 *GenFifoEntry)
+{
+	u32 TempCount;
+	u32 ImmData;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(Msg != NULL);
+	Xil_AssertVoid(GenFifoEntry != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_GenFifoEntryDataLen\r\n");
+#endif
+
+	if (Msg->ByteCount <= XQSPIPSU_GENFIFO_IMM_DATA_MASK) {
+		*GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK;
+		*GenFifoEntry |= Msg->ByteCount;
+	#ifdef DEBUG
+	xil_printf("\nFifoEntry=%08x\r\n", *GenFifoEntry);
+	#endif
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
+				*GenFifoEntry);
+	} else {
+		TempCount = Msg->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) != (u32)FALSE) {
+				*GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK;
+				*GenFifoEntry |= Exponent;
+	#ifdef DEBUG
+				xil_printf("\nFifoEntry=%08x\r\n",
+					*GenFifoEntry);
+	#endif
+				XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
+					*GenFifoEntry);
+			}
+			TempCount = TempCount >> 1;
+			Exponent++;
+		}
+		/* Immediate entry */
+		*GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_EXP;
+		if ((ImmData & 0xFFU) != (u32)FALSE) {
+			*GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK;
+			*GenFifoEntry |= ImmData & 0xFFU;
+	#ifdef DEBUG
+			xil_printf("\nFifoEntry=%08x\r\n", *GenFifoEntry);
+	#endif
+			XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
+					*GenFifoEntry);
+		}
+	}
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function creates Poll config register data to write
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @param	FlashMsg is a pointer to the structure containing transfer data.
+ *
+ * @return	None
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+u32 XQspiPsu_CreatePollDataConfig(const XQspiPsu *InstancePtr,
+		const XQspiPsu_Msg *FlashMsg)
+{
+	u32 ConfigData = 0;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(FlashMsg != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_CreatePollDataConfig\r\n");
+#endif
+
+	if ((InstancePtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_UPPER) != (u32)FALSE) {
+		ConfigData = (u32)XQSPIPSU_SELECT_FLASH_BUS_LOWER <<
+				XQSPIPSU_POLL_CFG_EN_MASK_UPPER_SHIFT;
+	}
+	if ((InstancePtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_LOWER) != (u32)FALSE) {
+		ConfigData |= (u32)XQSPIPSU_SELECT_FLASH_BUS_LOWER <<
+				XQSPIPSU_POLL_CFG_EN_MASK_LOWER_SHIFT;
+	}
+	ConfigData |= (u32)(((u32)FlashMsg->PollBusMask <<
+			XQSPIPSU_POLL_CFG_MASK_EN_SHIFT) & XQSPIPSU_POLL_CFG_MASK_EN_MASK);
+	ConfigData |= (u32)(((u32)FlashMsg->PollData <<
+			XQSPIPSU_POLL_CFG_DATA_VALUE_SHIFT)
+			& XQSPIPSU_POLL_CFG_DATA_VALUE_MASK);
+	return ConfigData;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * 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.
+ *
+ ******************************************************************************/
+u32 XQspiPsu_SelectSpiMode(u8 SpiMode)
+{
+	u32 Mask;
+
+	Xil_AssertNonvoid(SpiMode > 0U);
+#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;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Enable and initialize DMA Mode, set little endain, disable poll timeout,
+ * clear prescalar bits and reset thresholds
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @return	None.
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+void XQspiPsu_SetDefaultConfig(XQspiPsu *InstancePtr)
+{
+	u32 ConfigReg;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_SetDefaultConfig\r\n");
+#endif
+
+	/* 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);
+}
+
+/*****************************************************************************/
+/**
+ *
+ * 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.
+ *
+ ******************************************************************************/
+void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr,	XQspiPsu_Msg *Msg, s32 Size)
+{
+	s32 Count = 0;
+	u32 Data;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(Msg != NULL);
+	Xil_AssertVoid(Size > 0);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_ReadRxFifo\r\n");
+#endif
+	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)Xil_MemCpy(Msg->RxBfrPtr, (u8 *)&Data, 4);
+			InstancePtr->RxBytes -= 4;
+			Msg->RxBfrPtr += 4;
+			Count += 4;
+		} else {
+			/* Read unaligned bytes (< 4 bytes) */
+			(void)Xil_MemCpy(Msg->RxBfrPtr, (u8 *)&Data,
+				(u32)InstancePtr->RxBytes);
+			Msg->RxBfrPtr += InstancePtr->RxBytes;
+			Count += InstancePtr->RxBytes;
+			InstancePtr->RxBytes = 0;
+		}
+	}
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function reads data from RXFifo in IO mode.
+ *
+ * @param	InstancePtr is a pointer to the XQspiPsu instance.
+ * @param	Msg is a pointer to the structure containing transfer data.
+ * @param	StatusReg is the Interrupt status Register value.
+ *
+ * @return	None.
+ *
+ * @note	None.
+ *
+ ******************************************************************************/
+void XQspiPsu_IORead(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+		u32 StatusReg)
+{
+	s32 RxThr;
+
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(Msg != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_IORXComplete\r\n");
+#endif
+
+	if ((StatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK) != 0U) {
+			/*
+			 * Check if PIO RX is complete and
+			 * update RxBytes
+			 */
+		RxThr = (s32)XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+				XQSPIPSU_RX_THRESHOLD_OFFSET);
+		RxThr = RxThr*4;
+		XQspiPsu_ReadRxFifo(InstancePtr, Msg, RxThr);
+
+		return;
+	}
+
+	if ((StatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != 0U) {
+		XQspiPsu_ReadRxFifo(InstancePtr, Msg, InstancePtr->RxBytes);
+	}
+}
+
+#if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__)
+/*****************************************************************************/
+/**
+*
+* This function sets the Tapdelay values for the QSPIPSU device driver.The device
+* must be idle rather than busy transferring data before setting Tapdelay.
+*
+* @param	InstancePtr is a pointer to the XQspiPsu instance.
+* @param	TapdelayBypss contains the IOU_TAPDLY_BYPASS register value.
+* @param	LPBKDelay contains the GQSPI_LPBK_DLY_ADJ register value.
+* @param	Datadelay contains the QSPI_DATA_DLY_ADJ register value.
+*
+* @return
+*		- XST_SUCCESS if options are successfully set.
+*		- XST_DEVICE_BUSY if the device is currently transferring data.
+*		The transfer must complete or be aborted before setting TapDelay.
+*
+* @note
+* This function is not thread-safe.
+*
+******************************************************************************/
+s32 XQspipsu_Set_TapDelay(const XQspiPsu *InstancePtr, u32 TapdelayBypass,
+						u32 LPBKDelay, u32 Datadelay)
+{
+	s32 Status;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+	/*
+	 * Do not allow to modify the Control Register while a transfer is in
+	 * progress. Not thread-safe.
+	 */
+	if (InstancePtr->IsBusy == (u32)TRUE) {
+		Status = (s32)XST_DEVICE_BUSY;
+	} else {
+#if defined (__aarch64__) && (EL1_NONSECURE == 1) && !defined (versal)
+		Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(XPS_SYS_CTRL_BASEADDR +
+				IOU_TAPDLY_BYPASS_OFFSET) | ((u64)(0x4) << 32),
+				(u64)TapdelayBypass, 0, 0, 0, 0, 0);
+#elif defined (versal)
+		XQspiPsu_WriteReg(XQSPIPS_BASEADDR, IOU_TAPDLY_BYPASS_OFFSET,
+				TapdelayBypass);
+#else
+		XQspiPsu_WriteReg(XPS_SYS_CTRL_BASEADDR, IOU_TAPDLY_BYPASS_OFFSET,
+				TapdelayBypass);
+#endif
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+				XQSPIPSU_LPBK_DLY_ADJ_OFFSET, LPBKDelay);
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+				XQSPIPSU_DATA_DLY_ADJ_OFFSET, Datadelay);
+
+		Status = (s32)XST_SUCCESS;
+	}
+	return Status;
+}
+#endif
+/** @} */
diff --git a/bsps/shared/dev/spi/xqspipsu_options.c b/bsps/shared/dev/spi/xqspipsu_options.c
new file mode 100644
index 0000000000..c889d64abb
--- /dev/null
+++ b/bsps/shared/dev/spi/xqspipsu_options.c
@@ -0,0 +1,532 @@
+/******************************************************************************
+* Copyright (C) 2014 - 2022 Xilinx, Inc.  All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xqspipsu_options.c
+* @addtogroup Overview
+* @{
+*
+* This file implements functions to configure the QSPIPSU component,
+* specifically some optional settings, clock and flash related information.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.0   hk  08/21/14 First release
+*       sk  03/13/15 Added IO mode support.
+*       sk  04/24/15 Modified the code according to MISRAC-2012.
+* 1.1   sk  04/12/16 Added debug message prints.
+* 1.2	nsk 07/01/16 Modified XQspiPsu_SetOptions() to support
+*		     LQSPI options and updated OptionsTable
+*       rk  07/15/16 Added support for TapDelays at different frequencies.
+* 1.7	tjs 01/17/18 Added support to toggle the WP pin of flash. (PR#2448)
+* 1.7	tjs	03/14/18 Added support in EL1 NS mode. (CR#974882)
+* 1.8  tjs 05/02/18 Added support for IS25LP064 and IS25WP064.
+* 1.8  tjs 07/26/18 Resolved cppcheck errors. (CR#1006336)
+* 1.9	tjs	04/17/18 Updated register addresses as per the latest revision
+* 					 of versal (CR#999610)
+* 1.9  aru 01/17/19 Fixes violations according to MISRAC-2012
+*                  in safety mode and modified the code such as
+*                  Added Xil_MemCpy inplace of memcpy,Declared the pointer param
+*                  as Pointer to const, declared XQspi_Set_TapDelay() as static.
+* 1.9 akm 03/08/19 Set recommended clock and data tap delay values for 40MHZ,
+*		   100MHZ and 150MHZ frequencies(CR#1023187)
+* 1.10 akm 08/22/19 Set recommended tap delay values for 37.5MHZ, 100MHZ and
+*		    150MHZ frequencies in Versal.
+* 1.11 	akm 11/07/19 Removed LQSPI register access in Versal.
+* 1.11	akm 11/15/19 Fixed Coverity deadcode warning in
+* 				XQspipsu_Calculate_Tapdelay().
+* 1.11 akm 03/09/20 Reorganize the source code, enable qspi controller and
+*		     interrupts in XQspiPsu_CfgInitialize() API.
+* 1.13 akm 01/04/21 Fix MISRA-C violations.
+* 1.15 akm 03/03/22 Enable tapdelay settings for applications on Microblaze
+* 		     platform.
+*
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xqspipsu_control.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/**
+ * Create the table of options which are processed to get/set the device
+ * options. These options are table driven to allow easy maintenance and
+ * expansion of the options.
+ */
+typedef struct {
+	u32 Option;	/**< Get/Set the device option */
+	u32 Mask;	/**< Mask */
+} OptionsMap;
+
+static OptionsMap OptionsTable[] = {
+	{XQSPIPSU_CLK_ACTIVE_LOW_OPTION, XQSPIPSU_CFG_CLK_POL_MASK},
+	{XQSPIPSU_CLK_PHASE_1_OPTION, XQSPIPSU_CFG_CLK_PHA_MASK},
+	{XQSPIPSU_MANUAL_START_OPTION, XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK},
+#if !defined (versal)
+	{XQSPIPSU_LQSPI_MODE_OPTION, XQSPIPSU_CFG_WP_HOLD_MASK},
+#endif
+};
+
+/**
+ * Number of options in option table
+ */
+#define XQSPIPSU_NUM_OPTIONS	(sizeof(OptionsTable) / sizeof(OptionsMap))
+
+/*****************************************************************************/
+/**
+*
+* This function sets the options for the QSPIPSU device driver.The options
+* control how the device behaves relative to the QSPIPSU bus. The device must be
+* idle rather than busy transferring data before setting these device options.
+*
+* @param	InstancePtr is a pointer to the XQspiPsu instance.
+* @param	Options contains the specified options to be set. This is a bit
+*		mask where a 1 indicates the option should be turned ON and
+*		a 0 indicates no action. One or more bit values may be
+*		contained in the mask. See the bit definitions named
+*		XQSPIPSU_*_OPTIONS in the file xqspipsu.h.
+*
+* @return
+*		- XST_SUCCESS if options are successfully set.
+*		- XST_DEVICE_BUSY if the device is currently transferring data.
+*		The transfer must complete or be aborted before setting options.
+*
+* @note
+* This function is not thread-safe.
+*
+******************************************************************************/
+s32 XQspiPsu_SetOptions(XQspiPsu *InstancePtr, u32 Options)
+{
+	u32 ConfigReg;
+	u32 Index;
+#if !defined (versal)
+	u32 QspiPsuOptions;
+#endif
+	s32 Status;
+	u32 OptionsVal;
+	OptionsVal = Options;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+	/*
+	 * Do not allow to modify the Control Register while a transfer is in
+	 * progress. Not thread-safe.
+	 */
+	if (InstancePtr->IsBusy == (u32)TRUE) {
+		Status = (s32)XST_DEVICE_BUSY;
+	} else {
+		ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+					      XQSPIPSU_CFG_OFFSET);
+#if !defined (versal)
+		QspiPsuOptions = OptionsVal & XQSPIPSU_LQSPI_MODE_OPTION;
+		OptionsVal &= (~XQSPIPSU_LQSPI_MODE_OPTION);
+#endif
+		/*
+		 * Loop through the options table, turning the option on
+		 * depending on whether the bit is set in the incoming options flag.
+		 */
+		for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
+			if ((OptionsVal & OptionsTable[Index].Option) ==
+					OptionsTable[Index].Option) {
+				/* Turn it on */
+				ConfigReg |= OptionsTable[Index].Mask;
+			} else {
+				/* Turn it off */
+				ConfigReg &= ~(OptionsTable[Index].Mask);
+			}
+		}
+		/*
+		 * Now write the control register. Leave it to the upper layers
+		 * to restart the device.
+		 */
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+				 ConfigReg);
+
+		if ((OptionsVal & XQSPIPSU_MANUAL_START_OPTION) != (u32)FALSE) {
+			InstancePtr->IsManualstart = (u8)TRUE;
+		}
+#if !defined (versal)
+		if ((QspiPsuOptions & XQSPIPSU_LQSPI_MODE_OPTION) != (u32)FALSE) {
+			if ((Options & XQSPIPSU_LQSPI_LESS_THEN_SIXTEENMB) != (u32)FALSE) {
+				XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET,XQSPIPS_LQSPI_CR_RST_STATE);
+			} else {
+				XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET,XQSPIPS_LQSPI_CR_4_BYTE_STATE);
+			}
+			XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_CFG_OFFSET,XQSPIPS_LQSPI_CFG_RST_STATE);
+			/* Enable the QSPI controller */
+			XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_EN_OFFSET,XQSPIPSU_EN_MASK);
+		} else {
+			/*
+			 * Check for the LQSPI configuration options.
+			 */
+			ConfigReg = XQspiPsu_ReadReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET);
+			ConfigReg &= ~(XQSPIPSU_LQSPI_CR_LINEAR_MASK);
+			XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET, ConfigReg);
+		}
+#endif
+		Status = (s32)XST_SUCCESS;
+	}
+	return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function resets the options for the QSPIPSU device driver.The options
+* control how the device behaves relative to the QSPIPSU bus. The device must be
+* idle rather than busy transferring data before setting these device options.
+*
+* @param	InstancePtr is a pointer to the XQspiPsu instance.
+* @param	Options contains the specified options to be set. This is a bit
+*		mask where a 1 indicates the option should be turned OFF and
+*		a 0 indicates no action. One or more bit values may be
+*		contained in the mask. See the bit definitions named
+*		XQSPIPSU_*_OPTIONS in the file xqspipsu.h.
+*
+* @return
+*		- XST_SUCCESS if options are successfully set.
+*		- XST_DEVICE_BUSY if the device is currently transferring data.
+*		The transfer must complete or be aborted before setting options.
+*
+* @note
+* This function is not thread-safe.
+*
+******************************************************************************/
+s32 XQspiPsu_ClearOptions(XQspiPsu *InstancePtr, u32 Options)
+{
+	u32 ConfigReg;
+	u32 Index;
+	s32 Status;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+	/*
+	 * Do not allow to modify the Control Register while a transfer is in
+	 * progress. Not thread-safe.
+	 */
+	if (InstancePtr->IsBusy == (u32)TRUE) {
+		Status = (s32)XST_DEVICE_BUSY;
+	} else {
+
+		ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+					      XQSPIPSU_CFG_OFFSET);
+
+		/*
+		 * Loop through the options table, turning the option on
+		 * depending on whether the bit is set in the incoming options flag.
+		 */
+		for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
+			if ((Options & OptionsTable[Index].Option) != (u32)FALSE) {
+				/* Turn it off */
+				ConfigReg &= ~OptionsTable[Index].Mask;
+			}
+		}
+		/*
+		 * Now write the control register. Leave it to the upper layers
+		 * to restart the device.
+		 */
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+				 ConfigReg);
+
+		if ((Options & XQSPIPSU_MANUAL_START_OPTION) != (u32)FALSE) {
+			InstancePtr->IsManualstart = (u8)FALSE;
+		}
+
+		Status = (s32)XST_SUCCESS;
+	}
+
+	return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function gets the options for the QSPIPSU device. The options control how
+* the device behaves relative to the QSPIPSU bus.
+*
+* @param	InstancePtr is a pointer to the XQspiPsu instance.
+*
+* @return
+*
+* Options contains the specified options currently set. This is a bit value
+* where a 1 means the option is on, and a 0 means the option is off.
+* See the bit definitions named XQSPIPSU_*_OPTIONS in file xqspipsu.h.
+*
+* @note		None.
+*
+******************************************************************************/
+u32 XQspiPsu_GetOptions(const XQspiPsu *InstancePtr)
+{
+	u32 OptionsFlag = 0;
+	u32 ConfigReg;
+	u32 Index;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+	/* Loop through the options table to grab options */
+	for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
+		/*
+		 * Get the current options from QSPIPSU configuration register.
+		 */
+		ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+						      XQSPIPSU_CFG_OFFSET);
+		if ((ConfigReg & OptionsTable[Index].Mask) != (u32)FALSE) {
+			OptionsFlag |= OptionsTable[Index].Option;
+		}
+	}
+	return OptionsFlag;
+}
+
+/*****************************************************************************/
+/**
+*
+* Configures the clock according to the prescaler passed.
+*
+*
+* @param	InstancePtr is a pointer to the XQspiPsu instance.
+* @param	Prescaler - clock prescaler to be set.
+*
+* @return
+*		- XST_SUCCESS if successful.
+*		- XST_DEVICE_IS_STARTED if the device is already started.
+*		- XST_DEVICE_BUSY if the device is currently transferring data.
+*		It must be stopped to re-initialize.
+*
+* @note		None.
+*
+******************************************************************************/
+s32 XQspiPsu_SetClkPrescaler(const XQspiPsu *InstancePtr, u8 Prescaler)
+{
+	u32 ConfigReg;
+	s32 Status;
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+	Xil_AssertNonvoid(Prescaler <= XQSPIPSU_CR_PRESC_MAXIMUM);
+
+	/*
+	 * Do not allow the slave select to change while a transfer is in
+	 * progress. Not thread-safe.
+	 */
+	if (InstancePtr->IsBusy == (u32)TRUE) {
+		Status = (s32)XST_DEVICE_BUSY;
+	} else {
+		/*
+		 * Read the configuration register, mask out the relevant bits, and set
+		 * them with the shifted value passed into the function. Write the
+		 * results back to the configuration register.
+		 */
+		ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+					      XQSPIPSU_CFG_OFFSET);
+
+		ConfigReg &= ~(u32)XQSPIPSU_CFG_BAUD_RATE_DIV_MASK;
+		ConfigReg |= (u32) ((u32)Prescaler & (u32)XQSPIPSU_CR_PRESC_MAXIMUM) <<
+				    XQSPIPSU_CFG_BAUD_RATE_DIV_SHIFT;
+
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+				ConfigReg);
+
+#if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__)
+		Status = XQspipsu_Calculate_Tapdelay(InstancePtr,Prescaler);
+#else
+		Status = (s32)XST_SUCCESS;
+#endif
+	}
+	return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function should be used to tell the QSPIPSU driver the HW flash
+* configuration being used. This API should be called at least once in the
+* application. If desired, it can be called multiple times when switching
+* between communicating to different flahs devices/using different configs.
+*
+* @param	InstancePtr is a pointer to the XQspiPsu instance.
+* @param	FlashCS - Flash Chip Select.
+* @param	FlashBus - Flash Bus (Upper, Lower or Both).
+*
+* @return
+*		- XST_SUCCESS if successful.
+*		- XST_DEVICE_IS_STARTED if the device is already started.
+*		It must be stopped to re-initialize.
+*
+* @note		If this function is not called at least once in the application,
+*		the driver assumes there is a single flash connected to the
+*		lower bus and CS line.
+*
+******************************************************************************/
+void XQspiPsu_SelectFlash(XQspiPsu *InstancePtr, u8 FlashCS, u8 FlashBus)
+{
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(FlashCS > 0U);
+	Xil_AssertVoid(FlashBus > 0U);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_SelectFlash\r\n");
+#endif
+
+	/*
+	 * Bus and CS lines selected here will be updated in the instance and
+	 * used for subsequent GENFIFO entries during transfer.
+	 */
+
+	/* Choose slave select line */
+	switch (FlashCS) {
+		case XQSPIPSU_SELECT_FLASH_CS_BOTH:
+			InstancePtr->GenFifoCS = (u32)XQSPIPSU_GENFIFO_CS_LOWER |
+						(u32)XQSPIPSU_GENFIFO_CS_UPPER;
+			break;
+		case XQSPIPSU_SELECT_FLASH_CS_UPPER:
+			InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_UPPER;
+			break;
+		case XQSPIPSU_SELECT_FLASH_CS_LOWER:
+			InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
+			break;
+		default:
+			InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
+			break;
+	}
+
+	/* Choose bus */
+	switch (FlashBus) {
+		case XQSPIPSU_SELECT_FLASH_BUS_BOTH:
+			InstancePtr->GenFifoBus = (u32)XQSPIPSU_GENFIFO_BUS_LOWER |
+						(u32)XQSPIPSU_GENFIFO_BUS_UPPER;
+			break;
+		case XQSPIPSU_SELECT_FLASH_BUS_UPPER:
+			InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_UPPER;
+			break;
+		case XQSPIPSU_SELECT_FLASH_BUS_LOWER:
+			InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
+			break;
+		default:
+			InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
+			break;
+	}
+#ifdef DEBUG
+	xil_printf("\nGenFifoCS is %08x and GenFifoBus is %08x\r\n",
+				InstancePtr->GenFifoCS, InstancePtr->GenFifoBus);
+#endif
+
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets the Read mode for the QSPIPSU device driver.The device
+* must be idle rather than busy transferring data before setting Read mode
+* options.
+*
+* @param	InstancePtr is a pointer to the XQspiPsu instance.
+* @param	Mode contains the specified Mode to be set. See the
+* 		bit definitions named XQSPIPSU_READMODE_* in the file xqspipsu.h.
+*
+* @return
+*		- XST_SUCCESS if options are successfully set.
+*		- XST_DEVICE_BUSY if the device is currently transferring data.
+*		The transfer must complete or be aborted before setting Mode.
+*
+* @note
+* This function is not thread-safe.
+*
+******************************************************************************/
+s32 XQspiPsu_SetReadMode(XQspiPsu *InstancePtr, u32 Mode)
+{
+	u32 ConfigReg;
+	s32 Status;
+
+#ifdef DEBUG
+	xil_printf("\nXQspiPsu_SetReadMode\r\n");
+#endif
+
+	Xil_AssertNonvoid(InstancePtr != NULL);
+	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+	Xil_AssertNonvoid((Mode == XQSPIPSU_READMODE_DMA) || (Mode == XQSPIPSU_READMODE_IO));
+
+	/*
+	 * Do not allow to modify the Control Register while a transfer is in
+	 * progress. Not thread-safe.
+	 */
+	if (InstancePtr->IsBusy == (u32)TRUE) {
+		Status = (s32)XST_DEVICE_BUSY;
+	} else {
+
+		InstancePtr->ReadMode = Mode;
+
+		ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+					      XQSPIPSU_CFG_OFFSET);
+
+		if (Mode == XQSPIPSU_READMODE_DMA) {
+			ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
+			ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
+		} else {
+			ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
+		}
+
+		XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+				 ConfigReg);
+
+		Status = (s32)XST_SUCCESS;
+	}
+#ifdef DEBUG
+	xil_printf("\nRead Mode is %08x\r\n", InstancePtr->ReadMode);
+#endif
+	return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets the Write Protect and Hold options for the QSPIPSU device
+* driver.The device must be idle rather than busy transferring data before
+* setting Write Protect and Hold options.
+*
+* @param	InstancePtr is a pointer to the XQspiPsu instance.
+* @param	Value of the WP_HOLD bit in configuration register
+*
+* @return	None
+*
+* @note
+* This function is not thread-safe. This function can only be used with single
+* flash configuration and x1/x2 data mode. This function cannot be used with
+* x4 data mode and dual parallel and stacked flash configuration.
+*
+******************************************************************************/
+void XQspiPsu_SetWP(const XQspiPsu *InstancePtr, u8 Value)
+{
+	u32 ConfigReg;
+	Xil_AssertVoid(InstancePtr != NULL);
+	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+	Xil_AssertVoid(InstancePtr->IsBusy != TRUE);
+
+	ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+			XQSPIPSU_CFG_OFFSET);
+	ConfigReg |= (u32)((u32)Value << XQSPIPSU_CFG_WP_HOLD_SHIFT);
+	XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+					ConfigReg);
+}
+/** @} */
-- 
2.34.1



More information about the devel mailing list