예제 #1
0
/**
 * This function is used to copy the data from QSPI flash to destination
 * address
 *
 * @param SrcAddress is the address of the QSPI flash where copy should
 * start from
 *
 * @param DestAddress is the address of the destination where it
 * should copy to
 *
 * @param Length Length of the bytes to be copied
 *
 * @return
 * 		- XFSBL_SUCCESS for successful copy
 * 		- errors as mentioned in xfsbl_error.h
 *
 *****************************************************************************/
u32 XFsbl_Qspi32Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
{
	u32 Status = XFSBL_SUCCESS;
	u32 QspiAddr=0;
	u32 RemainingBytes=0;
	u32 TransferBytes=0;
	u32 DiscardByteCnt;

	XFsbl_Printf(DEBUG_INFO,"QSPI Reading Src 0x%0lx, Dest %0lx, Length %0lx\r\n",
			SrcAddress, DestAddress, Length);

	/**
	 * Check the read length with Qspi flash size
	 */
	if ((SrcAddress + Length) > QspiFlashSize)
	{
		Status = XFSBL_ERROR_QSPI_LENGTH;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_LENGTH\r\n");
		goto END;
	}


	/**
	 * Update no of bytes to be copied
	 */
	RemainingBytes = Length;

	while(RemainingBytes > 0) {

		if (RemainingBytes > DMA_DATA_TRAN_SIZE)
		{
			TransferBytes = DMA_DATA_TRAN_SIZE;
		} else {
			TransferBytes = RemainingBytes;
		}

		/**
		 * Translate address based on type of connection
		 * If stacked assert the slave select based on address
		 */
		QspiAddr = XFsbl_GetQspiAddr((u32 )SrcAddress);

		XFsbl_Printf(DEBUG_INFO,".");
		XFsbl_Printf(DEBUG_DETAILED,
					"QSPI Read Src 0x%0lx, Dest %0lx, Length %0lx\r\n",
						QspiAddr, DestAddress, TransferBytes);

		/**
		 * Setup the read command with the specified address and data for the
		 * Flash
		 */

		WriteBuffer[COMMAND_OFFSET]   = ReadCommand;
		WriteBuffer[ADDRESS_1_OFFSET] = (u8)((QspiAddr & 0xFF000000) >> 24);
		WriteBuffer[ADDRESS_2_OFFSET] = (u8)((QspiAddr & 0xFF0000) >> 16);
		WriteBuffer[ADDRESS_3_OFFSET] = (u8)((QspiAddr & 0xFF00) >> 8);
		WriteBuffer[ADDRESS_4_OFFSET] = (u8)(QspiAddr & 0xFF);
		DiscardByteCnt = 5;

		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;

		/*
		 * It is recommended to have a separate entry for dummy
		 */
		if ((ReadCommand == FAST_READ_CMD_32BIT) ||
				(ReadCommand == DUAL_READ_CMD_32BIT) ||
				(ReadCommand == QUAD_READ_CMD_32BIT)) {

			/* 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 (ReadCommand == FAST_READ_CMD_32BIT) {
				FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
			}

			if (ReadCommand == DUAL_READ_CMD_32BIT) {
				FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_DUALSPI;
			}

			if (ReadCommand == QUAD_READ_CMD_32BIT) {
				FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_QUADSPI;
			}

			FlashMsg[1].TxBfrPtr = NULL;
			FlashMsg[1].RxBfrPtr = NULL;
			FlashMsg[1].ByteCount = DUMMY_CLOCKS;
			FlashMsg[1].Flags = 0;
		}

		if (ReadCommand == FAST_READ_CMD_32BIT) {
			FlashMsg[2].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
		}

		if (ReadCommand == DUAL_READ_CMD_32BIT) {
			FlashMsg[2].BusWidth = XQSPIPSU_SELECT_MODE_DUALSPI;
		}

		if (ReadCommand == QUAD_READ_CMD_32BIT) {
			FlashMsg[2].BusWidth = XQSPIPSU_SELECT_MODE_QUADSPI;
		}

		FlashMsg[2].TxBfrPtr = NULL;
		FlashMsg[2].RxBfrPtr = (u8 *)DestAddress;
		FlashMsg[2].ByteCount = TransferBytes;
		FlashMsg[2].Flags = XQSPIPSU_MSG_FLAG_RX;

		if(QspiPsuInstancePtr->Config.ConnectionMode ==
				XQSPIPSU_CONNECTION_MODE_PARALLEL){
			FlashMsg[2].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
		}

		/**
		 * Send the read command to the Flash to read the specified number
		 * of bytes from the Flash, send the read command and address and
		 * receive the specified number of bytes of data in the data buffer
		 */
		Status = XQspiPsu_PolledTransfer(QspiPsuInstancePtr, FlashMsg, 3);
		if (Status != XST_SUCCESS) {
			Status = XFSBL_ERROR_QSPI_READ;
			XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n");
			goto END;
		}

		/**
		 * Update the variables
		 */
		RemainingBytes -= TransferBytes;
		DestAddress += TransferBytes;
		SrcAddress += TransferBytes;

	}

END:
	return Status;
}
예제 #2
0
/******************************************************************************
*
* This function reads serial FLASH ID connected to the SPI interface.
* It then deduces the make and size of the flash and obtains the
* connection mode to point to corresponding parameters in the flash
* configuration table. The flash driver will function based on this and
* it presently supports Micron and Spansion - 128, 256 and 512Mbit and
* Winbond 128Mbit
*
* @param	none
*
* @return	XST_SUCCESS if read id, otherwise XST_FAILURE.
*
* @note		None.
*
******************************************************************************/
int FlashReadID(XQspiPsu *QspiPsuPtr)
{
	int Status = XST_SUCCESS;

	/*
	 * Read ID
	 */
	TxBfrPtr = READ_ID_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;

	FlashMsg[1].TxBfrPtr = NULL;
	FlashMsg[1].RxBfrPtr = ReadBuffer;
	FlashMsg[1].ByteCount = 4;
	FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
	FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;

	Status = XQspiPsu_PolledTransfer(QspiPsuPtr, FlashMsg, 2);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	xil_printf("FlashID=0x%x 0x%x 0x%x\n\r", ReadBuffer[0], ReadBuffer[1],
		   ReadBuffer[2]);

	/*
	 * Deduce flash make
	 */
	if (ReadBuffer[0] == MICRON_ID) {
		QspiFlashMake = MICRON_ID;
		XFsbl_Printf(DEBUG_INFO, "MICRON ");
	} else if(ReadBuffer[0] == SPANSION_ID) {
		QspiFlashMake = SPANSION_ID;
		XFsbl_Printf(DEBUG_INFO, "SPANSION ");
	} else if(ReadBuffer[0] == WINBOND_ID) {
		QspiFlashMake = WINBOND_ID;
		XFsbl_Printf(DEBUG_INFO, "WINBOND ");
	} else {
		Status = XFSBL_ERROR_UNSUPPORTED_QSPI;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_UNSUPPORTED_QSPI\r\n");
		goto END;
	}

	/*
	 * Deduce flash Size
	 */
	if (ReadBuffer[2] == FLASH_SIZE_ID_128M) {
		QspiFlashSize = FLASH_SIZE_128M;
		XFsbl_Printf(DEBUG_INFO, "128M Bits\r\n");
	} else if (ReadBuffer[2] == FLASH_SIZE_ID_256M) {
		QspiFlashSize = FLASH_SIZE_256M;
		XFsbl_Printf(DEBUG_INFO, "256M Bits\r\n");
	} else if (ReadBuffer[2] == FLASH_SIZE_ID_512M) {
		QspiFlashSize = FLASH_SIZE_512M;
		XFsbl_Printf(DEBUG_INFO, "512M Bits\r\n");
	} else if (ReadBuffer[2] == FLASH_SIZE_ID_1G) {
		QspiFlashSize = FLASH_SIZE_1G;
		XFsbl_Printf(DEBUG_INFO, "1G Bits\r\n");
	}else {
		Status = XFSBL_ERROR_UNSUPPORTED_QSPI;
		XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_UNSUPPORTED_QSPI\r\n");
		goto END;
	}

END:
	return Status;
}
예제 #3
0
/******************************************************************************
*
* This functions selects the current bank
*
* @param	QspiPtr is a pointer to the QSPI driver component to use.
* @param	Pointer to the write buffer which contains data to be transmitted
* @param	BankSel is the bank to be selected in the flash device(s).
*
* @return	XST_SUCCESS if bank selected, otherwise XST_FAILURE.
*
* @note		None.
*
*
******************************************************************************/
static int SendBankSelect(u32 BankSel)
{
	u32 Status = XFSBL_SUCCESS;

	/*
	 * bank select commands for Micron and Spansion are different
	 */
	if (QspiFlashMake == MICRON_ID)	{
		/*
		 * For micron command WREN should be sent first
		 * except for some specific feature set
		 */
		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(QspiPsuInstancePtr, FlashMsg, 1);
		if (Status != XST_SUCCESS) {
			Status = XFSBL_ERROR_QSPI_READ;
			XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n");
			goto END;
		}

		/*
		 * Send the Extended address register write command
		 * written, no receive buffer required
		 */
		WriteBuffer[COMMAND_OFFSET]   = EXTADD_REG_WR_CMD;
		WriteBuffer[ADDRESS_1_OFFSET] = BankSel;

		FlashMsg[0].TxBfrPtr = WriteBuffer;
		FlashMsg[0].RxBfrPtr = NULL;
		FlashMsg[0].ByteCount = 2;
		FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
		FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;

		Status = XQspiPsu_PolledTransfer(QspiPsuInstancePtr, FlashMsg, 1);
		if (Status != XST_SUCCESS) {
			Status = XFSBL_ERROR_QSPI_READ;
			XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n");
			goto END;
		}
	}

	if (QspiFlashMake == SPANSION_ID) {
		/*
		 * Send the Extended address register write command
		 * written, no receive buffer required
		 */
		WriteBuffer[COMMAND_OFFSET]   = BANK_REG_WR_CMD;
		WriteBuffer[ADDRESS_1_OFFSET] = BankSel;

		FlashMsg[0].TxBfrPtr = WriteBuffer;
		FlashMsg[0].RxBfrPtr = NULL;
		FlashMsg[0].ByteCount = 2;
		FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
		FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;

		Status = XQspiPsu_PolledTransfer(QspiPsuInstancePtr, FlashMsg, 1);
		if (Status != XST_SUCCESS) {
			Status = XFSBL_ERROR_QSPI_READ;
			XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n");
			goto END;
		}
	}

	/*
	 * For testing - Read bank to verify
	 */
	if (QspiFlashMake == MICRON_ID) {
		/*
		 * Extended address register read command
		 */

		WriteBuffer[COMMAND_OFFSET]   = EXTADD_REG_RD_CMD;
		FlashMsg[0].TxBfrPtr = WriteBuffer;
		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 = ReadBuffer;
		FlashMsg[1].ByteCount = 1;
		FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
		FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;

		Status = XQspiPsu_PolledTransfer(QspiPsuInstancePtr, FlashMsg, 2);
		if (Status != XST_SUCCESS) {
			Status = XFSBL_ERROR_QSPI_READ;
			XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n");
			goto END;
		}
	}

	if (QspiFlashMake == SPANSION_ID) {
		/*
		 * Bank register read command
		 */
		WriteBuffer[COMMAND_OFFSET]   = BANK_REG_RD_CMD;
		FlashMsg[0].TxBfrPtr = WriteBuffer;
		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 = ReadBuffer;
		FlashMsg[1].ByteCount = 1;
		FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
		FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;

		Status = XQspiPsu_PolledTransfer(QspiPsuInstancePtr, FlashMsg, 2);
		if (Status != XST_SUCCESS) {
			Status = XFSBL_ERROR_QSPI_READ;
			XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n");
			goto END;
		}

		if (ReadBuffer[0] != BankSel) {
			XFsbl_Printf(DEBUG_INFO, "Bank Select %d != Register Read %d\n\r", BankSel,
				ReadBuffer[0]);
			Status = XFSBL_ERROR_QSPI_READ;
			XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n");
			goto END;
		}
	}

	/* Winbond can be added here */
END:
	return Status;
}
예제 #4
0
/**
 * This function is used to copy the data from QSPI flash to destination
 * address
 *
 * @param SrcAddress is the address of the QSPI flash where copy should
 * start from
 *
 * @param DestAddress is the address of the destination where it
 * should copy to
 *
 * @param Length Length of the bytes to be copied
 *
 * @return
 * 		- XFSBL_SUCCESS for successful copy
 * 		- errors as mentioned in xfsbl_error.h
 *
 *****************************************************************************/
u32 XFsbl_Qspi24Copy(u32 SrcAddress, PTRSIZE DestAddress, u32 Length)
{
    u32 Status = XFSBL_SUCCESS;
    u32 QspiAddr=0, OrigAddr=0;
    u32 BankSel=0;
    u32 RemainingBytes=0;
    u32 TransferBytes=0;
    u32 DiscardByteCnt;
    u8 BankSwitchFlag=0;
    u32 BankSize=SINGLEBANKSIZE;
    u32 BankMask=SINGLEBANKMASK;

    XFsbl_Printf(DEBUG_INFO,"QSPI Reading Src 0x%0lx, Dest %0lx, Length %0lx\r\n",
                 SrcAddress, DestAddress, Length);

    /**
     * Check the read length with Qspi flash size
     */
    if ((SrcAddress + Length) > QspiFlashSize)
    {
        Status = XFSBL_ERROR_QSPI_LENGTH;
        XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_LENGTH\r\n");
        goto END;
    }

    /* Multiply bank size & mask in case of Dual Parallel */
    if (QspiPsuInstancePtr->Config.ConnectionMode ==
            XQSPIPSU_CONNECTION_MODE_PARALLEL) {
        BankSize =  SINGLEBANKSIZE * 2;
        BankMask =  SINGLEBANKMASK * 2;
    }

    /**
     * Update no of bytes to be copied
     */
    RemainingBytes = Length;

    while(RemainingBytes > 0) {

        if (RemainingBytes > DMA_DATA_TRAN_SIZE)
        {
            TransferBytes = DMA_DATA_TRAN_SIZE;
        } else {
            TransferBytes = RemainingBytes;
        }

        /**
         * Translate address based on type of connection
         * If stacked assert the slave select based on address
         */
        QspiAddr = XFsbl_GetQspiAddr((u32 )SrcAddress);

        /**
         * Multiply address by 2 in case of Dual Parallel
         * This address is used to calculate the bank crossing
         * condition
         */
        if (QspiPsuInstancePtr->Config.ConnectionMode ==
                XQSPIPSU_CONNECTION_MODE_PARALLEL) {
            OrigAddr = QspiAddr * 2;
        } else {
            OrigAddr = QspiAddr;
        }

        /**
         * Select bank
         * check logic for DualQspi
         */
        if(QspiFlashSize > BankSize) {
            BankSel = QspiAddr/BANKSIZE;
            Status = SendBankSelect(BankSel);
            if (Status != XFSBL_SUCCESS) {
                Status = XFSBL_ERROR_QSPI_READ;
                XFsbl_Printf(DEBUG_GENERAL,
                             "XFSBL_ERROR_QSPI_READ\r\n");
                goto END;
            }
        }


        /**
         * If data to be read spans beyond the current bank, then
         * calculate Transfer Bytes in current bank. 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);

        /**
         * Setup the read command with the specified address and data for the
         * Flash
         */

        WriteBuffer[COMMAND_OFFSET]   = ReadCommand;
        WriteBuffer[ADDRESS_1_OFFSET] = (u8)((QspiAddr & 0xFF0000) >> 16);
        WriteBuffer[ADDRESS_2_OFFSET] = (u8)((QspiAddr & 0xFF00) >> 8);
        WriteBuffer[ADDRESS_3_OFFSET] = (u8)(QspiAddr & 0xFF);
        DiscardByteCnt = 4;

        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;

        /* It is recommended to have a separate entry for dummy */
        if ((ReadCommand == FAST_READ_CMD_24BIT) || (ReadCommand == DUAL_READ_CMD_24BIT) ||
                (ReadCommand == QUAD_READ_CMD_24BIT)) {
            /* 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 (ReadCommand == FAST_READ_CMD_24BIT) {
                FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
            }

            if (ReadCommand == DUAL_READ_CMD_24BIT) {
                FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_DUALSPI;
            }

            if (ReadCommand == QUAD_READ_CMD_24BIT) {
                FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_QUADSPI;
            }

            FlashMsg[1].TxBfrPtr = NULL;
            FlashMsg[1].RxBfrPtr = NULL;
            FlashMsg[1].ByteCount = DUMMY_CLOCKS;
            FlashMsg[1].Flags = 0;
        }

        if (ReadCommand == FAST_READ_CMD_24BIT) {
            FlashMsg[2].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
        }

        if (ReadCommand == DUAL_READ_CMD_24BIT) {
            FlashMsg[2].BusWidth = XQSPIPSU_SELECT_MODE_DUALSPI;
        }

        if (ReadCommand == QUAD_READ_CMD_24BIT) {
            FlashMsg[2].BusWidth = XQSPIPSU_SELECT_MODE_QUADSPI;
        }

        FlashMsg[2].TxBfrPtr = NULL;
        FlashMsg[2].RxBfrPtr = (u8 *)DestAddress;
        FlashMsg[2].ByteCount = TransferBytes;
        FlashMsg[2].Flags = XQSPIPSU_MSG_FLAG_RX;

        if(QspiPsuInstancePtr->Config.ConnectionMode ==
                XQSPIPSU_CONNECTION_MODE_PARALLEL) {
            FlashMsg[2].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
        }

        /**
         * Send the read command to the Flash to read the specified number
         * of bytes from the Flash, send the read command and address and
         * receive the specified number of bytes of data in the data buffer
         */
        Status = XQspiPsu_PolledTransfer(QspiPsuInstancePtr, FlashMsg, 3);
        if (Status != XST_SUCCESS) {
            Status = XFSBL_ERROR_QSPI_READ;
            XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n");
            goto END;
        }

        /**
         * Update the variables
         */
        RemainingBytes -= TransferBytes;
        DestAddress += TransferBytes;
        SrcAddress += TransferBytes;
    }

    if(BankSwitchFlag == 1)
    {
        /*
         * Reset Bank selection to zero
         */
        Status = SendBankSelect(0);
        if (Status != XST_SUCCESS) {
            Status = XFSBL_ERROR_QSPI_READ;
            XFsbl_Printf(DEBUG_GENERAL,"XFSBL_ERROR_QSPI_READ\r\n");
            goto END;
        }
    }

END:
    return Status;
}