/**
*
* Main function to execute the Numonyx Quad Serial Flash Read/Write example.
*
* @param	None
*
* @return	XST_SUCCESS if successful else XST_FAILURE.
*
* @note		None
*
******************************************************************************/
int main()
{
	int Status;
	u32 Index;
	u32 Address;
	XIsf_WriteParam WriteParam;
	XIsf_ReadParam ReadParam;

	/*
	 * Initialize the SPI driver so that it's ready to use,
	 * specify the device ID that is generated in xparameters.h.
	 */
	Status = XSpi_Initialize(&Spi, SPI_DEVICE_ID);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Connect the SPI driver to the interrupt subsystem such that
	 * interrupts can occur. This function is application specific.
	 */
	Status = SetupInterruptSystem(&Spi);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Setup the handler for the SPI that will be called from the interrupt
	 * context when an SPI status occurs, specify a pointer to the SPI
	 * driver instance as the callback reference so the handler is able to
	 * access the instance data.
	 */
	XIsf_SetStatusHandler(&Isf, &Spi, (XSpi_StatusHandler)SpiHandler);

	/*
	 * Start the SPI driver so that interrupts and the device are enabled.
	 */
	XSpi_Start(&Spi);

	/*
	 * Set the QSPI options
	 */
	Status = XIsf_SetSpiConfiguration(&Isf, &Spi,
			XSP_MASTER_OPTION | XSP_MANUAL_SSELECT_OPTION,
			XISF_SPI_PRESCALER);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Initialize the Serial Flash Library.
	 */
	Status = XIsf_Initialize(&Isf, &Spi, ISF_SPI_SELECT, IsfWriteBuffer);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Set The transfer Mode to Interrupt
	 */
	XIsf_SetTransferMode(&Isf,XISF_INTERRUPT_MODE);

	/*
	 * Specify the address in the Serial Flash for the Erase/Write/Read
	 * operations.
	 */
	Address = ISF_TEST_ADDRESS;

	/*
	 * The following code Erases a Sector in the Numonyx Serial Flash.
	 */

	/*
	 * Perform the Write Enable operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Flash is not Busy.
	 */
	Status = IsfWaitForFlashNotBusy();
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Perform the Sector Erase operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_Erase(&Isf, XISF_SECTOR_ERASE, Address);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Flash is not Busy.
	 */
	Status = IsfWaitForFlashNotBusy();
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Perform the Write Enable operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Flash is not Busy.
	 */
	Status = IsfWaitForFlashNotBusy();
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Set the
	 * - Address within the Serial Flash where the data is to be written.
	 * - Number of bytes to be written to the Serial Flash.
	 * - Write Buffer which contains the data to be written to the Serial
	 *   Flash.
	 */
	WriteParam.Address = Address;
	WriteParam.NumBytes = ISF_PAGE_SIZE;
	WriteParam.WritePtr = WriteBuffer;

	/*
	 * Prepare the write buffer. Fill in the data need to be written into
	 * Serial Flash.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
		WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
	}

	/*
	 * Perform the Write operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_Write(&Isf, XISF_DUAL_IP_PAGE_WRITE, (void*) &WriteParam);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Flash is not Busy.
	 */
	Status = IsfWaitForFlashNotBusy();
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Read from the flash using Dual Output Fast Read command.
	 * Set the
	 * - Address in the Serial Flash where the data is to be read from.
	 * - Number of bytes to be read from the Serial Flash.
	 * - Read Buffer to which the data is to be read.
	 * - Number of dummy bytes for the read command.
	 */
	ReadParam.Address = Address;
	ReadParam.NumBytes = ISF_PAGE_SIZE;
	ReadParam.ReadPtr = ReadBuffer;
	ReadParam.NumDummyBytes = DUAL_READ_DUMMY_BYTES;

	/*
	 * Clear the read Buffer.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
	    DUAL_READ_DUMMY_BYTES; Index++) {
		ReadBuffer[Index] = 0x0;
	}

	/*
	 * Perform the read operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_Read(&Isf, XISF_DUAL_OP_FAST_READ, (void*) &ReadParam);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Compare the data read against the data Written.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
		if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
				DUAL_READ_DUMMY_BYTES] !=
					(u8)(Index + ISF_TEST_BYTE)) {
			return XST_FAILURE;
		}
	}

	/*
	 * Perform the Write Enable operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Flash is not Busy.
	 */
	Status = IsfWaitForFlashNotBusy();
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Move to the next page in the flash.
	 */
	Address += ISF_PAGE_SIZE;

	/*
	 * Set the
	 * - Address within the Serial Flash where the data is to be written.
	 * - Number of bytes to be written to the Serial Flash.
	 * - Write Buffer which contains the data to be written to the Serial
	 *   Flash.
	 */
	WriteParam.Address = Address;
	WriteParam.NumBytes = ISF_PAGE_SIZE;
	WriteParam.WritePtr = WriteBuffer;

	/*
	 * Prepare the write buffer. Fill in the data need to be written into
	 * Serial Flash.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
		WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
	}

	/*
	 * Perform the Write operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_Write(&Isf, XISF_DUAL_IP_EXT_PAGE_WRITE, (void*) &WriteParam);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Flash is not Busy.
	 */
	Status = IsfWaitForFlashNotBusy();
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Read from the flash using Dual Input/Output Fast Read command.
	 * Set the
	 * - Address in the Serial Flash where the data is to be read from.
	 * - Number of bytes to be read from the Serial Flash.
	 * - Read Buffer to which the data is to be read.
	 * - Number of dummy bytes for the read command.
	 */
	ReadParam.Address = Address;
	ReadParam.NumBytes = ISF_PAGE_SIZE;
	ReadParam.ReadPtr = ReadBuffer;
	ReadParam.NumDummyBytes = DUAL_IO_READ_DUMMY_BYTES;

	/*
	 * Clear the read Buffer.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
	    DUAL_IO_READ_DUMMY_BYTES; Index++) {
		ReadBuffer[Index] = 0x0;
	}

	/*
	 * Perform the read operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_Read(&Isf, XISF_DUAL_IO_FAST_READ, (void*) &ReadParam);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Compare the data read against the data Written.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
		if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
				DUAL_IO_READ_DUMMY_BYTES] !=
					(u8)(Index + ISF_TEST_BYTE)) {
			return XST_FAILURE;
		}
	}

	/*
	 * Perform the Write Enable operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Flash is not Busy.
	 */
	Status = IsfWaitForFlashNotBusy();
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Move to the next page in the flash.
	 */
	Address += ISF_PAGE_SIZE;

	/*
	 * Set the
	 * - Address within the Serial Flash where the data is to be written.
	 * - Number of bytes to be written to the Serial Flash.
	 * - Write Buffer which contains the data to be written to the Serial
	 *   Flash.
	 */
	WriteParam.Address = Address;
	WriteParam.NumBytes = ISF_PAGE_SIZE;
	WriteParam.WritePtr = WriteBuffer;

	/*
	 * Prepare the write buffer. Fill in the data need to be written into
	 * Serial Flash.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
		WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
	}

	/*
	 * Perform the Write operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_Write(&Isf, XISF_QUAD_IP_PAGE_WRITE, (void*) &WriteParam);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Flash is not Busy.
	 */
	Status = IsfWaitForFlashNotBusy();
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Read from the flash using Quad Output Fast Read command.
	 * Set the
	 * - Address in the Serial Flash where the data is to be read from.
	 * - Number of bytes to be read from the Serial Flash.
	 * - Read Buffer to which the data is to be read.
	 * - Number of dummy bytes for the read command.
	 */
	ReadParam.Address = Address;
	ReadParam.NumBytes = ISF_PAGE_SIZE;
	ReadParam.ReadPtr = ReadBuffer;
	ReadParam.NumDummyBytes = QUAD_READ_DUMMY_BYTES;

	/*
	 * Clear the read Buffer.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
	    QUAD_READ_DUMMY_BYTES; Index++) {
		ReadBuffer[Index] = 0x0;
	}

	/*
	 * Perform the read operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_Read(&Isf, XISF_QUAD_OP_FAST_READ, (void*) &ReadParam);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Compare the data read against the data Written.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
		if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
				QUAD_READ_DUMMY_BYTES] !=
					(u8)(Index + ISF_TEST_BYTE)) {
			return XST_FAILURE;
		}
	}

	/*
	 * Perform the Write Enable operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_WriteEnable(&Isf, XISF_WRITE_ENABLE);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Flash is not Busy.
	 */
	Status = IsfWaitForFlashNotBusy();
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Move to the next page in the flash.
	 */
	Address += ISF_PAGE_SIZE;

	/*
	 * Set the
	 * - Address within the Serial Flash where the data is to be written.
	 * - Number of bytes to be written to the Serial Flash.
	 * - Write Buffer which contains the data to be written to the Serial
	 *   Flash.
	 */
	WriteParam.Address = Address;
	WriteParam.NumBytes = ISF_PAGE_SIZE;
	WriteParam.WritePtr = WriteBuffer;

	/*
	 * Prepare the write buffer. Fill in the data need to be written into
	 * Serial Flash.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
		WriteParam.WritePtr[Index] = Index + ISF_TEST_BYTE;
	}

	/*
	 * Perform the Write operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_Write(&Isf, XISF_QUAD_IP_EXT_PAGE_WRITE,
			    (void*) &WriteParam);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Flash is not Busy.
	 */
	Status = IsfWaitForFlashNotBusy();
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Read from the flash using Quad Input/Output Fast Read command.
	 * Set the
	 * - Address in the Serial Flash where the data is to be read from.
	 * - Number of bytes to be read from the Serial Flash.
	 * - Read Buffer to which the data is to be read.
	 * - Number of dummy bytes for the read command.
	 */
	ReadParam.Address = Address;
	ReadParam.NumBytes = ISF_PAGE_SIZE;
	ReadParam.ReadPtr = ReadBuffer;
	ReadParam.NumDummyBytes = QUAD_IO_READ_DUMMY_BYTES;

	/*
	 * Clear the read Buffer.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE + XISF_CMD_SEND_EXTRA_BYTES +
	    QUAD_IO_READ_DUMMY_BYTES; Index++) {
		ReadBuffer[Index] = 0x0;
	}

	/*
	 * Perform the read operation.
	 */
	TransferInProgress = TRUE;
	Status = XIsf_Read(&Isf, XISF_QUAD_IO_FAST_READ, (void*) &ReadParam);
	if(Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait till the Transfer is complete and check for errors.
	 */
	while(TransferInProgress);
	if(ErrorCount != 0) {
		return XST_FAILURE;
	}

	/*
	 * Compare the data read against the data written.
	 */
	for(Index = 0; Index < ISF_PAGE_SIZE; Index++) {
		if(ReadBuffer[Index + XISF_CMD_SEND_EXTRA_BYTES +
				QUAD_IO_READ_DUMMY_BYTES] !=
					(u8)(Index + ISF_TEST_BYTE)) {
			return XST_FAILURE;
		}
	}

	return XST_SUCCESS;
}
Exemple #2
0
/**
*
* The geometry of the underlying Serial Flash is determined by reading the
* Joint Electron Device Engineering Council (JEDEC) Device Information and
* the Status Register of the Serial Flash.
* This API when called initializes the SPI interface with default settings.
* With custom settings, user should call XIsf_SetSpiConfiguration() and then
* call this API.
*
* @param	InstancePtr is a pointer to the XIsf instance.
* @param	SpiInstPtr is a pointer to the XIsf_Iface instance to be worked on.
* @param	SlaveSelect is a 32-bit mask with a 1 in the bit position of the
*		slave being selected. Only one slave can be selected at a time.
* @param	WritePtr is a pointer to the buffer allocated by the user to be
*		used by the In-system and Serial Flash Library to perform any
*		read/write operations on the Serial Flash device.
*		User applications must pass the address of this buffer for the
*		Library to work.
*		- Write operations :
*			- The size of this buffer should be equal to the Number
*			of bytes to be written to the Serial Flash +
*			XISF_CMD_MAX_EXTRA_BYTES.
*			- The size of this buffer should be large enough for
*			usage across all the applications that use a common
*			instance of the Serial Flash.
*			- A minimum of one byte and a maximum of ISF_PAGE_SIZE
*			bytes can be written to the Serial Flash, through a
*			single Write operation.
* 		- Read operations :
* 			- The size of this buffer should be equal to
*			XISF_CMD_MAX_EXTRA_BYTES, if the application only reads
*			from the Serial Flash (no write operations).
*
* @return	- XST_SUCCESS if successful.
*		- XST_DEVICE_IS_STOPPED if the device must be started before
*		transferring data.
*		- XST_FAILURE, otherwise.
*
* @note		- The XIsf_Initialize() API is a blocking call (for both
*		polled and interrupt modes of the Spi driver). It reads the
*		JEDEC information of the device and waits till the transfer is
*		complete before checking if the information is valid.
*		- This library can support multiple instances of Serial Flash at
*		a time, provided they are of the same device family (either
*		Atmel, Intel or STM, Winbond or Spansion) as the device family
*		is selected at compile time.
*
******************************************************************************/
int XIsf_Initialize(XIsf *InstancePtr, XIsf_Iface *SpiInstPtr, u8 SlaveSelect,
				u8 *WritePtr)
{
	int Status;
	u8 ReadBuf[XISF_INFO_READ_BYTES + XISF_INFO_EXTRA_BYTES];

	if (InstancePtr == NULL) {
		return XST_FAILURE;
	}

	if (SpiInstPtr == NULL) {
		return XST_FAILURE;
	}

	if (WritePtr == NULL) {
		return XST_FAILURE;
	}

	InstancePtr->IsReady = FALSE;
	InstancePtr->SpiSlaveSelect = SlaveSelect;
	InstancePtr->WriteBufPtr = WritePtr;

#ifdef XPAR_XISF_INTERFACE_AXISPI
	if (SpiInstPtr->IsStarted != XIL_COMPONENT_IS_STARTED) {
		 return XST_DEVICE_IS_STOPPED;
	}
#endif

	if (!InstancePtr->RegDone) {
		XIsf_SetSpiConfiguration(InstancePtr, SpiInstPtr,
				XISF_SPI_OPTIONS, XISF_SPI_PRESCALER);
	}

	/*
         * Get the JEDEC Device Info.
         * The IsReady is temporarily made TRUE and
	 * transfer is set in polling mode to fetch the JEDEC Info.
         */
	XIsf_SetTransferMode(InstancePtr, XISF_POLLING_MODE);
        InstancePtr->IsReady = TRUE;
        Status = XIsf_GetDeviceInfo(InstancePtr, ReadBuf);
        InstancePtr->IsReady = FALSE;
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

#ifdef XPAR_XISF_INTERFACE_AXISPI
	/*
	 * Wait until the transfer is complete.
	 */
	do {
		Status =
		InstancePtr->XIsf_Iface_SetSlaveSelect(InstancePtr->SpiInstPtr,
					InstancePtr->SpiSlaveSelect);
	} while(Status == XST_DEVICE_BUSY);

	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
#endif

#if (XPAR_XISF_FLASH_FAMILY == ATMEL)
	/*
	 * Check for Atmel Serial Flash.
	 */
	Status = AtmelFlashInitialize(InstancePtr, ReadBuf);

#endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */

#if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \
    (XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == SPANSION) \
	|| (XPAR_XISF_FLASH_FAMILY == SST))

	/*
	 * Check for Intel/STM/Winbond/Spansion Serial Flash.
	 */
	Status = IntelStmFlashInitialize(InstancePtr, ReadBuf);

#endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL) || (XPAR_XISF_FLASH_FAMILY==STM) \
	(XPAR_XISF_FLASH_FAMILY == WINBOND) ||
	(XPAR_XISF_FLASH_FAMILY == SPANSION)) */

	return Status;
}
/**
* The purpose of this function is to illustrate how to use the XQspiPs
* device driver in interrupt mode. This function writes and reads data
* from a serial FLASH.
*
* @return	XST_SUCCESS if successful else XST_FAILURE.
*
* @note
*
* This function calls other functions which contain loops that may be infinite
* if interrupts are not working such that it may not return. If the device
* slave select is not correct and the device is not responding on bus it will
* read a status of 0xFF for the status register as the bus is pulled up.
*
*****************************************************************************/
int QspiFlashPollExample(XScuGic *IntcInstancePtr, XQspiPs *QspiInstancePtr,
			 u16 QspiDeviceId, u16 QspiIntrId)
{
	u8 *BufferPtr;
	u8 UniqueValue;
	int Count;
	int Page;
	int Status;
    	u32 Options;

	/*
	* Lookup the device configuration in the temporary CROM table. Use this
	* configuration info down below when initializing this component.
	*/
	ConfigPtr = XQspiPs_LookupConfig(QspiDeviceId);
	if (ConfigPtr == NULL) {
		return XST_DEVICE_NOT_FOUND;
	}

	Status = XQspiPs_CfgInitialize(QspiInstancePtr, ConfigPtr,
			ConfigPtr->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Set the QSPI options
	 */
	Options = XQSPIPS_FORCE_SSELECT_OPTION |
			XQSPIPS_MANUAL_START_OPTION |
			XQSPIPS_HOLD_B_DRIVE_OPTION;
	XIsf_SetSpiConfiguration(&Isf, QspiInstancePtr, Options,
			XISF_SPI_PRESCALER);

	if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_STACKED) {
			/*
			 * Enable two flash memories, Shared bus
			 * (NOT separate bus), L_PAGE selected by default
		 	 */
			XQspiPs_SetLqspiConfigReg(QspiInstancePtr,
						DUAL_STACK_CONFIG_WRITE);
	}

	if(ConfigPtr->ConnectionMode == XQSPIPS_CONNECTION_MODE_PARALLEL) {
			/*
			 * Enable two flash memories on separate buses
			 */
			XQspiPs_SetLqspiConfigReg(QspiInstancePtr,
						DUAL_QSPI_CONFIG_WRITE);
	}

	/* Initialize the XILISF Library */
	XIsf_Initialize(&Isf, QspiInstancePtr, FLASH_QSPI_SELECT,
				   IsfWriteBuffer);

	/*
	 * Initialize the write buffer for a pattern to write to the FLASH
	 * and the read buffer to zero so it can be verified after the read,
	 * the test value that is added to the unique value allows the value
	 * to be changed in a debug environment to guarantee
	 */
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;
		Count++, UniqueValue++) {
		WriteBuffer[Count] = (u8)(UniqueValue + Test_Polled);
	}
	memset(ReadBuffer, 0x00, sizeof(ReadBuffer));


	Status = FlashErase(&Isf, TEST_ADDRESS, MAX_DATA);
	if(Status != XST_SUCCESS){
		return XST_FAILURE;
	}

	/*
	 * Write the data in the write buffer to the serial FLASH a page at a
	 * time, starting from TEST_ADDRESS
	 */

	for (Page = 0; Page < PAGE_COUNT; Page++) {
		Status = FlashWrite(&Isf,
			(Page * PAGE_SIZE) + TEST_ADDRESS, PAGE_SIZE,
				XISF_QUAD_IP_PAGE_WRITE);
		if(Status != XST_SUCCESS){
			return XST_FAILURE;
		}
	}

	/******************************************************
	 **********************NORMAL READ*********************
	 ******************************************************/

	/*
	 * Read the contents of the FLASH from TEST_ADDRESS, using Normal Read
	 * command
	 */
	Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA, XISF_READ);
	if(Status != XST_SUCCESS){
		return XST_FAILURE;
	}

	/*
	 * Setup a pointer to the start of the data that was read into the read
	 * buffer and verify the data read is the data that was written
		 */
	BufferPtr = ReadBuffer;
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
			Count++, UniqueValue++) {
		if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
			return XST_FAILURE;
		}
	}


	/******************************************************
	 **********************FAST READ***********************
	 ******************************************************/

	/*
	 * Read the contents of the FLASH from TEST_ADDRESS, using Fast Read
	 * command
	 */
	Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA,
							XISF_FAST_READ);
	if(Status != XST_SUCCESS){
		return XST_FAILURE;
	}

	/*
	 * Setup a pointer to the start of the data that was read into the read
	 * buffer and verify the data read is the data that was written
	 */

	BufferPtr = ReadBuffer;
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
			Count++, UniqueValue++) {
		if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
			return XST_FAILURE;
		}
	}


	/******************************************************
	 ******************DUAL OP FAST READ*******************
	 ******************************************************/

	/*
	 * Read the contents of the FLASH from TEST_ADDRESS, using DUAL OP
	 * Fast Read command
	 */
	Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA,
						XISF_DUAL_OP_FAST_READ);
	if(Status != XST_SUCCESS){
		return XST_FAILURE;
	}

	/*
	 * Setup a pointer to the start of the data that was read into the read
	 * buffer and verify the data read is the data that was written
	 */

	BufferPtr = ReadBuffer;
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
			Count++, UniqueValue++) {

		if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
			return XST_FAILURE;
		}
	}

	/******************************************************
	 ******************QUAD IO FAST READ*******************
	 ******************************************************/

	/*
	 * Read the contents of the FLASH from TEST_ADDRESS, using QUAD IO
	 * Fast Read command
	 */
	Status = FlashRead(&Isf, TEST_ADDRESS, MAX_DATA,
						XISF_QUAD_OP_FAST_READ);
	if(Status != XST_SUCCESS){
		return XST_FAILURE;
	}

	/*
	 * Setup a pointer to the start of the data that was read into the read
	 * buffer and verify the data read is the data that was written
	 */

	BufferPtr = ReadBuffer;
	for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
			Count++, UniqueValue++) {
		if (BufferPtr[Count] != (u8)(UniqueValue + Test_Polled)) {
			return XST_FAILURE;
		}
	}

	return XST_SUCCESS;
}