791 lines
21 KiB
C
791 lines
21 KiB
C
/*****************************************************************************
|
|
* Copyright (c) 2012 - 2020 Xilinx, Inc. All rights reserved.
|
|
* SPDX-License-Identifier: MIT
|
|
******************************************************************************/
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* @file pcap.c
|
|
*
|
|
* Contains code for enabling and accessing the PCAP
|
|
*
|
|
* <pre>
|
|
* MODIFICATION HISTORY:
|
|
*
|
|
* Ver Who Date Changes
|
|
* ----- ---- -------- -------------------------------------------------------
|
|
* 1.00a ecm 02/10/10 Initial release
|
|
* 2.00a jz 05/28/11 Add SD support
|
|
* 2.00a mb 25/05/12 using the EDK provided devcfg driver
|
|
* Nand/SD encryption and review comments
|
|
* 3.00a mb 16/08/12 Added the poll function
|
|
* Removed the FPGA_RST_CTRL define
|
|
* Added the flag for NON PS instantiated bitstream
|
|
* 4.00a sgd 02/28/13 Fix for CR#681014 - ECC init in FSBL should not call
|
|
* fabric_init()
|
|
* Fix for CR#689026 - FSBL doesn't hold PL resets active
|
|
* during bit download
|
|
* Fix for CR#699475 - FSBL functionality is broken and
|
|
* its not able to boot in QSPI/NAND
|
|
* bootmode
|
|
* Fix for CR#705664 - FSBL fails to decrypt the
|
|
* bitstream when the image is AES
|
|
* encrypted using non-zero key value
|
|
* 6.00a kc 08/30/13 Fix for CR#722979 - Provide customer-friendly
|
|
* changelogs in FSBL
|
|
* 7.00a kc 10/25/13 Fix for CR#724620 - How to handle PCAP_MODE after
|
|
* bitstream configuration
|
|
* Fix for CR#726178 - FabricInit() PROG_B is kept active
|
|
* for 5mS.
|
|
* Fix for CR#731839 - FSBL has to check the
|
|
* HMAC error status after decryption
|
|
* 12/04/13 Fix for CR#764382 - How to handle PCAP_MODE after
|
|
* bitstream configuration - PCAP_MODE
|
|
* and PCAP_PR bits are not modified
|
|
* 8.00a kc 2/20/14 Fix for CR#775631 - FSBL: FsblGetGlobalTimer()
|
|
* is not proper
|
|
* 10.00a kc 07/24/14 Fix for CR#809336 - Minor code cleanup
|
|
* 13.00a ssc 04/10/15 Fix for CR#846899 - Corrected logic to clear
|
|
* DMA done count
|
|
* 15.00a gan 07/21/16 Fix for CR# 953654 -(2016.3)FSBL -
|
|
* In pcap.c/pcap.h/main.h,
|
|
* Fabric Initialization sequence
|
|
* is modified to check the PL power
|
|
* before sequence starts and checking
|
|
* INIT_B reset status twice in case
|
|
* of failure.
|
|
* 16.00a gan 08/02/16 Fix for CR# 955897 -(2016.3)FSBL -
|
|
* In pcap.c, check pl power
|
|
* through MCTRL register for
|
|
* 3.0 and later versions of silicon.
|
|
* </pre>
|
|
*
|
|
* @note
|
|
*
|
|
******************************************************************************/
|
|
|
|
/***************************** Include Files *********************************/
|
|
|
|
#include "pcap.h"
|
|
#include "nand.h" /* For NAND geometry information */
|
|
#include "fsbl.h"
|
|
#include "image_mover.h" /* For MoveImage */
|
|
#include "xparameters.h"
|
|
#include "xil_exception.h"
|
|
#include "xdevcfg.h"
|
|
#include "sleep.h"
|
|
#include "xtime_l.h"
|
|
|
|
#ifdef XPAR_XWDTPS_0_BASEADDR
|
|
#include "xwdtps.h"
|
|
#endif
|
|
/************************** Constant Definitions *****************************/
|
|
/*
|
|
* The following constants map to the XPAR parameters created in the
|
|
* xparameters.h file. They are only defined here such that a user can easily
|
|
* change all the needed parameters in one place.
|
|
*/
|
|
|
|
#define DCFG_DEVICE_ID XPAR_XDCFG_0_DEVICE_ID
|
|
|
|
/**************************** Type Definitions *******************************/
|
|
|
|
/***************** Macros (Inline Functions) Definitions *********************/
|
|
|
|
/************************** Function Prototypes ******************************/
|
|
extern int XDcfgPollDone(u32 MaskValue, u32 MaxCount);
|
|
|
|
/************************** Variable Definitions *****************************/
|
|
/* Devcfg driver instance */
|
|
static XDcfg DcfgInstance;
|
|
XDcfg *DcfgInstPtr;
|
|
extern u32 Silicon_Version;
|
|
#ifdef XPAR_XWDTPS_0_BASEADDR
|
|
extern XWdtPs Watchdog; /* Instance of WatchDog Timer */
|
|
#endif
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
*
|
|
* This function transfer data using PCAP
|
|
*
|
|
* @param SourceDataPtr is a pointer to where the data is read from
|
|
* @param DestinationDataPtr is a pointer to where the data is written to
|
|
* @param SourceLength is the length of the data to be moved in words
|
|
* @param DestinationLength is the length of the data to be moved in words
|
|
* @param SecureTransfer indicated the encryption key location, 0 for
|
|
* non-encrypted
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if the transfer is successful
|
|
* - XST_FAILURE if the transfer fails
|
|
*
|
|
* @note None
|
|
*
|
|
****************************************************************************/
|
|
u32 PcapDataTransfer(u32 *SourceDataPtr, u32 *DestinationDataPtr,
|
|
u32 SourceLength, u32 DestinationLength, u32 SecureTransfer)
|
|
{
|
|
u32 Status;
|
|
u32 IntrStsReg;
|
|
u32 PcapTransferType = XDCFG_CONCURRENT_NONSEC_READ_WRITE;
|
|
|
|
/*
|
|
* Check for secure transfer
|
|
*/
|
|
if (SecureTransfer) {
|
|
PcapTransferType = XDCFG_CONCURRENT_SECURE_READ_WRITE;
|
|
}
|
|
|
|
#ifdef FSBL_PERF
|
|
XTime tXferCur = 0;
|
|
FsblGetGlobalTime(&tXferCur);
|
|
#endif
|
|
|
|
/*
|
|
* Clear the PCAP status registers
|
|
*/
|
|
Status = ClearPcapStatus();
|
|
if (Status != XST_SUCCESS) {
|
|
fsbl_printf(DEBUG_INFO,"PCAP_CLEAR_STATUS_FAIL \r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
#ifdef XPAR_XWDTPS_0_BASEADDR
|
|
/*
|
|
* Prevent WDT reset
|
|
*/
|
|
XWdtPs_RestartWdt(&Watchdog);
|
|
#endif
|
|
|
|
/*
|
|
* PCAP single DMA transfer setup
|
|
*/
|
|
SourceDataPtr = (u32*)((u32)SourceDataPtr | PCAP_LAST_TRANSFER);
|
|
DestinationDataPtr = (u32*)((u32)DestinationDataPtr | PCAP_LAST_TRANSFER);
|
|
|
|
/*
|
|
* Transfer using Device Configuration
|
|
*/
|
|
Status = XDcfg_Transfer(DcfgInstPtr, (u8 *)SourceDataPtr,
|
|
SourceLength,
|
|
(u8 *)DestinationDataPtr,
|
|
DestinationLength, PcapTransferType);
|
|
if (Status != XST_SUCCESS) {
|
|
fsbl_printf(DEBUG_INFO,"Status of XDcfg_Transfer = %lu \r \n",Status);
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* Dump the PCAP registers
|
|
*/
|
|
PcapDumpRegisters();
|
|
|
|
/*
|
|
* Poll for the DMA done
|
|
*/
|
|
Status = XDcfgPollDone(XDCFG_IXR_DMA_DONE_MASK, MAX_COUNT);
|
|
if (Status != XST_SUCCESS) {
|
|
fsbl_printf(DEBUG_INFO,"PCAP_DMA_DONE_FAIL \r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
fsbl_printf(DEBUG_INFO,"DMA Done ! \n\r");
|
|
|
|
/*
|
|
* Check for errors
|
|
*/
|
|
IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
|
|
if (IntrStsReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) {
|
|
fsbl_printf(DEBUG_INFO,"Errors in PCAP \r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* For Performance measurement
|
|
*/
|
|
#ifdef FSBL_PERF
|
|
XTime tXferEnd = 0;
|
|
fsbl_printf(DEBUG_GENERAL,"Time taken is ");
|
|
FsblMeasurePerfTime(tXferCur,tXferEnd);
|
|
#endif
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
*
|
|
* This function loads PL partition using PCAP
|
|
*
|
|
* @param SourceDataPtr is a pointer to where the data is read from
|
|
* @param DestinationDataPtr is a pointer to where the data is written to
|
|
* @param SourceLength is the length of the data to be moved in words
|
|
* @param DestinationLength is the length of the data to be moved in words
|
|
* @param SecureTransfer indicated the encryption key location, 0 for
|
|
* non-encrypted
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if the transfer is successful
|
|
* - XST_FAILURE if the transfer fails
|
|
*
|
|
* @note None
|
|
*
|
|
****************************************************************************/
|
|
u32 PcapLoadPartition(u32 *SourceDataPtr, u32 *DestinationDataPtr,
|
|
u32 SourceLength, u32 DestinationLength, u32 SecureTransfer)
|
|
{
|
|
u32 Status;
|
|
u32 IntrStsReg;
|
|
u32 PcapTransferType = XDCFG_NON_SECURE_PCAP_WRITE;
|
|
|
|
/*
|
|
* Check for secure transfer
|
|
*/
|
|
if (SecureTransfer) {
|
|
PcapTransferType = XDCFG_SECURE_PCAP_WRITE;
|
|
}
|
|
|
|
#ifdef FSBL_PERF
|
|
XTime tXferCur = 0;
|
|
FsblGetGlobalTime(&tXferCur);
|
|
#endif
|
|
|
|
/*
|
|
* Clear the PCAP status registers
|
|
*/
|
|
Status = ClearPcapStatus();
|
|
if (Status != XST_SUCCESS) {
|
|
fsbl_printf(DEBUG_INFO,"PCAP_CLEAR_STATUS_FAIL \r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* For Bitstream case destination address will be 0xFFFFFFFF
|
|
*/
|
|
DestinationDataPtr = (u32*)XDCFG_DMA_INVALID_ADDRESS;
|
|
|
|
/*
|
|
* New Bitstream download initialization sequence
|
|
*/
|
|
Status = FabricInit();
|
|
if (Status != XST_SUCCESS) {
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
|
|
#ifdef XPAR_XWDTPS_0_BASEADDR
|
|
/*
|
|
* Prevent WDT reset
|
|
*/
|
|
XWdtPs_RestartWdt(&Watchdog);
|
|
#endif
|
|
|
|
/*
|
|
* PCAP single DMA transfer setup
|
|
*/
|
|
SourceDataPtr = (u32*)((u32)SourceDataPtr | PCAP_LAST_TRANSFER);
|
|
DestinationDataPtr = (u32*)((u32)DestinationDataPtr | PCAP_LAST_TRANSFER);
|
|
|
|
/*
|
|
* Transfer using Device Configuration
|
|
*/
|
|
Status = XDcfg_Transfer(DcfgInstPtr, (u8 *)SourceDataPtr,
|
|
SourceLength,
|
|
(u8 *)DestinationDataPtr,
|
|
DestinationLength, PcapTransferType);
|
|
if (Status != XST_SUCCESS) {
|
|
fsbl_printf(DEBUG_INFO,"Status of XDcfg_Transfer = %lu \r \n",Status);
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Dump the PCAP registers
|
|
*/
|
|
PcapDumpRegisters();
|
|
|
|
|
|
/*
|
|
* Poll for the DMA done
|
|
*/
|
|
Status = XDcfgPollDone(XDCFG_IXR_DMA_DONE_MASK, MAX_COUNT);
|
|
if (Status != XST_SUCCESS) {
|
|
fsbl_printf(DEBUG_INFO,"PCAP_DMA_DONE_FAIL \r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
fsbl_printf(DEBUG_INFO,"DMA Done ! \n\r");
|
|
|
|
/*
|
|
* Poll for FPGA Done
|
|
*/
|
|
Status = XDcfgPollDone(XDCFG_IXR_PCFG_DONE_MASK, MAX_COUNT);
|
|
if (Status != XST_SUCCESS) {
|
|
fsbl_printf(DEBUG_INFO,"PCAP_FPGA_DONE_FAIL\r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
fsbl_printf(DEBUG_INFO,"FPGA Done ! \n\r");
|
|
|
|
/*
|
|
* Check for errors
|
|
*/
|
|
IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
|
|
if (IntrStsReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) {
|
|
fsbl_printf(DEBUG_INFO,"Errors in PCAP \r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* For Performance measurement
|
|
*/
|
|
#ifdef FSBL_PERF
|
|
XTime tXferEnd = 0;
|
|
fsbl_printf(DEBUG_GENERAL,"Time taken is ");
|
|
FsblMeasurePerfTime(tXferCur,tXferEnd);
|
|
#endif
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
*
|
|
* This function Initializes the PCAP driver.
|
|
*
|
|
* @param none
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if the pcap driver initialization is successful
|
|
* - XST_FAILURE if the pcap driver initialization fails
|
|
*
|
|
* @note none
|
|
*
|
|
****************************************************************************/
|
|
int InitPcap(void)
|
|
{
|
|
XDcfg_Config *ConfigPtr;
|
|
int Status = XST_SUCCESS;
|
|
DcfgInstPtr = &DcfgInstance;
|
|
|
|
/*
|
|
* Initialize the Device Configuration Interface driver.
|
|
*/
|
|
ConfigPtr = XDcfg_LookupConfig(DCFG_DEVICE_ID);
|
|
|
|
Status = XDcfg_CfgInitialize(DcfgInstPtr, ConfigPtr,
|
|
ConfigPtr->BaseAddr);
|
|
if (Status != XST_SUCCESS) {
|
|
fsbl_printf(DEBUG_INFO, "XDcfg_CfgInitialize failed \n\r");
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
/**
|
|
*
|
|
* This function programs the Fabric for use.
|
|
*
|
|
* @param None
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if the Fabric initialization is successful
|
|
* - XST_FAILURE if the Fabric initialization fails
|
|
* @note None
|
|
*
|
|
****************************************************************************/
|
|
u32 FabricInit(void)
|
|
{
|
|
u32 PcapReg;
|
|
u32 PcapCtrlRegVal;
|
|
u32 StatusReg;
|
|
u32 MctrlReg;
|
|
u32 PcfgInit;
|
|
u32 TimerExpired=0;
|
|
XTime tCur=0;
|
|
XTime tEnd=0;
|
|
|
|
|
|
/*
|
|
* Set Level Shifters DT618760 - PS to PL enabling
|
|
*/
|
|
Xil_Out32(PS_LVL_SHFTR_EN, LVL_PS_PL);
|
|
fsbl_printf(DEBUG_INFO,"Level Shifter Value = 0x%lx \r\n",
|
|
Xil_In32(PS_LVL_SHFTR_EN));
|
|
|
|
/*
|
|
* Get DEVCFG controller settings
|
|
*/
|
|
PcapReg = XDcfg_ReadReg(DcfgInstPtr->Config.BaseAddr,
|
|
XDCFG_CTRL_OFFSET);
|
|
|
|
/*
|
|
* Check the PL power status
|
|
*/
|
|
if(Silicon_Version >= SILICON_VERSION_3)
|
|
{
|
|
MctrlReg = XDcfg_GetMiscControlRegister(DcfgInstPtr);
|
|
|
|
if((MctrlReg & XDCFG_MCTRL_PCAP_PCFG_POR_B_MASK) !=
|
|
XDCFG_MCTRL_PCAP_PCFG_POR_B_MASK)
|
|
{
|
|
fsbl_printf(DEBUG_INFO,"Fabric not powered up\r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Setting PCFG_PROG_B signal to high
|
|
*/
|
|
XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,
|
|
(PcapReg | XDCFG_CTRL_PCFG_PROG_B_MASK));
|
|
|
|
/*
|
|
* Check for AES source key
|
|
*/
|
|
PcapCtrlRegVal = XDcfg_GetControlRegister(DcfgInstPtr);
|
|
if (PcapCtrlRegVal & XDCFG_CTRL_PCFG_AES_FUSE_MASK) {
|
|
/*
|
|
* 5msec delay
|
|
*/
|
|
usleep(5000);
|
|
}
|
|
|
|
/*
|
|
* Setting PCFG_PROG_B signal to low
|
|
*/
|
|
XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,
|
|
(PcapReg & ~XDCFG_CTRL_PCFG_PROG_B_MASK));
|
|
|
|
/*
|
|
* Check for AES source key
|
|
*/
|
|
if (PcapCtrlRegVal & XDCFG_CTRL_PCFG_AES_FUSE_MASK) {
|
|
/*
|
|
* 5msec delay
|
|
*/
|
|
usleep(5000);
|
|
}
|
|
|
|
/*
|
|
* Polling the PCAP_INIT status for Reset or timeout
|
|
*/
|
|
|
|
XTime_GetTime(&tCur);
|
|
do
|
|
{
|
|
PcfgInit = (XDcfg_GetStatusRegister(DcfgInstPtr) &
|
|
XDCFG_STATUS_PCFG_INIT_MASK);
|
|
if(PcfgInit == 0)
|
|
{
|
|
break;
|
|
}
|
|
XTime_GetTime(&tEnd);
|
|
if((u64)((u64)tCur + (COUNTS_PER_MILLI_SECOND*30)) > (u64)tEnd)
|
|
{
|
|
TimerExpired = 1;
|
|
}
|
|
|
|
} while(!TimerExpired);
|
|
|
|
if(TimerExpired == 1)
|
|
{
|
|
TimerExpired = 0;
|
|
/*
|
|
* Came here due to expiration and PCAP_INIT is set.
|
|
* Retry PCFG_PROG_B High -> Low again
|
|
*/
|
|
|
|
/*
|
|
* Setting PCFG_PROG_B signal to high
|
|
*/
|
|
XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,
|
|
(PcapReg | XDCFG_CTRL_PCFG_PROG_B_MASK));
|
|
|
|
/*
|
|
* Check for AES source key
|
|
*/
|
|
PcapCtrlRegVal = XDcfg_GetControlRegister(DcfgInstPtr);
|
|
if (PcapCtrlRegVal & XDCFG_CTRL_PCFG_AES_FUSE_MASK) {
|
|
/*
|
|
* 5msec delay
|
|
*/
|
|
usleep(5000);
|
|
}
|
|
|
|
/*
|
|
* Setting PCFG_PROG_B signal to low
|
|
*/
|
|
XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,
|
|
(PcapReg & ~XDCFG_CTRL_PCFG_PROG_B_MASK));
|
|
|
|
/*
|
|
* Check for AES source key
|
|
*/
|
|
if (PcapCtrlRegVal & XDCFG_CTRL_PCFG_AES_FUSE_MASK) {
|
|
/*
|
|
* 5msec delay
|
|
*/
|
|
usleep(5000);
|
|
}
|
|
/*
|
|
* Polling the PCAP_INIT status for Reset or timeout (second iteration)
|
|
*/
|
|
|
|
XTime_GetTime(&tCur);
|
|
do
|
|
{
|
|
PcfgInit = (XDcfg_GetStatusRegister(DcfgInstPtr) &
|
|
XDCFG_STATUS_PCFG_INIT_MASK);
|
|
if(PcfgInit == 0)
|
|
{
|
|
break;
|
|
}
|
|
XTime_GetTime(&tEnd);
|
|
if((u64)((u64)tCur + (COUNTS_PER_MILLI_SECOND*30)) > (u64)tEnd)
|
|
{
|
|
TimerExpired = 1;
|
|
}
|
|
|
|
} while(!TimerExpired);
|
|
|
|
if(TimerExpired == 1)
|
|
{
|
|
/*
|
|
* Came here due to PCAP_INIT is not getting reset
|
|
* for PCFG_PROG_B signal High -> Low
|
|
*/
|
|
fsbl_printf(DEBUG_INFO,"Fabric Init failed\r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Setting PCFG_PROG_B signal to high
|
|
*/
|
|
XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,
|
|
(PcapReg | XDCFG_CTRL_PCFG_PROG_B_MASK));
|
|
|
|
/*
|
|
* Polling the PCAP_INIT status for Set
|
|
*/
|
|
while(!(XDcfg_GetStatusRegister(DcfgInstPtr) &
|
|
XDCFG_STATUS_PCFG_INIT_MASK));
|
|
|
|
/*
|
|
* Get Device configuration status
|
|
*/
|
|
StatusReg = XDcfg_GetStatusRegister(DcfgInstPtr);
|
|
fsbl_printf(DEBUG_INFO,"Devcfg Status register = 0x%lx \r\n",StatusReg);
|
|
|
|
fsbl_printf(DEBUG_INFO,"PCAP:Fabric is Initialized done\r\n");
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
/******************************************************************************/
|
|
/**
|
|
*
|
|
* This function Clears the PCAP status registers.
|
|
*
|
|
* @param None
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if the pcap status registers are cleared
|
|
* - XST_FAILURE if errors are there
|
|
* - XST_DEVICE_BUSY if Pcap device is busy
|
|
* @note None
|
|
*
|
|
****************************************************************************/
|
|
u32 ClearPcapStatus(void)
|
|
{
|
|
|
|
u32 StatusReg;
|
|
u32 IntStatusReg;
|
|
|
|
/*
|
|
* Clear it all, so if Boot ROM comes back, it can proceed
|
|
*/
|
|
XDcfg_IntrClear(DcfgInstPtr, 0xFFFFFFFF);
|
|
|
|
/*
|
|
* Get PCAP Interrupt Status Register
|
|
*/
|
|
IntStatusReg = XDcfg_IntrGetStatus(DcfgInstPtr);
|
|
if (IntStatusReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) {
|
|
fsbl_printf(DEBUG_INFO,"FATAL errors in PCAP %lx\r\n",
|
|
IntStatusReg);
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* Read the PCAP status register for DMA status
|
|
*/
|
|
StatusReg = XDcfg_GetStatusRegister(DcfgInstPtr);
|
|
|
|
fsbl_printf(DEBUG_INFO,"PCAP:StatusReg = 0x%.8lx\r\n", StatusReg);
|
|
|
|
/*
|
|
* If the queue is full, return w/ XST_DEVICE_BUSY
|
|
*/
|
|
if ((StatusReg & XDCFG_STATUS_DMA_CMD_Q_F_MASK) ==
|
|
XDCFG_STATUS_DMA_CMD_Q_F_MASK) {
|
|
|
|
fsbl_printf(DEBUG_INFO,"PCAP_DEVICE_BUSY\r\n");
|
|
return XST_DEVICE_BUSY;
|
|
}
|
|
|
|
fsbl_printf(DEBUG_INFO,"PCAP:device ready\r\n");
|
|
|
|
/*
|
|
* There are unacknowledged DMA commands outstanding
|
|
*/
|
|
if ((StatusReg & XDCFG_STATUS_DMA_CMD_Q_E_MASK) !=
|
|
XDCFG_STATUS_DMA_CMD_Q_E_MASK) {
|
|
|
|
IntStatusReg = XDcfg_IntrGetStatus(DcfgInstPtr);
|
|
|
|
if ((IntStatusReg & XDCFG_IXR_DMA_DONE_MASK) !=
|
|
XDCFG_IXR_DMA_DONE_MASK){
|
|
/*
|
|
* Error state, transfer cannot occur
|
|
*/
|
|
fsbl_printf(DEBUG_INFO,"PCAP:IntStatus indicates error\r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
else {
|
|
/*
|
|
* clear out the status
|
|
*/
|
|
XDcfg_IntrClear(DcfgInstPtr, XDCFG_IXR_DMA_DONE_MASK);
|
|
}
|
|
}
|
|
|
|
if ((StatusReg & XDCFG_STATUS_DMA_DONE_CNT_MASK) != 0) {
|
|
XDcfg_SetStatusRegister(DcfgInstPtr, StatusReg |
|
|
XDCFG_STATUS_DMA_DONE_CNT_MASK);
|
|
}
|
|
|
|
fsbl_printf(DEBUG_INFO,"PCAP:Clear done\r\n");
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
*
|
|
* This function prints PCAP register status.
|
|
*
|
|
* @param none
|
|
*
|
|
* @return none
|
|
*
|
|
* @note none
|
|
*
|
|
****************************************************************************/
|
|
void PcapDumpRegisters (void) {
|
|
|
|
fsbl_printf(DEBUG_INFO,"PCAP register dump:\r\n");
|
|
|
|
fsbl_printf(DEBUG_INFO,"PCAP CTRL 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_CTRL_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_CTRL_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP LOCK 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_LOCK_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_LOCK_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP CONFIG 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_CFG_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_CFG_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP ISR 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_STS_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_STS_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP IMR 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_MASK_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_MASK_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP STATUS 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_STATUS_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_STATUS_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP DMA SRC ADDR 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_ADDR_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_ADDR_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP DMA DEST ADDR 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_ADDR_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_ADDR_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP DMA SRC LEN 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_LEN_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_LEN_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP DMA DEST LEN 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_LEN_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_LEN_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP ROM SHADOW CTRL 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_ROM_SHADOW_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_ROM_SHADOW_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP MBOOT 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_MULTIBOOT_ADDR_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_MULTIBOOT_ADDR_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP SW ID 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_SW_ID_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_SW_ID_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP UNLOCK 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_UNLOCK_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_UNLOCK_OFFSET));
|
|
fsbl_printf(DEBUG_INFO,"PCAP MCTRL 0x%x: 0x%08lx\r\n",
|
|
XPS_DEV_CFG_APB_BASEADDR + XDCFG_MCTRL_OFFSET,
|
|
Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_MCTRL_OFFSET));
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
*
|
|
* This function Polls for the DMA done or FPGA done.
|
|
*
|
|
* @param none
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if polling for DMA/FPGA done is successful
|
|
* - XST_FAILURE if polling for DMA/FPGA done fails
|
|
*
|
|
* @note none
|
|
*
|
|
****************************************************************************/
|
|
int XDcfgPollDone(u32 MaskValue, u32 MaxCount)
|
|
{
|
|
int Count = MaxCount;
|
|
u32 IntrStsReg = 0;
|
|
|
|
/*
|
|
* poll for the DMA done
|
|
*/
|
|
IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
|
|
while ((IntrStsReg & MaskValue) !=
|
|
MaskValue) {
|
|
IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
|
|
Count -=1;
|
|
|
|
if (IntrStsReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) {
|
|
fsbl_printf(DEBUG_INFO,"FATAL errors in PCAP %lx\r\n",
|
|
IntrStsReg);
|
|
PcapDumpRegisters();
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
if(!Count) {
|
|
fsbl_printf(DEBUG_GENERAL,"PCAP transfer timed out \r\n");
|
|
return XST_FAILURE;
|
|
}
|
|
if (Count > (MAX_COUNT-100)) {
|
|
fsbl_printf(DEBUG_GENERAL,".");
|
|
}
|
|
}
|
|
|
|
fsbl_printf(DEBUG_GENERAL,"\n\r");
|
|
|
|
XDcfg_IntrClear(DcfgInstPtr, IntrStsReg & MaskValue);
|
|
|
|
return XST_SUCCESS;
|
|
}
|