XILINX製Zynq™ UltraScale+™ MPSoCのブートプログラムFSBL(First-Stage Boot Loader)をInfineon(旧Cypress)製QSPIフラッシュS25Hxに対応させました。
FSBLはOSSとして公開されています。
https://github.com/Xilinx/embeddedsw/tree/master/lib/sw_apps/zynqmp_fsbl
XILINXがサポートしているフラッシュデバイスは
https://support.xilinx.com/s/article/65463?language=ja
の通りです。
S25Hxは含まれてないので、FSBLも本品に対応していません。なので、ブートデバイスにS25Hxを採用した場合、FSBLはS25Hxを認識しないので、Second Stage Boot LoaderのU-Bootをフラッシュから読み出せません。
そこで、次のように改造してS25Hxに対応させました。FSBLのリビジョンは2020.3です。
https://github.com/Xilinx/embeddedsw/tree/release-2020.3/lib/sw_apps/zynqmp_fsbl
diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.c
index 0b6aac4624..4557a6a344 100644
--- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.c
+++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.c
@@ -1,5 +1,5 @@
/******************************************************************************
-* Copyright (c) 2015 - 2020 Xilinx, Inc. All rights reserved.
+* Copyright (c) 2015 - 2022 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
@@ -25,6 +25,12 @@
* sk 03/13/19 Added dual parallel support and QPI support for 24bit
* boot mode for Macronix flash parts.
* 5.0 bsv 11/15/20 Added Macronix 2G flash support
+* 6.0 bsv 07/29/21 Added Winbond 2G flash support
+* bsv 09/08/21 Added MultiDie read support for Micron 2G flash part
+* 7.0 bsv 04/28/22 Fixed bug in Qspi copy when destination address is not
+* 64 byte aligned
+* bsv 05/03/22 Replace memcpy with Xil_MemCpy to avoid non-word aligned
+* access to memory
*
* </pre>
*
@@ -47,6 +53,8 @@
* change all the needed parameters in one place.
*/
#define QSPI_DEVICE_ID XPAR_XQSPIPSU_0_DEVICE_ID
+#define XFSBL_SIXTY_FOUR_BYTE_MASK (0x3FU)
+#define XFSBL_SIXTY_FOUR_BYTE_VAL (64U)
/**************************** Type Definitions *******************************/
@@ -56,9 +64,11 @@
static u32 FlashReadID(XQspiPsu *QspiPsuPtr);
static u32 MacronixEnable4B(XQspiPsu *QspiPsuPtr);
static u32 MacronixEnableQPIMode(XQspiPsu *QspiPsuPtr, int Enable);
+static u32 CypressEnable4B(XQspiPsu *QspiPsuPtr);
+static u32 CypressEnableQuadMode(XQspiPsu *QspiPsuPtr, u32 QspiBaseAddr);
/************************** Variable Definitions *****************************/
-static XQspiPsu QspiPsuInstance;
+static XQspiPsu QspiPsuInstance __attribute__ ((aligned(64)));
static u32 QspiFlashSize=0U;
static u32 QspiFlashMake=0U;
static u32 ReadCommand=0U;
@@ -69,6 +79,9 @@ static u8 TxBfrPtr __attribute__ ((aligned(32)));
static u8 ReadBuffer[10] __attribute__ ((aligned(32)));
static u8 WriteBuffer[10] __attribute__ ((aligned(32)));
static u32 MacronixFlash = 0U;
+static u32 CypressFlash = 0U;
+u8 MultiDie = (u8)FALSE;
+
/******************************************************************************
*
* This function reads serial FLASH ID connected to the SPI interface.
@@ -118,6 +131,8 @@ static u32 FlashReadID(XQspiPsu *QspiPsuPtr)
* Deduce flash make
*/
MacronixFlash = 0U;
+ CypressFlash = 0U;
+
if (ReadBuffer[0] == MICRON_ID) {
QspiFlashMake = MICRON_ID;
XFsbl_Printf(DEBUG_INFO, "MICRON ");
@@ -134,6 +149,10 @@ static u32 FlashReadID(XQspiPsu *QspiPsuPtr)
} else if(ReadBuffer[0] == ISSI_ID) {
QspiFlashMake = ISSI_ID;
XFsbl_Printf(DEBUG_INFO, "ISSI ");
+ } else if(ReadBuffer[0] == CYPRESS_ID) {
+ QspiFlashMake = CYPRESS_ID;
+ XFsbl_Printf(DEBUG_INFO, "CYPRESS ");
+ CypressFlash = 1U;
} else {
UStatus = XFSBL_ERROR_UNSUPPORTED_QSPI;
XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_UNSUPPORTED_QSPI\r\n");
@@ -175,8 +194,13 @@ static u32 FlashReadID(XQspiPsu *QspiPsuPtr)
} else if ((ReadBuffer[2] == FLASH_SIZE_ID_2G)
|| (ReadBuffer[2] == MACRONIX_FLASH_SIZE_ID_2G)
|| (ReadBuffer[2] == MACRONIX_FLASH_1_8_V_SIZE_ID_2G)) {
- QspiFlashSize = FLASH_SIZE_2G;
- XFsbl_Printf(DEBUG_INFO, "2G Bits\r\n");
+ QspiFlashSize = FLASH_SIZE_2G;
+ if ((QspiFlashMake == WINBOND_ID) ||
+ (QspiFlashMake == MICRON_ID) ||
+ (QspiFlashMake == CYPRESS_ID)) {
+ MultiDie = (u8)TRUE;
+ }
+ XFsbl_Printf(DEBUG_INFO, "2G Bits\r\n");
}else {
UStatus = XFSBL_ERROR_UNSUPPORTED_QSPI;
XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_UNSUPPORTED_QSPI\r\n");
@@ -361,7 +385,7 @@ END:
*
*
******************************************************************************/
-static u32 XFsbl_GetQspiAddr(u32 Address )
+static u32 XFsbl_GetQspiAddr(u32 Address)
{
u32 RealAddr;
@@ -602,6 +626,9 @@ u32 XFsbl_Qspi24Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
u32 BankSize;
u32 BankMask;
s32 SStatus;
+ u8 TempBuf[XFSBL_SIXTY_FOUR_BYTE_VAL] __attribute__ ((aligned(64)));
+ u32 UnalignedBytes = (u32)(DestAddress & XFSBL_SIXTY_FOUR_BYTE_MASK);
+ PTRSIZE DestAddr;
XFsbl_Printf(DEBUG_INFO,"QSPI Reading Src 0x%0lx, Dest %0lx, Length %0lx\r\n",
SrcAddress, DestAddress, Length);
@@ -642,6 +669,21 @@ u32 XFsbl_Qspi24Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
TransferBytes = RemainingBytes;
}
+ /* Check for 64 byte alignment of DMA destination */
+ if (UnalignedBytes != 0U) {
+ UnalignedBytes = (u32)XFSBL_SIXTY_FOUR_BYTE_VAL -
+ UnalignedBytes;
+ if (UnalignedBytes > TransferBytes) {
+ UnalignedBytes = TransferBytes;
+ }
+ else {
+ TransferBytes = UnalignedBytes;
+ }
+ DestAddr = (PTRSIZE)TempBuf;
+ }
+ else {
+ DestAddr = DestAddress;
+ }
/**
* Translate address based on type of connection
* If stacked assert the slave select based on address
@@ -736,7 +778,7 @@ u32 XFsbl_Qspi24Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
/*Data*/
FlashMsg[3].TxBfrPtr = NULL;
- FlashMsg[3].RxBfrPtr = (u8 *)DestAddress;
+ FlashMsg[3].RxBfrPtr = (u8 *)DestAddr;
FlashMsg[3].ByteCount = TransferBytes;
FlashMsg[3].BusWidth = XQSPIPSU_SELECT_MODE_QUADSPI;
FlashMsg[3].Flags = XQSPIPSU_MSG_FLAG_RX;
@@ -812,7 +854,7 @@ u32 XFsbl_Qspi24Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
}
FlashMsg[2].TxBfrPtr = NULL;
- FlashMsg[2].RxBfrPtr = (u8 *)DestAddress;
+ FlashMsg[2].RxBfrPtr = (u8 *)DestAddr;
FlashMsg[2].ByteCount = TransferBytes;
FlashMsg[2].Flags = XQSPIPSU_MSG_FLAG_RX;
@@ -834,6 +876,10 @@ u32 XFsbl_Qspi24Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
}
}
+ if (UnalignedBytes != 0U) {
+ Xil_MemCpy((void *)DestAddress, TempBuf, UnalignedBytes);
+ UnalignedBytes = 0U;
+ }
/**
* Update the variables
*/
@@ -895,6 +941,8 @@ u32 XFsbl_Qspi32Init(u32 DeviceFlags)
s32 Status;
u32 QspiMode;
u32 UStatus;
+ u32 Addr;
+ u32 Size;
@@ -943,7 +991,6 @@ u32 XFsbl_Qspi32Init(u32 DeviceFlags)
* Configure the qspi in linear mode if running in XIP
* TBD
*/
-
switch ((u32)XPAR_PSU_QSPI_0_QSPI_MODE) {
case XQSPIPSU_CONNECTION_MODE_SINGLE:
@@ -1007,6 +1054,9 @@ u32 XFsbl_Qspi32Init(u32 DeviceFlags)
goto END;
}
+ /*
+ * for Macronix
+ */
if (MacronixFlash == 1U) {
if (QspiPsuInstance.Config.BusWidth == XFSBL_QSPI_BUSWIDTH_FOUR) {
ReadCommand = QUAD_READ_CMD_24BIT2;
@@ -1036,10 +1086,11 @@ u32 XFsbl_Qspi32Init(u32 DeviceFlags)
}
}
}
+
/**
* add code: For a Stacked connection, read second Flash ID
*/
- QspiMode = QspiPsuInstance.Config.ConnectionMode;
+ QspiMode = QspiPsuInstance.Config.ConnectionMode;
if ((QspiMode ==
(s32)(XQSPIPSU_CONNECTION_MODE_PARALLEL)) ||
(QspiMode ==
@@ -1047,6 +1098,68 @@ u32 XFsbl_Qspi32Init(u32 DeviceFlags)
QspiFlashSize = 2 * QspiFlashSize;
}
+ /*
+ * for Cypress
+ */
+ if (CypressFlash == 1U) {
+ if (QspiPsuInstance.Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ XQspiPsu_SelectFlash(&QspiPsuInstance,
+ XQSPIPSU_SELECT_FLASH_CS_BOTH,
+ XQSPIPSU_SELECT_FLASH_BUS_BOTH);
+ for (Addr = 0; Addr < QspiFlashSize; Addr += FLASH_SIZE_1G /* 128 MByte */) {
+ Status = CypressEnable4B(&QspiPsuInstance);
+ if (Status != XFSBL_SUCCESS) {
+ UStatus = XFSBL_FAILURE;
+ goto END;
+ }
+ Status = CypressEnableQuadMode(&QspiPsuInstance, Addr);
+ if (Status != XFSBL_SUCCESS) {
+ UStatus = XFSBL_FAILURE;
+ goto END;
+ }
+ }
+ } else {
+ XQspiPsu_SelectFlash(&QspiPsuInstance,
+ XQSPIPSU_SELECT_FLASH_CS_LOWER,
+ XQSPIPSU_SELECT_FLASH_BUS_LOWER);
+ if (QspiPsuInstance.Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_SINGLE)
+ Size = QspiFlashSize;
+ else if (QspiPsuInstance.Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_STACKED)
+ Size = QspiFlashSize / 2;
+ for (Addr = 0; Addr < Size; Addr += FLASH_SIZE_1G) {
+ Status = CypressEnable4B(&QspiPsuInstance);
+ if (Status != XFSBL_SUCCESS) {
+ UStatus = XFSBL_FAILURE;
+ goto END;
+ }
+ Status = CypressEnableQuadMode(&QspiPsuInstance, Addr);
+ if (Status != XFSBL_SUCCESS) {
+ UStatus = XFSBL_FAILURE;
+ goto END;
+ }
+ }
+ if (QspiPsuInstance.Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_STACKED) {
+ XQspiPsu_SelectFlash(&QspiPsuInstance,
+ XQSPIPSU_SELECT_FLASH_CS_UPPER,
+ XQSPIPSU_SELECT_FLASH_BUS_LOWER);
+ for (Addr = Size; Addr < QspiFlashSize; Addr += FLASH_SIZE_1G) {
+ Status = CypressEnable4B(&QspiPsuInstance);
+ if (Status != XFSBL_SUCCESS) {
+ UStatus = XFSBL_FAILURE;
+ goto END;
+ }
+ Status = CypressEnableQuadMode(&QspiPsuInstance, Addr);
+ if (Status != XFSBL_SUCCESS) {
+ UStatus = XFSBL_FAILURE;
+ goto END;
+ }
+ }
+ }
+ }
+ }
+
END:
return UStatus;
}
@@ -1167,6 +1280,168 @@ END:
return UStatus;
}
+/******************************************************************************
+*
+* Static API used for Cypress flash to enable 4BYTE mode
+*
+* @param QspiPsuPtr Pointer to QSPI instance.
+*
+* @return XFSBL_SUCCESS if success, otherwise XFSBL_FAILURE.
+*
+* @note None.
+*
+******************************************************************************/
+static u32 CypressEnable4B(XQspiPsu *QspiPsuPtr)
+{
+ s32 Status;
+ u32 UStatus;
+
+ XFsbl_Printf(DEBUG_GENERAL,"CYPRESS_FLASH_MODE\r\n");
+
+ /*Enable 4 byte mode*/
+ TxBfrPtr = 0xB7;
+ FlashMsg[0].TxBfrPtr = &TxBfrPtr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ Status = XQspiPsu_PolledTransfer(QspiPsuPtr, &FlashMsg[0], 1);
+ if (Status != XFSBL_SUCCESS) {
+ UStatus = XFSBL_FAILURE;
+ goto END;
+ }
+ XFsbl_Printf(DEBUG_GENERAL,"CYPESS_ENABLE_4BYTE_DONE\r\n");
+
+ UStatus = XFSBL_SUCCESS;
+
+END:
+ return UStatus;
+}
+
+/******************************************************************************
+*
+* Static API used for Cypress flash to enable Quad mode
+*
+* @param QspiPsuPtr Pointer to QSPI instance.
+*
+* @return XFSBL_SUCCESS if success, otherwise XFSBL_ERROR_QSPI_READ.
+*
+* @note None.
+*
+******************************************************************************/
+#define CYPRESS_READ_AR_CMD 0x65 /* Read any register */
+#define CYPRESS_WRITE_AR_CMD 0x71 /* Write any register */
+#define CYPRESS_REG_ADDR_CFR1V 0x00800002
+#define CYPRESS_QUAD_EN 0x02 /* Quad I/O */
+
+static u32 CypressEnableQuadMode(XQspiPsu *QspiPsuPtr, u32 QspiBaseAddr)
+{
+ s32 Status;
+ u32 UStatus;
+ u32 QspiAddr;
+
+ memset(ReadBuffer, 0, sizeof(ReadBuffer));
+ memset(WriteBuffer, 0, sizeof(WriteBuffer));
+
+ /* Check current Quad Enable bit value. */
+ QspiAddr = QspiBaseAddr + CYPRESS_REG_ADDR_CFR1V;
+ WriteBuffer[COMMAND_OFFSET] = CYPRESS_READ_AR_CMD;
+ WriteBuffer[ADDRESS_1_OFFSET] = (u8)((QspiAddr & 0xFF000000U) >> 24);
+ WriteBuffer[ADDRESS_2_OFFSET] = (u8)((QspiAddr & 0xFF0000U) >> 16);
+ WriteBuffer[ADDRESS_3_OFFSET] = (u8)((QspiAddr & 0xFF00U) >> 8);
+ WriteBuffer[ADDRESS_4_OFFSET] = (u8)(QspiAddr & 0xFFU);
+ FlashMsg[0].TxBfrPtr = WriteBuffer;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 5;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = ReadBuffer;
+ FlashMsg[1].ByteCount = 1;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+ if (QspiPsuInstance.Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_PARALLEL)
+ FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+
+ Status = XQspiPsu_PolledTransfer(QspiPsuPtr, &FlashMsg[0], 2);
+ if (Status != XFSBL_SUCCESS) {
+ UStatus = XFSBL_FAILURE;
+ goto END;
+ }
+
+ if (ReadBuffer[0] & CYPRESS_QUAD_EN) {
+ UStatus = XFSBL_SUCCESS;
+ XFsbl_Printf(DEBUG_GENERAL, "CYPESS_QUAD_BIT_ALREADY_SET at 0x%08x\n\r", QspiBaseAddr);
+ goto END;
+ }
+
+ /* Enable register write */
+ TxBfrPtr = WRITE_ENABLE_CMD;
+ FlashMsg[0].TxBfrPtr = &TxBfrPtr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ Status = XQspiPsu_PolledTransfer(&QspiPsuInstance, &FlashMsg[0], 1);
+ if (Status != XFSBL_SUCCESS) {
+ UStatus = XFSBL_FAILURE;
+ goto END;
+ }
+
+ /* Enable quad mode */
+ WriteBuffer[COMMAND_OFFSET] = CYPRESS_WRITE_AR_CMD;
+ WriteBuffer[5] = ReadBuffer[0] | CYPRESS_QUAD_EN;
+ FlashMsg[0].TxBfrPtr = WriteBuffer;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 6;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ Status = XQspiPsu_PolledTransfer(&QspiPsuInstance, &FlashMsg[0], 1);
+ if (Status != XFSBL_SUCCESS) {
+ UStatus = XFSBL_FAILURE;
+ goto END;
+ }
+
+ /* Read back and check it. */
+ WriteBuffer[COMMAND_OFFSET] = CYPRESS_READ_AR_CMD;
+ FlashMsg[0].TxBfrPtr = WriteBuffer;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 5;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = ReadBuffer;
+ FlashMsg[1].ByteCount = 1;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+ if (QspiPsuInstance.Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_PARALLEL)
+ FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+
+ Status = XQspiPsu_PolledTransfer(QspiPsuPtr, &FlashMsg[0], 2);
+ if (Status != XFSBL_SUCCESS) {
+ UStatus = XFSBL_FAILURE;
+ goto END;
+ }
+
+ if (!(ReadBuffer[0] & CYPRESS_QUAD_EN)) {
+ UStatus = XFSBL_FAILURE;
+ XFsbl_Printf(DEBUG_GENERAL, "CYPESS_QUAD_BIT_NOT_SET at 0x%08x\n\r", QspiBaseAddr);
+ goto END;
+ }
+
+ XFsbl_Printf(DEBUG_GENERAL, "CYPESS_QUAD_BIT_SET at 0x%08x\n\r", QspiBaseAddr);
+
+ UStatus = XFSBL_SUCCESS;
+
+END:
+ return UStatus;
+}
+
/*****************************************************************************/
/**
* This function is used to copy the data from QSPI flash to destination
@@ -1193,6 +1468,12 @@ u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
u32 TransferBytes;
u32 DiscardByteCnt;
u32 UStatus;
+ u32 BankSize;
+ u32 BankMask;
+ u32 OrigAddr;
+ u8 TempBuf[XFSBL_SIXTY_FOUR_BYTE_VAL] __attribute__ ((aligned(64)));
+ u32 UnalignedBytes = (u32)(DestAddress & XFSBL_SIXTY_FOUR_BYTE_MASK);
+ PTRSIZE DestAddr;
XFsbl_Printf(DEBUG_INFO,"QSPI Reading Src 0x%0lx, Dest %0lx, Length %0lx\r\n",
SrcAddress, DestAddress, Length);
@@ -1207,12 +1488,24 @@ u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
goto END;
}
+ if (MultiDie == (u8)TRUE) {
+ BankSize = BANKSIZE_64MB;
+ BankMask = BANKMASK_64MB;
+ }
+ else {
+ BankSize = BANKSIZE;
+ BankMask = BANKMASK;
+ }
+ if (QspiPsuInstance.Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL){
+ BankSize *= 2U;
+ BankMask *= 2U;
+ }
/**
* Update no of bytes to be copied
*/
RemainingBytes = Length;
-
while(RemainingBytes > 0U) {
if (RemainingBytes > DMA_DATA_TRAN_SIZE)
@@ -1222,24 +1515,62 @@ u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
TransferBytes = RemainingBytes;
}
+ /* Check for 64 byte alignment of DMA destination */
+ if (UnalignedBytes != 0U) {
+ UnalignedBytes = (u32)XFSBL_SIXTY_FOUR_BYTE_VAL -
+ UnalignedBytes;
+ if (UnalignedBytes > TransferBytes) {
+ UnalignedBytes = TransferBytes;
+ }
+ else {
+ TransferBytes = UnalignedBytes;
+ }
+ DestAddr = (PTRSIZE)TempBuf;
+ }
+ else {
+ DestAddr = DestAddress;
+ }
+
/**
* Translate address based on type of connection
* If stacked assert the slave select based on address
*/
QspiAddr = XFsbl_GetQspiAddr((u32 )SrcAddress);
+ if (MultiDie == (u8)TRUE) {
+ /**
+ * Multiply address by 2 in case of Dual Parallel
+ * This address is used to calculate the bank crossing
+ * condition
+ */
+ if (QspiPsuInstance.Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL){
+ OrigAddr = QspiAddr * 2U;
+ } else {
+ OrigAddr = QspiAddr;
+ }
+ /**
+ * If data to be read spans beyond the current die, then
+ * calculate Transfer Bytes in current die. Else
+ * transfer bytes are same
+ */
+ if ((OrigAddr & BankMask) != ((OrigAddr + TransferBytes)
+ & BankMask)) {
+ TransferBytes = (OrigAddr & BankMask) + BankSize
+ - OrigAddr;
+ }
+ }
XFsbl_Printf(DEBUG_INFO,".");
XFsbl_Printf(DEBUG_DETAILED,
"QSPI Read Src 0x%0lx, Dest %0lx, Length %0lx\r\n",
- QspiAddr, DestAddress, TransferBytes);
+ QspiAddr, DestAddr, TransferBytes);
/**
* Setup the read command with the specified address and data for the
* Flash
*/
if ((MacronixFlash == 1U) &&
- (QspiPsuInstance.Config.BusWidth == XFSBL_QSPI_BUSWIDTH_FOUR)) {
-
+ (QspiPsuInstance.Config.BusWidth == XFSBL_QSPI_BUSWIDTH_FOUR)) {
/* Enable QPI mode */
Status = MacronixEnableQPIMode(&QspiPsuInstance, ENABLE_QPI);
if (Status != XFSBL_SUCCESS) {
@@ -1280,7 +1611,7 @@ u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
/*Data*/
FlashMsg[3].TxBfrPtr = NULL;
- FlashMsg[3].RxBfrPtr = (u8 *)DestAddress;
+ FlashMsg[3].RxBfrPtr = (u8 *)DestAddr;
FlashMsg[3].ByteCount = TransferBytes;
FlashMsg[3].BusWidth = XQSPIPSU_SELECT_MODE_QUADSPI;
FlashMsg[3].Flags = XQSPIPSU_MSG_FLAG_RX;
@@ -1303,7 +1634,6 @@ u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n");
goto END;
}
-
} else {
WriteBuffer[COMMAND_OFFSET] = (u8)ReadCommand;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((QspiAddr & 0xFF000000U) >> 24);
@@ -1362,7 +1692,7 @@ u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
}
FlashMsg[2].TxBfrPtr = NULL;
- FlashMsg[2].RxBfrPtr = (u8 *)DestAddress;
+ FlashMsg[2].RxBfrPtr = (u8 *)DestAddr;
FlashMsg[2].ByteCount = TransferBytes;
FlashMsg[2].Flags = XQSPIPSU_MSG_FLAG_RX;
@@ -1383,6 +1713,10 @@ u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
goto END;
}
}
+ if (UnalignedBytes != 0U) {
+ Xil_MemCpy((void *)DestAddress, TempBuf, TransferBytes);
+ UnalignedBytes = 0U;
+ }
/**
* Update the variables
*/
@@ -1392,6 +1726,7 @@ u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
}
UStatus = XFSBL_SUCCESS;
+
END:
return UStatus;
}
diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.h
index b37a657690..d1fc889bbc 100644
--- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.h
+++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_qspi.h
@@ -1,5 +1,5 @@
/******************************************************************************
-* Copyright (c) 2015 - 2020 Xilinx, Inc. All rights reserved.
+* Copyright (c) 2015 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
@@ -25,6 +25,8 @@
* sk 03/13/19 Added dual parallel support and QPI support for 24bit
* boot mode for Macronix flash parts.
* 5.0 bsv 11/15/20 Added Macronix 2G flash support
+* 6.0 bsv 07/29/21 Added Winbond 2G flash support
+* bsv 09/08/21 Added MultiDie read support for Micron 2G flash part
*
* </pre>
*
@@ -126,6 +128,8 @@ extern "C" {
#define FLASH_SIZE_16MB (0x1000000U)
#define BANKSIZE (FLASH_SIZE_16MB)
#define SINGLEBANKSIZE BANKSIZE
+#define BANKSIZE_64MB (0x4000000U)
+#define BANKMASK_64MB (~(BANKSIZE_64MB - 1U))
/*
* Bank mask
@@ -152,6 +156,7 @@ extern "C" {
#define WINBOND_ID (0xEFU)
#define MACRONIX_ID (0xC2U)
#define ISSI_ID (0x9DU)
+#define CYPRESS_ID (0x34U)
#define FLASH_SIZE_ID_8M (0x14U)
#define FLASH_SIZE_ID_16M (0x15U)