diff --git a/lib/sw_services/xilisf/src/include/xilisf.h b/lib/sw_services/xilisf/src/include/xilisf.h index 444dd24b..230a68f7 100644 --- a/lib/sw_services/xilisf/src/include/xilisf.h +++ b/lib/sw_services/xilisf/src/include/xilisf.h @@ -496,6 +496,7 @@ * These were done to fix CR#858950. * 5.3 sk 06/01/15 Used Half of Actual byte count for calculating * Real Byte count in parallel mode. CR# 859979. +* 5.4 sk 08/07/17 Added QSPIPSU flash interface support for ZynqMP. * * * @@ -517,6 +518,8 @@ extern "C" { #include "xspips.h" #elif XPAR_XISF_INTERFACE_PSQSPI #include "xqspips.h" +#elif XPAR_XISF_INTERFACE_QSPIPSU +#include "xqspipsu.h" #endif /** @@ -637,6 +640,8 @@ extern "C" { #elif XPAR_XISF_INTERFACE_PSQSPI #define XISF_SPI_OPTIONS (XQSPIPS_MANUAL_START_OPTION | \ XQSPIPS_FORCE_SSELECT_OPTION) +#elif XPAR_XISF_INTERFACE_QSPIPSU +#define XISF_SPI_OPTIONS XQSPIPSU_MANUAL_START_OPTION #elif XPAR_XISF_INTERFACE_PSSPI #define XISF_SPI_OPTIONS (XSPIPS_MASTER_OPTION | \ XSPIPS_FORCE_SSELECT_OPTION) @@ -647,6 +652,8 @@ extern "C" { */ #ifdef XPAR_XISF_INTERFACE_PSQSPI #define XISF_SPI_PRESCALER XQSPIPS_CLK_PRESCALE_4 +#elif XPAR_XISF_INTERFACE_QSPIPSU +#define XISF_SPI_PRESCALER XQSPIPSU_CLK_PRESCALE_4 #elif XPAR_XISF_INTERFACE_PSSPI #define XISF_SPI_PRESCALER XSPIPS_CLK_PRESCALE_8 #elif XPAR_XISF_INTERFACE_AXISPI @@ -765,6 +772,8 @@ typedef XSpi XIsf_Iface; typedef XSpiPs XIsf_Iface; #elif XPAR_XISF_INTERFACE_PSQSPI typedef XQspiPs XIsf_Iface; +#elif XPAR_XISF_INTERFACE_QSPIPSU +typedef XQspiPsu XIsf_Iface; #endif typedef void (*XIsf_StatusHandler) (void *CallBackRef, u32 StatusEvent, unsigned int ByteCount); @@ -788,7 +797,8 @@ typedef struct { * 0 - Default/Normal Addressing Mode * 1 - Power-Of-2 Addressing Mode */ u16 DeviceCode; /**< The Serial Flash Device Code */ -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) u8 DeviceIDMemSize; /**< Byte of device ID indicating the memory * size */ u8 NumDie; /**< No. of die forming a single flash */ @@ -807,21 +817,36 @@ typedef struct { u8 FourByteAddrMode; /**< In four byte address mode flag */ int (*XIsf_Iface_SetOptions) (XIsf_Iface *InstancePtr, u32 Options); -#ifndef XPAR_XISF_INTERFACE_PSQSPI +#if (!defined (XPAR_XISF_INTERFACE_PSQSPI)) && \ + (!defined (XPAR_XISF_INTERFACE_QSPIPSU)) int (*XIsf_Iface_SetSlaveSelect) (XIsf_Iface *InstancePtr, u8 SlaveMask); +#else +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + void (*XIsf_Iface_SetSlaveSelect) + (XIsf_Iface *InstancePtr, u8 FlashCS, u8 FlashBus); #else int (*XIsf_Iface_SetSlaveSelect) (XIsf_Iface *InstancePtr); +#endif #endif int (*XIsf_Iface_Start) (XIsf_Iface *InstancePtr); +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + int (*XIsf_Iface_Transfer) + (XIsf_Iface *InstancePtr, XQspiPsu_Msg *Msg, + u32 NumMsg); + int (*XIsf_Iface_PolledTransfer) + (XIsf_Iface *InstancePtr, XQspiPsu_Msg *Msg, + u32 NumMsg); +#else int (*XIsf_Iface_Transfer) (XIsf_Iface *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, unsigned int ByteCount); int (*XIsf_Iface_PolledTransfer) (XIsf_Iface *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr, unsigned ByteCount); +#endif int (*XIsf_Iface_SetClkPrescaler) (XIsf_Iface *InstancePtr, u8 PreScaler); XIsf_StatusHandler StatusHandler; @@ -986,7 +1011,8 @@ int XIsf_Read(XIsf *InstancePtr, XIsf_ReadOperation Operation, int XIsf_Erase(XIsf *InstancePtr, XIsf_EraseOperation Operation, u32 Address); #if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ - defined(XPAR_XISF_INTERFACE_AXISPI)) + (defined(XPAR_XISF_INTERFACE_AXISPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU))) /* * Function for entering into 4 byte mode for Micron flash. */ diff --git a/lib/sw_services/xilisf/src/xilisf.c b/lib/sw_services/xilisf/src/xilisf.c index 1d02c18c..cfe9e5d8 100644 --- a/lib/sw_services/xilisf/src/xilisf.c +++ b/lib/sw_services/xilisf/src/xilisf.c @@ -92,6 +92,7 @@ * 5.2 asa 05/12/15 Added APIs to support 4 byte addressing for Micron flash. * 2 APIs were added, one to enter into 4 byte mode and the other * to exit from the same. +* 5.4 sk 08/07/17 Added QSPIPSU flash interface support for ZynqMP. * * * @@ -103,6 +104,8 @@ /************************** Constant Definitions *****************************/ +#define SIXTEENMB 0x1000000 /**< Sixteen MB */ + /**************************** Type Definitions *******************************/ #if (XPAR_XISF_FLASH_FAMILY == ATMEL) @@ -123,7 +126,8 @@ typedef struct { || (XPAR_XISF_FLASH_FAMILY == SST) || \ (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - (!defined(XPAR_XISF_INTERFACE_PSQSPI))) \ + ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \ + (!defined(XPAR_XISF_INTERFACE_QSPIPSU)))) /** * The following structure specifies the geometry of the Intel/STM Serial Flash. */ @@ -139,11 +143,13 @@ typedef struct { (XPAR_XISF_FLASH_FAMILY == SST) || \ (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - (!defined(XPAR_XISF_INTERFACE_PSQSPI)))*/ + ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \ + (!defined(XPAR_XISF_INTERFACE_QSPIPSU))))*/ #if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - defined(XPAR_XISF_INTERFACE_PSQSPI)) + (defined(XPAR_XISF_INTERFACE_PSQSPI) || \ + defined(XPAR_XISF_INTERFACE_QSPIPSU))) /** * The following structure specifies the geometry of the Spansion/Micron * Serial Flash. @@ -171,7 +177,8 @@ typedef struct { #endif /* (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - defined(XPAR_XISF_INTERFACE_PSQSPI)) */ + (defined(XPAR_XISF_INTERFACE_PSQSPI) || \ + defined(XPAR_XISF_INTERFACE_QSPIPSU)))*/ /***************** Macros (Inline Functions) Definitions *********************/ @@ -193,23 +200,27 @@ static int AtmelFlashInitialize(XIsf *InstancePtr, u8 *ReadBuf); #if (((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \ (XPAR_XISF_FLASH_FAMILY == SST) || (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \ + (!defined(XPAR_XISF_INTERFACE_QSPIPSU)))) static int IntelStmFlashInitialize(XIsf *InstancePtr, u8 *ReadBuf); #endif /* (((XPAR_XISF_FLASH_FAMILY == INTEL) || \ (XPAR_XISF_FLASH_FAMILY == STM) || \ (XPAR_XISF_FLASH_FAMILY == SST) || \ (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - (!defined(XPAR_XISF_INTERFACE_PSQSPI))) */ + ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \ + (!defined(XPAR_XISF_INTERFACE_QSPIPSU)))) */ #if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - defined(XPAR_XISF_INTERFACE_PSQSPI)) + (defined(XPAR_XISF_INTERFACE_PSQSPI) || \ + defined(XPAR_XISF_INTERFACE_QSPIPSU))) static int SpaMicWinFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr); #endif /* (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - defined(XPAR_XISF_INTERFACE_PSQSPI)) */ + (defined(XPAR_XISF_INTERFACE_PSQSPI) || \ + defined(XPAR_XISF_INTERFACE_QSPIPSU))) */ /************************** Variable Definitions *****************************/ @@ -250,7 +261,8 @@ static const AtmelDeviceGeometry AtmelDevices[] = { || (XPAR_XISF_FLASH_FAMILY == SST) || \ (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \ + (!defined(XPAR_XISF_INTERFACE_QSPIPSU)))) static const IntelStmDeviceGeometry IntelStmDevices[] = { {XISF_MANUFACTURER_ID_INTEL, XISF_INTEL_DEV_S3316MBIT, XISF_BYTES256_PER_PAGE, XISF_PAGES256_PER_SECTOR, @@ -401,11 +413,13 @@ static const IntelStmDeviceGeometry IntelStmDevices[] = { || (XPAR_XISF_FLASH_FAMILY == SST) || \ (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - (!defined(XPAR_XISF_INTERFACE_PSQSPI)))*/ + ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \ + (!defined(XPAR_XISF_INTERFACE_QSPIPSU))))*/ #if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - defined(XPAR_XISF_INTERFACE_PSQSPI)) + (defined(XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU))) static const SpaMicWinDeviceGeometry SpaMicWinDevices[] = { {0x10000, 0x100, 256, 0x10000, 0x1000000, XISF_MANUFACTURER_ID_SPANSION, XISF_SPANSION_ID_BYTE2_128, @@ -485,7 +499,8 @@ static const SpaMicWinDeviceGeometry SpaMicWinDevices[] = { }; #endif /* (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - defined(XPAR_XISF_INTERFACE_PSQSPI)) */ + (defined(XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU))) */ /* * The following variables are shared between non-interrupt processing and @@ -620,7 +635,8 @@ int XIsf_Initialize(XIsf *InstancePtr, XIsf_Iface *SpiInstPtr, u8 SlaveSelect, || (XPAR_XISF_FLASH_FAMILY == SST) || \ (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \ + (!defined(XPAR_XISF_INTERFACE_QSPIPSU)))) /* * Check for Intel/STM/Winbond/Spansion Serial Flash. @@ -631,16 +647,19 @@ int XIsf_Initialize(XIsf *InstancePtr, XIsf_Iface *SpiInstPtr, u8 SlaveSelect, || (XPAR_XISF_FLASH_FAMILY == SST) || \ (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - (!defined(XPAR_XISF_INTERFACE_PSQSPI)))*/ + ((!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \ + (!defined(XPAR_XISF_INTERFACE_QSPIPSU))))*/ #if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - defined(XPAR_XISF_INTERFACE_PSQSPI)) + (defined(XPAR_XISF_INTERFACE_PSQSPI) || \ + defined(XPAR_XISF_INTERFACE_QSPIPSU))) Status = SpaMicWinFlashInitialize(InstancePtr, ReadBuf); #endif /*(((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - defined(XPAR_XISF_INTERFACE_PSQSPI)) */ + (defined(XPAR_XISF_INTERFACE_PSQSPI) || \ + defined(XPAR_XISF_INTERFACE_QSPIPSU))) */ return Status; } @@ -712,6 +731,10 @@ int XIsf_GetStatus(XIsf *InstancePtr, u8 *ReadPtr) { int Status; u8 Mode; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_Msg FlashMsg[2]; + u8* NULLPtr = NULL; +#endif if (InstancePtr == NULL) { return (int)(XST_FAILURE); @@ -725,6 +748,7 @@ int XIsf_GetStatus(XIsf *InstancePtr, u8 *ReadPtr) return (int)(XST_FAILURE); } +#ifndef XPAR_XISF_INTERFACE_QSPIPSU /* * Prepare the Write Buffer. */ @@ -736,6 +760,30 @@ int XIsf_GetStatus(XIsf *InstancePtr, u8 *ReadPtr) */ Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, ReadPtr, XISF_STATUS_RDWR_BYTES); +#else + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_READ; + FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsg[1].TxBfrPtr = NULL; + FlashMsg[1].RxBfrPtr = ReadPtr; + FlashMsg[1].ByteCount = 2; + FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX; + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XQSPIPSU_CONNECTION_MODE_PARALLEL){ + FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE; + } + InstancePtr->SpiInstPtr->Msg = FlashMsg; + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2); +#endif + /* * Get the Transfer Mode */ @@ -774,6 +822,10 @@ int XIsf_GetStatusReg2(XIsf *InstancePtr, u8 *ReadPtr) { int Status; u8 Mode; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_Msg FlashMsg[2]; +#endif + u8* NULLPtr = NULL; if (InstancePtr == NULL) { return (int)(XST_FAILURE); @@ -787,6 +839,7 @@ int XIsf_GetStatusReg2(XIsf *InstancePtr, u8 *ReadPtr) return (int)(XST_FAILURE); } +#ifndef XPAR_XISF_INTERFACE_QSPIPSU /* * Prepare the Write Buffer. */ @@ -798,6 +851,29 @@ int XIsf_GetStatusReg2(XIsf *InstancePtr, u8 *ReadPtr) */ Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, ReadPtr, XISF_STATUS_RDWR_BYTES); +#else + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_STATUSREG_READ; + FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsg[1].TxBfrPtr = NULL; + FlashMsg[1].RxBfrPtr = ReadPtr; + FlashMsg[1].ByteCount = 2; + FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX; + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XQSPIPSU_CONNECTION_MODE_PARALLEL){ + FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE; + } + InstancePtr->SpiInstPtr->Msg = FlashMsg; + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2); +#endif /* * Get the Transfer Mode */ @@ -836,6 +912,10 @@ int XIsf_GetDeviceInfo(XIsf *InstancePtr, u8 *ReadPtr) { int Status; u8 Mode; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_Msg FlashMsg[2]; + u8* NULLPtr = NULL; +#endif if (InstancePtr == NULL) { return (int)(XST_FAILURE); @@ -849,6 +929,7 @@ int XIsf_GetDeviceInfo(XIsf *InstancePtr, u8 *ReadPtr) return (int)(XST_FAILURE); } +#ifndef XPAR_XISF_INTERFACE_QSPIPSU /* * Prepare the Write Buffer. */ @@ -863,6 +944,26 @@ int XIsf_GetDeviceInfo(XIsf *InstancePtr, u8 *ReadPtr) */ Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, ReadPtr, XISF_INFO_READ_BYTES); +#else + InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_ISFINFO_READ; + FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsg[1].TxBfrPtr = NULL; + FlashMsg[1].RxBfrPtr = ReadPtr; + FlashMsg[1].ByteCount = 5; + FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX; + InstancePtr->SpiInstPtr->Msg = FlashMsg; + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2); +#endif + /* * Get the Transfer Mode */ @@ -904,6 +1005,10 @@ int XIsf_WriteEnable(XIsf *InstancePtr, u8 WriteEnable) u8 Mode; u8 WriteEnableBuf[1] = {0}; u8 * NULLPtr = NULL; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_Msg FlashMsg[2]; +#endif + #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)) @@ -930,11 +1035,25 @@ int XIsf_WriteEnable(XIsf *InstancePtr, u8 WriteEnable) Xil_AssertNonvoid(NULLPtr == NULL); +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].TxBfrPtr = WriteEnableBuf; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + InstancePtr->SpiInstPtr->Msg = FlashMsg; + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 1); +#else + /* * Initiate the Transfer. */ Status = XIsf_Transfer(InstancePtr, WriteEnableBuf, NULLPtr, XISF_CMD_WRITE_ENABLE_DISABLE_BYTES); +#endif /* * Get the Transfer Mode @@ -986,6 +1105,9 @@ int XIsf_Ioctl(XIsf *InstancePtr, XIsf_IoctlOperation Operation) int Status; u8 Mode; u8* NULLPtr = NULL; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_Msg FlashMsg[2]; +#endif #if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \ (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ @@ -1035,11 +1157,26 @@ int XIsf_Ioctl(XIsf *InstancePtr, XIsf_IoctlOperation Operation) Xil_AssertNonvoid(NULLPtr == NULL); +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = NumBytes; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + InstancePtr->SpiInstPtr->Msg = FlashMsg; + /* + * Initiate the Transfer. + */ + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 1); +#else + /* * Initiate the Transfer. */ Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, NumBytes); +#endif + /* * Get the Transfer Mode */ @@ -1084,17 +1221,17 @@ int XIsf_Ioctl(XIsf *InstancePtr, XIsf_IoctlOperation Operation) ******************************************************************************/ int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr, u32 ByteCount) { - int Status; + int Status = XST_SUCCESS; /* * Select the Serial Flash as a slave. */ -#ifndef XPAR_XISF_INTERFACE_PSQSPI +#ifdef XPAR_XISF_INTERFACE_PSQSPI Status = InstancePtr->XIsf_Iface_SetSlaveSelect( - InstancePtr->SpiInstPtr,InstancePtr->SpiSlaveSelect); -#else + InstancePtr->SpiInstPtr); +#elif (!defined(XPAR_XISF_INTERFACE_QSPIPSU)) Status = InstancePtr->XIsf_Iface_SetSlaveSelect( - InstancePtr->SpiInstPtr); + InstancePtr->SpiInstPtr,InstancePtr->SpiSlaveSelect); #endif if (Status != (int)(XST_SUCCESS)) { return (int)(XST_FAILURE); @@ -1123,22 +1260,36 @@ int XIsf_Transfer(XIsf *InstancePtr, u8 *WritePtr, u8* ReadPtr, u32 ByteCount) #endif if (InstancePtr->IntrMode == XISF_INTERRUPT_MODE) { -#if defined(XPAR_XISF_INTERFACE_PSQSPI) || defined(XPAR_XISF_INTERFACE_PSSPI) +#if defined(XPAR_XISF_INTERFACE_PSQSPI) || defined(XPAR_XISF_INTERFACE_PSSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) XIsf_TransferInProgress = TRUE; #endif +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + Status = InstancePtr->XIsf_Iface_Transfer( + InstancePtr->SpiInstPtr, + InstancePtr->SpiInstPtr->Msg, ByteCount); +#else Status = InstancePtr->XIsf_Iface_Transfer( InstancePtr->SpiInstPtr, WritePtr, ReadPtr, ByteCount); -#if defined(XPAR_XISF_INTERFACE_PSQSPI) || defined(XPAR_XISF_INTERFACE_PSSPI) +#endif +#if defined(XPAR_XISF_INTERFACE_PSQSPI) || defined(XPAR_XISF_INTERFACE_PSSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) while (XIsf_TransferInProgress != 0){ /*NOP*/ } #endif } else { +#if XPAR_XISF_INTERFACE_QSPIPSU + Status = InstancePtr->XIsf_Iface_PolledTransfer( + InstancePtr->SpiInstPtr, + InstancePtr->SpiInstPtr->Msg, ByteCount); +#else Status = InstancePtr->XIsf_Iface_PolledTransfer( InstancePtr->SpiInstPtr, WritePtr, ReadPtr, ByteCount); +#endif } if (Status != (int)(XST_SUCCESS)) { @@ -1173,6 +1324,12 @@ void XIsf_RegisterInterface(XIsf *InstancePtr) InstancePtr->XIsf_Iface_Transfer = XSpiPs_Transfer; InstancePtr->XIsf_Iface_PolledTransfer = XSpiPs_PolledTransfer; InstancePtr->XIsf_Iface_SetClkPrescaler = XSpiPs_SetClkPrescaler; +#elif XPAR_XISF_INTERFACE_QSPIPSU + InstancePtr->XIsf_Iface_SetOptions = XQspiPsu_SetOptions; + InstancePtr->XIsf_Iface_SetSlaveSelect = XQspiPsu_SelectFlash; + InstancePtr->XIsf_Iface_Transfer = XQspiPsu_InterruptTransfer; + InstancePtr->XIsf_Iface_PolledTransfer = XQspiPsu_PolledTransfer; + InstancePtr->XIsf_Iface_SetClkPrescaler = XQspiPsu_SetClkPrescaler; #elif XPAR_XISF_INTERFACE_PSQSPI InstancePtr->XIsf_Iface_SetOptions = XQspiPs_SetOptions; InstancePtr->XIsf_Iface_SetSlaveSelect = XQspiPs_SetSlaveSelect; @@ -1331,7 +1488,8 @@ static int AtmelFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr) #endif /* (XPAR_XISF_FLASH_FAMILY == ATMEL) */ #if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ - defined(XPAR_XISF_INTERFACE_AXISPI)) + (defined(XPAR_XISF_INTERFACE_AXISPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU))) /*****************************************************************************/ /** * @@ -1352,6 +1510,11 @@ int XIsf_MicronFlashEnter4BAddMode(XIsf *InstancePtr) int Status; u8* NULLPtr = NULL; u8 Mode; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_Msg FlashMsg[2]; + u8 FlashMake, ReadStatusCmd, FSRFlag; + u8 FlashStatus[2] = {0}; +#endif if (InstancePtr == NULL) { return (int)(XST_FAILURE); @@ -1367,8 +1530,83 @@ int XIsf_MicronFlashEnter4BAddMode(XIsf *InstancePtr) InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_ENTER_4BYTE_ADDR_MODE; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + /* + * Enable write before transfer + */ + Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } + + FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + InstancePtr->SpiInstPtr->Msg = FlashMsg; + + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 1); + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + if((InstancePtr->NumDie > (u8)1) && + (FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) { + ReadStatusCmd = READ_FLAG_STATUS_CMD; + FSRFlag = 1; + } else { + ReadStatusCmd = READ_STATUS_CMD; + FSRFlag = 0; + } + + while (1) { + FlashMsg[0].TxBfrPtr = &ReadStatusCmd; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsg[1].TxBfrPtr = NULL; + FlashMsg[1].RxBfrPtr = FlashStatus; + FlashMsg[1].ByteCount = 2; + FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX; + + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE; + } + InstancePtr->SpiInstPtr->Msg = FlashMsg; + + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + if(FSRFlag) { + FlashStatus[1] &= FlashStatus[0]; + } else { + FlashStatus[1] |= FlashStatus[0]; + } + } + + if(FSRFlag) { + if ((FlashStatus[1] & 0x80) != 0) { + break; + } + } else { + if ((FlashStatus[1] & 0x01) == 0) { + break; + } + } + } +#else + Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, XISF_CMD_4BYTE_ADDR_ENTER_EXIT_BYTES); +#endif Mode = XIsf_GetTransferMode(InstancePtr); @@ -1405,6 +1643,11 @@ int XIsf_MicronFlashExit4BAddMode(XIsf *InstancePtr) int Status; u8* NULLPtr = NULL; u8 Mode; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_Msg FlashMsg[2]; + u8 FlashMake, ReadStatusCmd, FSRFlag; + u8 FlashStatus[2] = {0}; +#endif if (InstancePtr == NULL) { return (int)(XST_FAILURE); @@ -1420,8 +1663,82 @@ int XIsf_MicronFlashExit4BAddMode(XIsf *InstancePtr) InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_EXIT_4BYTE_ADDR_MODE; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + /* + * Enable write before transfer + */ + Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE); + if (Status != (int)XST_SUCCESS) { + return (int)XST_FAILURE; + } + + FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + InstancePtr->SpiInstPtr->Msg = FlashMsg; + + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 1); + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + + if((InstancePtr->NumDie > (u8)1) && + (FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) { + ReadStatusCmd = READ_FLAG_STATUS_CMD; + FSRFlag = 1; + } else { + ReadStatusCmd = READ_STATUS_CMD; + FSRFlag = 0; + } + + while (1) { + FlashMsg[0].TxBfrPtr = &ReadStatusCmd; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsg[1].TxBfrPtr = NULL; + FlashMsg[1].RxBfrPtr = FlashStatus; + FlashMsg[1].ByteCount = 2; + FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX; + + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE; + } + InstancePtr->SpiInstPtr->Msg = FlashMsg; + + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + if(FSRFlag) { + FlashStatus[1] &= FlashStatus[0]; + } else { + FlashStatus[1] |= FlashStatus[0]; + } + } + + if(FSRFlag) { + if ((FlashStatus[1] & 0x80) != 0) { + break; + } + } else { + if ((FlashStatus[1] & 0x01) == 0) { + break; + } + } + } +#else Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, XISF_CMD_4BYTE_ADDR_ENTER_EXIT_BYTES); +#endif Mode = XIsf_GetTransferMode(InstancePtr); @@ -1437,12 +1754,14 @@ int XIsf_MicronFlashExit4BAddMode(XIsf *InstancePtr) return Status; } #endif /* ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ - defined(XPAR_XISF_INTERFACE_AXISPI)) */ + (defined(XPAR_XISF_INTERFACE_AXISPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU)))*/ #if (((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \ (XPAR_XISF_FLASH_FAMILY == SST) || (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - (!defined(XPAR_XISF_INTERFACE_PSQSPI))) + (!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \ + (!defined(XPAR_XISF_INTERFACE_QSPIPSU))) /*****************************************************************************/ /** * @@ -1526,11 +1845,13 @@ static int IntelStmFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr) || (XPAR_XISF_FLASH_FAMILY == SST) || \ (XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - (!defined(XPAR_XISF_INTERFACE_PSQSPI)))*/ + (!defined(XPAR_XISF_INTERFACE_PSQSPI)) && \ + (!defined(XPAR_XISF_INTERFACE_QSPIPSU)))*/ #if (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - defined(XPAR_XISF_INTERFACE_PSQSPI)) + (defined(XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU))) /*****************************************************************************/ /** * @@ -1560,6 +1881,31 @@ static int SpaMicWinFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr) u8 * WriteBfrPtr = InstancePtr->WriteBufPtr; int Status; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + u8* NULLPtr = NULL; + XQspiPsu_Msg FlashMsg[2]; + /* + * Read ID + */ + *WriteBfrPtr = READ_ID; + FlashMsg[0].TxBfrPtr = WriteBfrPtr; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsg[1].TxBfrPtr = NULL; + FlashMsg[1].RxBfrPtr = BufferPtr; + FlashMsg[1].ByteCount = 3; + FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX; + InstancePtr->SpiInstPtr->Msg = FlashMsg; + + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2); + + BufferPtr[1] = BufferPtr[0]; + BufferPtr[3] = BufferPtr[2]; +#else /* * Read ID in Auto mode. */ @@ -1570,6 +1916,7 @@ static int SpaMicWinFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr) Status = XIsf_Transfer(InstancePtr, WriteBfrPtr, BufferPtr, RD_ID_SIZE); +#endif if (Status != (int)(XST_SUCCESS)) { return (int)(XST_FAILURE); } @@ -1717,11 +2064,38 @@ static int SpaMicWinFlashInitialize(XIsf *InstancePtr, u8 *BufferPtr) InstancePtr->NumSectors = SpaMicWinDevices[XIsf_FCTIndex].NumSect; InstancePtr->IsReady = TRUE; +#if (XPAR_XISF_FLASH_FAMILY == SPANSION) && \ + defined(XPAR_XISF_INTERFACE_QSPIPSU) + /* + * This will put the flash in 4Byte Addressing mode. Exit from + * 4Byte has to take care by the user if required. + */ + if (SpaMicWinDevices[XIsf_FCTIndex].FlashDeviceSize > SIXTEENMB) { + if (InstancePtr->SpiInstPtr->Config.ConnectionMode == XISF_QSPIPS_CONNECTION_MODE_PARALLEL) { + InstancePtr->XIsf_Iface_SetSlaveSelect(InstancePtr->SpiInstPtr, + XQSPIPSU_SELECT_FLASH_CS_UPPER, XQSPIPSU_SELECT_FLASH_BUS_UPPER); + Status = XIsf_MicronFlashEnter4BAddMode(InstancePtr); + } + InstancePtr->XIsf_Iface_SetSlaveSelect(InstancePtr->SpiInstPtr, + XQSPIPSU_SELECT_FLASH_CS_LOWER, XQSPIPSU_SELECT_FLASH_BUS_LOWER); + Status = XIsf_MicronFlashEnter4BAddMode(InstancePtr); + if (InstancePtr->SpiInstPtr->Config.ConnectionMode == XISF_QSPIPS_CONNECTION_MODE_STACKED) { + InstancePtr->XIsf_Iface_SetSlaveSelect(InstancePtr->SpiInstPtr, + XQSPIPSU_SELECT_FLASH_CS_UPPER, XQSPIPSU_SELECT_FLASH_BUS_LOWER); + Status = XIsf_MicronFlashEnter4BAddMode(InstancePtr); + } + if (Status != (int)(XST_SUCCESS)) { + return (int)(XST_FAILURE); + } + } +#endif + return (int)(XST_SUCCESS); } #endif /* (((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) && \ - defined(XPAR_XISF_INTERFACE_PSQSPI))*/ + (defined(XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU)))*/ /*****************************************************************************/ /** @@ -1742,26 +2116,36 @@ u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address) { u32 LqspiCr; u32 RealAddr = {0}; -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) switch(QspiPtr->Config.ConnectionMode) { case XISF_QSPIPS_CONNECTION_MODE_SINGLE: +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_SelectFlash(QspiPtr, XQSPIPSU_SELECT_FLASH_CS_LOWER, + XQSPIPSU_SELECT_FLASH_BUS_LOWER); +#endif RealAddr = Address; break; case XISF_QSPIPS_CONNECTION_MODE_STACKED: +#ifndef XPAR_XISF_INTERFACE_QSPIPSU /* * Get the current LQSPI Config reg value */ LqspiCr = XQspiPs_GetLqspiConfigReg(QspiPtr); - +#endif /* Select lower or upper Flash based on sector address */ if(Address & SpaMicWinDevices[XIsf_FCTIndex].FlashDeviceSize) { +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_SelectFlash(QspiPtr, + XQSPIPSU_SELECT_FLASH_CS_UPPER, XQSPIPSU_SELECT_FLASH_BUS_LOWER); +#else /* * Set selection to U_PAGE */ XQspiPs_SetLqspiConfigReg(QspiPtr, LqspiCr | XQSPIPS_LQSPI_CR_U_PAGE_MASK); - +#endif /* * Subtract first flash size when accessing second * flash. @@ -1771,25 +2155,36 @@ u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address) } else{ +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_SelectFlash(QspiPtr, + XQSPIPSU_SELECT_FLASH_CS_LOWER, XQSPIPSU_SELECT_FLASH_BUS_LOWER); +#else /* * Set selection to L_PAGE */ XQspiPs_SetLqspiConfigReg(QspiPtr, LqspiCr & (~XQSPIPS_LQSPI_CR_U_PAGE_MASK)); +#endif RealAddr = Address; } +#ifndef XPAR_XISF_INTERFACE_QSPIPSU /* * Assert the Flash chip select. */ (void)XQspiPs_SetSlaveSelect(QspiPtr); +#endif break; case XISF_QSPIPS_CONNECTION_MODE_PARALLEL: /* * The effective address in each flash is the actual * address / 2 */ +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_SelectFlash(QspiPtr, + XQSPIPSU_SELECT_FLASH_CS_BOTH, XQSPIPSU_SELECT_FLASH_BUS_BOTH); +#endif RealAddr = Address / 2; break; default: @@ -1914,7 +2309,10 @@ void XIsf_SetStatusHandler(XIsf *InstancePtr, XIsf_Iface *XIfaceInstancePtr, * the QSPI driver instance as the callback reference so the handler * is able to access the instance data */ -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_SetStatusHandler(XIfaceInstancePtr, XIfaceInstancePtr, + (XQspiPsu_StatusHandler) XIsf_IfaceHandler); +#elif XPAR_XISF_INTERFACE_PSQSPI XQspiPs_SetStatusHandler(XIfaceInstancePtr, XIfaceInstancePtr, (XQspiPs_StatusHandler) XIsf_IfaceHandler); #elif XPAR_XISF_INTERFACE_PSSPI diff --git a/lib/sw_services/xilisf/src/xilisf_erase.c b/lib/sw_services/xilisf/src/xilisf_erase.c index c2e09970..bde02d03 100644 --- a/lib/sw_services/xilisf/src/xilisf_erase.c +++ b/lib/sw_services/xilisf/src/xilisf_erase.c @@ -58,6 +58,7 @@ * BulkErase() * 5.2 asa 05/12/15 Added support for Micron (N25Q256A) flash part * which supports 4 byte addressing. +* 5.4 sk 08/07/17 Added QSPIPSU flash interface support for ZynqMP. * * ******************************************************************************/ @@ -84,7 +85,8 @@ static int PageErase(XIsf *InstancePtr, u32 Address); static int BlockErase(XIsf *InstancePtr, u32 Address); static int SectorErase(XIsf *InstancePtr, u32 Address); static int BulkErase(XIsf *InstancePtr); -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) static int DieErase(XIsf *InstancePtr); #endif /************************** Variable Definitions *****************************/ @@ -301,7 +303,14 @@ static int SectorErase(XIsf *InstancePtr, u32 Address) u8 FlashStatus[2] = {0}; u8 ReadStatusCmdBuf[] = { READ_STATUS_CMD, 0 }; u8 ReadFlagSRCmd[] = {READ_FLAG_STATUS_CMD, 0}; -#ifdef XPAR_XISF_INTERFACE_PSQSPI + u8 *WriteBfrPtr = InstancePtr->WriteBufPtr; + u8 FSRFlag, ReadStatusCmd; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_Msg FlashMsg[2]; +#endif + +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) u32 FlashMake = InstancePtr->ManufacturerID; #endif @@ -357,18 +366,26 @@ static int SectorErase(XIsf *InstancePtr, u32 Address) InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); InstancePtr->WriteBufPtr[BYTE5] = (u8) (RealAddr); +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].ByteCount = 5; +#endif } else { #endif InstancePtr->WriteBufPtr[BYTE1] = XISF_CMD_SECTOR_ERASE; InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr); +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].ByteCount = 4; +#endif + #if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ (!defined(XPAR_XISF_INTERFACE_PSQSPI))) } #endif -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) /* * Enable write before transfer */ @@ -377,6 +394,16 @@ static int SectorErase(XIsf *InstancePtr, u32 Address) return (int)XST_FAILURE; } #endif + +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + InstancePtr->SpiInstPtr->Msg = FlashMsg; + + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 1); +#else if (InstancePtr->FourByteAddrMode == TRUE) { Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE); @@ -384,22 +411,73 @@ static int SectorErase(XIsf *InstancePtr, u32 Address) Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, XISF_CMD_SEND_EXTRA_BYTES); } +#endif if (Status != (int)XST_SUCCESS) { return (int)XST_FAILURE; } -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) + if((InstancePtr->NumDie > (u8)1) && (FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) { - + ReadStatusCmd = READ_FLAG_STATUS_CMD; + FSRFlag = 1; +#ifndef XPAR_XISF_INTERFACE_QSPIPSU Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus, (u32)sizeof(ReadFlagSRCmd)); +#endif + } else { + ReadStatusCmd = READ_STATUS_CMD; + FSRFlag = 0; } /* * Wait for the sector erase command to the Flash to be completed */ while (1) { +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].TxBfrPtr = &ReadStatusCmd; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsg[1].TxBfrPtr = NULL; + FlashMsg[1].RxBfrPtr = FlashStatus; + FlashMsg[1].ByteCount = 2; + FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX; + + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE; + } + InstancePtr->SpiInstPtr->Msg = FlashMsg; + + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + if(FSRFlag) { + FlashStatus[1] &= FlashStatus[0]; + } else { + FlashStatus[1] |= FlashStatus[0]; + } + } + + if(FSRFlag) { + if ((FlashStatus[1] & 0x80) != 0) { + break; + } + } else { + if ((FlashStatus[1] & 0x01) == 0) { + break; + } + } +#else /* * Poll the status register of the device to determine * when it completes, by sending a read status command @@ -419,8 +497,10 @@ static int SectorErase(XIsf *InstancePtr, u32 Address) if ((FlashStatus[1] & 0x01) == 0) { break; } +#endif } +#ifdef XPAR_XISF_INTERFACE_PSQSPI if((InstancePtr->NumDie > (u8)1) && (FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) { @@ -428,6 +508,7 @@ static int SectorErase(XIsf *InstancePtr, u32 Address) XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus, (u32)sizeof(ReadFlagSRCmd)); } +#endif #endif return Status; @@ -452,12 +533,16 @@ static int BulkErase(XIsf *InstancePtr) { int Status = (int)(XST_FAILURE); u8* NULLPtr = NULL; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_Msg FlashMsg[2]; +#endif #if ((XPAR_XISF_FLASH_FAMILY == INTEL) || (XPAR_XISF_FLASH_FAMILY == STM) || \ (XPAR_XISF_FLASH_FAMILY == WINBOND) || (XPAR_XISF_FLASH_FAMILY == SST) \ || (XPAR_XISF_FLASH_FAMILY == SPANSION)) -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) /* * If the number of die is greater than 1 call die erase */ @@ -478,13 +563,25 @@ static int BulkErase(XIsf *InstancePtr) } Xil_AssertNonvoid(NULLPtr == NULL); +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + InstancePtr->SpiInstPtr->Msg = FlashMsg; + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 1); +#else /* * Initiate the Transfer. */ Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, XISF_BULK_ERASE_BYTES); -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#endif + +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) } #endif #endif /* ((XPAR_XISF_FLASH_FAMILY==INTEL)||(XPAR_XISF_FLASH_FAMILY==STM)) \ @@ -495,7 +592,8 @@ static int BulkErase(XIsf *InstancePtr) return Status; } -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) /*****************************************************************************/ /** * @@ -514,6 +612,13 @@ static int DieErase(XIsf *InstancePtr) { int Status = (int)(XST_FAILURE); u8* NULLPtr = NULL; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_Msg FlashMsg[2]; + u8 ReadStatusCmd, FSRFlag; + u32 FlashMake = InstancePtr->ManufacturerID; + u8 FlashStatus[2] = {0}; +#endif + #if ((XPAR_XISF_FLASH_FAMILY == WINBOND) || \ (XPAR_XISF_FLASH_FAMILY == SPANSION)) @@ -522,11 +627,13 @@ static int DieErase(XIsf *InstancePtr) u8 FlagStatus[2] = {0}; for(DieCnt = 0; DieCnt < InstancePtr->NumDie; DieCnt++) { +#ifndef XPAR_XISF_INTERFACE_QSPIPSU /* * Select bank - the lower of the 2 banks in each die * This is specific to Micron flash */ Status = SendBankSelect(InstancePtr, DieCnt*2); +#endif /* * Setup the write command with the specified address and data @@ -552,7 +659,24 @@ static int DieErase(XIsf *InstancePtr) } Xil_AssertNonvoid(NULLPtr == NULL); +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = BYTE5; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + InstancePtr->SpiInstPtr->Msg = FlashMsg; + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 1); + if((InstancePtr->NumDie > (u8)1) && + (FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) { + ReadStatusCmd = READ_FLAG_STATUS_CMD; + FSRFlag = 1; + } else { + ReadStatusCmd = READ_STATUS_CMD; + FSRFlag = 0; + } +#else /* * Send the sector erase command and address; no receive buffer * is specified since there is nothing to receive @@ -560,11 +684,54 @@ static int DieErase(XIsf *InstancePtr) Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, DIE_ERASE_SIZE); +#endif /* * Wait for the sector erase command to Flash to be completed */ while (1) { +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].TxBfrPtr = &ReadStatusCmd; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsg[1].TxBfrPtr = NULL; + FlashMsg[1].RxBfrPtr = FlashStatus; + FlashMsg[1].ByteCount = 2; + FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX; + InstancePtr->SpiInstPtr->Msg = FlashMsg; + + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE; + } + + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + if(FSRFlag) { + FlashStatus[1] &= FlashStatus[0]; + } else { + FlashStatus[1] |= FlashStatus[0]; + } + } + + if(FSRFlag) { + if ((FlashStatus[1] & 0x80) != 0) { + break; + } + } else { + if ((FlashStatus[1] & 0x01) == 0) { + break; + } + } +#else /* * Poll the status register of the device to determine @@ -585,6 +752,7 @@ static int DieErase(XIsf *InstancePtr) if ((FlagStatus[1] & (u8)0x80) == (u8)0x80) { break; } +#endif } } diff --git a/lib/sw_services/xilisf/src/xilisf_read.c b/lib/sw_services/xilisf/src/xilisf_read.c index a40a7eaf..6c311b4a 100644 --- a/lib/sw_services/xilisf/src/xilisf_read.c +++ b/lib/sw_services/xilisf/src/xilisf_read.c @@ -57,6 +57,7 @@ * which supports 4 byte addressing. * 5.3 sk 06/01/15 Used Half of Actual byte count for calculating * Real Byte count in parallel mode. CR# 859979. +* 5.4 sk 08/07/17 Added QSPIPSU flash interface support for ZynqMP. * * ******************************************************************************/ @@ -371,6 +372,14 @@ static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, u32 ByteCount) u32 LocalAddress = Address; u32 TempByteCnt = LocalByteCnt; u8 WriteBuffer[10] = {0}; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + u32 DieSize, BusWidth, DieTempData; + u8 DiscardByteCnt; + int DieNo; + u8 * NULLPtr = NULL; + XQspiPsu_Msg FlashMsg[3]; +#endif + if (LocalByteCnt <= 0 ) { return (int)XST_FAILURE; } @@ -387,6 +396,23 @@ static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, u32 ByteCount) */ RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, LocalAddress); +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + + DieNo = RealAddr/DieSize; + + DieTempData = (DieSize * (DieNo+1)) - (RealAddr); + + if (InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL) { + DieTempData = DieTempData*2; + } + + /* For Dual Stacked, split and read for boundary crossing */ + if(LocalByteCnt > DieTempData) { + RealByteCnt = DieTempData; + } else { +#endif + #ifdef XPAR_XISF_INTERFACE_PSQSPI if(InstancePtr->DeviceIDMemSize > 0x18U) { @@ -412,7 +438,7 @@ static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, u32 ByteCount) } if(InstancePtr->SpiInstPtr->Config.ConnectionMode == - XQSPIPS_CONNECTION_MODE_PARALLEL) { + XISF_QSPIPS_CONNECTION_MODE_PARALLEL) { TempByteCnt = LocalByteCnt/2; } @@ -428,7 +454,8 @@ static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, u32 ByteCount) #endif RealByteCnt = LocalByteCnt; -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) } #endif #if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ @@ -439,16 +466,43 @@ static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, u32 ByteCount) WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); WriteBuffer[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); WriteBuffer[BYTE5] = (u8) (RealAddr); +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + DiscardByteCnt = 5; +#endif } else { #endif WriteBuffer[BYTE1] = XISF_CMD_RANDOM_READ; WriteBuffer[BYTE2] = (u8)((RealAddr & 0xFF0000) >> XISF_ADDR_SHIFT16); WriteBuffer[BYTE3] = (u8)((RealAddr & 0xFF00) >> XISF_ADDR_SHIFT8); WriteBuffer[BYTE4] = (u8)(RealAddr & 0xFF); +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + DiscardByteCnt = 4; +#endif #if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ (!defined(XPAR_XISF_INTERFACE_PSQSPI))) } #endif + +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].TxBfrPtr = WriteBuffer; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = DiscardByteCnt; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[1].TxBfrPtr = NULL; + FlashMsg[1].RxBfrPtr = ReadPtr; + FlashMsg[1].ByteCount = RealByteCnt; + FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX; + + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE; + } + InstancePtr->SpiInstPtr->Msg = FlashMsg; + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2); +#else if (InstancePtr->FourByteAddrMode == TRUE) { Status = XIsf_Transfer(InstancePtr, WriteBuffer, &(ReadPtr[TotalByteCnt - LocalByteCnt]), @@ -458,10 +512,16 @@ static int ReadData(XIsf *InstancePtr, u32 Address, u8 *ReadPtr, u32 ByteCount) &(ReadPtr[TotalByteCnt - LocalByteCnt]), RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES); } +#endif if (Status != (int)(XST_SUCCESS)) { return (int)XST_FAILURE; } +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + LocalAddress += RealByteCnt; + ReadPtr += RealByteCnt; +#endif + #ifdef XPAR_XISF_INTERFACE_PSQSPI /* * To discard the first 4 dummy bytes, shift the data in read buffer @@ -538,6 +598,14 @@ static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address, u32 LocalAddress = Address; u32 TempByteCnt = LocalByteCnt; u8 WriteBuffer[5]= {0}; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + u32 DieSize, BusWidth, DieTempData; + u32 FlashMsgCnt; + u8 DiscardByteCnt; + int DieNo; + u8 * NULLPtr = NULL; + XQspiPsu_Msg FlashMsg[3]; +#endif if (LocalByteCnt <= 0 ) { return (int)XST_FAILURE; @@ -559,6 +627,23 @@ static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address, */ RealAddr = GetRealAddr(InstancePtr->SpiInstPtr, LocalAddress); +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + + DieNo = RealAddr/DieSize; + + DieTempData = (DieSize * (DieNo+1)) - (RealAddr); + + if (InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL) { + DieTempData = DieTempData*2; + } + + /* For Dual Stacked, split and read for boundary crossing */ + if(LocalByteCnt > DieTempData) { + RealByteCnt = DieTempData; + } else { +#endif + #ifdef XPAR_XISF_INTERFACE_PSQSPI if(InstancePtr->DeviceIDMemSize > 0x18U) { /* @@ -583,7 +668,7 @@ static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address, } if(InstancePtr->SpiInstPtr->Config.ConnectionMode == - XQSPIPS_CONNECTION_MODE_PARALLEL) { + XISF_QSPIPS_CONNECTION_MODE_PARALLEL) { TempByteCnt = LocalByteCnt/2; } /* @@ -598,7 +683,8 @@ static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address, #endif RealByteCnt = LocalByteCnt; -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) } #endif #if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ @@ -609,24 +695,89 @@ static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address, WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); WriteBuffer[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); WriteBuffer[BYTE5] = (u8) RealAddr; - +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + DiscardByteCnt = 5; +#else for (Index = 0; Index < NumDummyBytes; Index++) { WriteBuffer[Index + BYTE5 + 1] = (u8) (XISF_DUMMYBYTE); } +#endif } else { #endif WriteBuffer[BYTE1] = Command; WriteBuffer[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); WriteBuffer[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); WriteBuffer[BYTE4] = (u8) RealAddr; - +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + DiscardByteCnt = 4; +#else for (Index = 0; Index < NumDummyBytes; Index++) { WriteBuffer[Index + BYTE5] = (u8) (XISF_DUMMYBYTE); } +#endif #if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ (!defined(XPAR_XISF_INTERFACE_PSQSPI))) } #endif + +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].TxBfrPtr = WriteBuffer; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = DiscardByteCnt; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsgCnt = 1; + BusWidth = XQSPIPSU_SELECT_MODE_SPI; + /* It is recommended to have a separate entry for dummy */ + if ((Command == XISF_CMD_FAST_READ) || + (Command == XISF_CMD_DUAL_OP_FAST_READ) || + (Command == XISF_CMD_QUAD_OP_FAST_READ) || + (Command == XISF_CMD_FAST_READ_4BYTE) || + (Command == XISF_CMD_DUAL_OP_FAST_READ_4B) || + (Command == XISF_CMD_QUAD_OP_FAST_READ_4B)) { + /* Update Dummy cycles as per flash specs for QUAD IO */ + + /* + * It is recommended that Bus width value during dummy + * phase should be same as data phase + */ + if ((Command == XISF_CMD_FAST_READ) || + (Command == XISF_CMD_FAST_READ_4BYTE)) { + BusWidth = XQSPIPSU_SELECT_MODE_SPI; + } + + if ((Command == XISF_CMD_DUAL_OP_FAST_READ) || + (Command == XISF_CMD_DUAL_OP_FAST_READ_4B)) { + BusWidth = XQSPIPSU_SELECT_MODE_DUALSPI; + } + + if ((Command == XISF_CMD_QUAD_OP_FAST_READ) || + (Command == XISF_CMD_QUAD_OP_FAST_READ_4B)) { + BusWidth = XQSPIPSU_SELECT_MODE_QUADSPI; + } + + FlashMsg[1].BusWidth = BusWidth; + FlashMsg[1].TxBfrPtr = NULL; + FlashMsg[1].RxBfrPtr = NULL; + FlashMsg[1].ByteCount = 8; + FlashMsg[1].Flags = 0; + + FlashMsgCnt++; + } + FlashMsg[FlashMsgCnt].BusWidth = BusWidth; + FlashMsg[FlashMsgCnt].TxBfrPtr = NULL; + FlashMsg[FlashMsgCnt].RxBfrPtr = ReadPtr; + FlashMsg[FlashMsgCnt].ByteCount = RealByteCnt; + FlashMsg[FlashMsgCnt].Flags = XQSPIPSU_MSG_FLAG_RX; + + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + FlashMsg[FlashMsgCnt].Flags |= XQSPIPSU_MSG_FLAG_STRIPE; + } + InstancePtr->SpiInstPtr->Msg = FlashMsg; + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, FlashMsgCnt+1); +#else RealByteCnt += NumDummyBytes; if (InstancePtr->FourByteAddrMode == TRUE) { Status = (int)XIsf_Transfer(InstancePtr, WriteBuffer, @@ -637,10 +788,17 @@ static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address, &(ReadPtr[TotalByteCnt - LocalByteCnt]), RealByteCnt + XISF_CMD_SEND_EXTRA_BYTES); } +#endif if (Status != (int)(XST_SUCCESS)) { return (int)(XST_FAILURE); } +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + LocalAddress += RealByteCnt; + LocalByteCnt -= RealByteCnt; + ReadPtr += RealByteCnt; +#endif + #ifdef XPAR_XISF_INTERFACE_PSQSPI /* * To discard the first 5 dummy bytes, shift the data in read buffer @@ -658,10 +816,13 @@ static int FastReadData(XIsf *InstancePtr, u8 Command, u32 Address, */ LocalAddress = (LocalAddress & BANKMASK) + SIXTEENMB; #endif + +#ifndef XPAR_XISF_INTERFACE_QSPIPSU /* * Decrease byte count by bytes already read. */ LocalByteCnt = LocalByteCnt - (RealByteCnt - NumDummyBytes); +#endif } return (int)XST_SUCCESS; diff --git a/lib/sw_services/xilisf/src/xilisf_write.c b/lib/sw_services/xilisf/src/xilisf_write.c index 74105155..49f4b2cf 100644 --- a/lib/sw_services/xilisf/src/xilisf_write.c +++ b/lib/sw_services/xilisf/src/xilisf_write.c @@ -56,6 +56,7 @@ * XIsf_Write() * 5.2 asa 05/12/15 Added support for Micron (N25Q256A) flash part * which supports 4 byte addressing. +* 5.4 sk 08/07/17 Added QSPIPSU flash interface support for ZynqMP. * * ******************************************************************************/ @@ -81,7 +82,7 @@ extern u32 GetRealAddr(XIsf_Iface *QspiPtr, u32 Address); extern int SendBankSelect(XIsf *InstancePtr, u32 BankSel); #endif static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address, - const u8 *BufferPtr, u32 ByteCount); + u8 *BufferPtr, u32 ByteCount); static int AutoPageWrite(XIsf *InstancePtr, u32 Address); static int BufferWrite(XIsf *InstancePtr, u8 BufferNum, const u8 *WritePtr, u32 ByteOffset, u32 NumBytes); @@ -383,7 +384,7 @@ int XIsf_Write(XIsf *InstancePtr, XIsf_WriteOperation Operation, * ******************************************************************************/ static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address, - const u8 *BufferPtr, u32 ByteCount) + u8 *BufferPtr, u32 ByteCount) { u8 Mode; u32 Index; @@ -393,8 +394,14 @@ static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address, u8 FlagStatus[2] = {0}; u8 FlashStatus[2] = {0}; u8 * NULLPtr = NULL; - const u8 * LocalBufPtr = BufferPtr; -#ifdef XPAR_XISF_INTERFACE_PSQSPI + u8 * LocalBufPtr = BufferPtr; +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + XQspiPsu_Msg FlashMsg[2]; + u8 ReadStatusCmd, FSRFlag; + u32 CmdByteCount; +#endif +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) u32 FlashMake = InstancePtr->ManufacturerID; #endif u8 ReadStatusCmdBuf[] = { READ_STATUS_CMD, 0 }; @@ -455,33 +462,65 @@ static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address, InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); InstancePtr->WriteBufPtr[BYTE5] = (u8) (RealAddr); +#ifndef XPAR_XISF_INTERFACE_QSPIPSU for(Index = 5U; Index < (ByteCount + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE); Index++) { InstancePtr->WriteBufPtr[Index] = *LocalBufPtr; LocalBufPtr += 1; } +#else + CmdByteCount = 5; +#endif } else { #endif InstancePtr->WriteBufPtr[BYTE1] = Command; InstancePtr->WriteBufPtr[BYTE2] = (u8) (RealAddr >> XISF_ADDR_SHIFT16); InstancePtr->WriteBufPtr[BYTE3] = (u8) (RealAddr >> XISF_ADDR_SHIFT8); InstancePtr->WriteBufPtr[BYTE4] = (u8) (RealAddr); +#ifndef XPAR_XISF_INTERFACE_QSPIPSU for(Index = 4U; Index < (ByteCount + XISF_CMD_SEND_EXTRA_BYTES); Index++) { InstancePtr->WriteBufPtr[Index] = *LocalBufPtr; LocalBufPtr += 1; } +#else + CmdByteCount = 4; +#endif + #if ((XPAR_XISF_FLASH_FAMILY == SPANSION) && \ (!defined(XPAR_XISF_INTERFACE_PSQSPI))) } #endif -#ifdef XPAR_XISF_INTERFACE_PSQSPI +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) /* * Enable write before transfer */ Status = XIsf_WriteEnable(InstancePtr, XISF_WRITE_ENABLE); #endif + +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].TxBfrPtr = InstancePtr->WriteBufPtr; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = CmdByteCount; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsg[1].TxBfrPtr = LocalBufPtr; + FlashMsg[1].RxBfrPtr = NULL; + FlashMsg[1].ByteCount = ByteCount; + FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_TX; + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE; + } + + InstancePtr->SpiInstPtr->Msg = FlashMsg; + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2); + +#else if (InstancePtr->FourByteAddrMode == TRUE) { Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, (ByteCount + XISF_CMD_SEND_EXTRA_BYTES_4BYTE_MODE)); @@ -489,18 +528,29 @@ static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address, Status = XIsf_Transfer(InstancePtr, InstancePtr->WriteBufPtr, NULLPtr, (ByteCount + XISF_CMD_SEND_EXTRA_BYTES)); } +#endif + if (Status != (int)XST_SUCCESS) { return (int)XST_FAILURE; } -#ifdef XPAR_XISF_INTERFACE_PSQSPI - if((InstancePtr->NumDie > 1) && - (FlashMake == XISF_MANUFACTURER_ID_MICRON)) { +#if defined (XPAR_XISF_INTERFACE_PSQSPI) || \ + defined (XPAR_XISF_INTERFACE_QSPIPSU) + + if((InstancePtr->NumDie > (u8)1) && + (FlashMake == (u32)XISF_MANUFACTURER_ID_MICRON)) { +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + ReadStatusCmd = READ_FLAG_STATUS_CMD; + FSRFlag = 1; +#else Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus, (u32)sizeof(ReadFlagSRCmd)); - if(Status != (int)XST_SUCCESS){ - return (int)XST_FAILURE; - } +#endif + } else { +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + ReadStatusCmd = READ_STATUS_CMD; + FSRFlag = 0; +#endif } /* @@ -508,6 +558,48 @@ static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address, * some time for the data to be written */ while (1) { +#ifdef XPAR_XISF_INTERFACE_QSPIPSU + FlashMsg[0].TxBfrPtr = &ReadStatusCmd; + FlashMsg[0].RxBfrPtr = NULL; + FlashMsg[0].ByteCount = 1; + FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX; + + FlashMsg[1].TxBfrPtr = NULL; + FlashMsg[1].RxBfrPtr = FlashStatus; + FlashMsg[1].ByteCount = 2; + FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI; + FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX; + + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE; + } + InstancePtr->SpiInstPtr->Msg = FlashMsg; + + Status = XIsf_Transfer(InstancePtr, NULLPtr, NULLPtr, 2); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + if(InstancePtr->SpiInstPtr->Config.ConnectionMode == + XISF_QSPIPS_CONNECTION_MODE_PARALLEL){ + if(FSRFlag) { + FlashStatus[1] &= FlashStatus[0]; + } else { + FlashStatus[1] |= FlashStatus[0]; + } + } + + if(FSRFlag) { + if ((FlashStatus[1] & 0x80) != 0) { + break; + } + } else { + if ((FlashStatus[1] & 0x01) == 0) { + break; + } + } +#else /* * Poll the status register of the Flash to determine when it * completes, by sending a read status command and receiving @@ -529,8 +621,10 @@ static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address, if ((FlashStatus[1] & 0x01) == 0) { break; } +#endif } +#ifdef XPAR_XISF_INTERFACE_PSQSPI if((InstancePtr->NumDie > 1) && (FlashMake == XISF_MANUFACTURER_ID_MICRON)) { Status = XIsf_Transfer(InstancePtr, ReadFlagSRCmd, FlagStatus, @@ -539,6 +633,7 @@ static int WriteData(XIsf *InstancePtr, u8 Command, u32 Address, return (int)XST_FAILURE; } } +#endif #endif return Status;