
Modified the function by replacing XDCFG_INT_STS_OFFSET) & XDCFG_IXR_D_P_DONE_MASK) == XDCFG_IXR_D_P_DONE_MASK); with XDCFG_INT_STS_OFFSET) & XDCFG_IXR_D_P_DONE_MASK) != XDCFG_IXR_D_P_DONE_MASK); Signed-off-by: Shakti Bhatnagar <shaktib@xilinx.com>
942 lines
29 KiB
C
Executable file
942 lines
29 KiB
C
Executable file
/******************************************************************************
|
||
*
|
||
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
|
||
*
|
||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
* of this software and associated documentation files (the "Software"), to deal
|
||
* in the Software without restriction, including without limitation the rights
|
||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
* copies of the Software, and to permit persons to whom the Software is
|
||
* furnished to do so, subject to the following conditions:
|
||
*
|
||
* The above copyright notice and this permission notice shall be included in
|
||
* all copies or substantial portions of the Software.
|
||
*
|
||
* Use of the Software is limited solely to applications:
|
||
* (a) running on a Xilinx device, or
|
||
* (b) that interact with a Xilinx device through a bus or interconnect.
|
||
*
|
||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
* SOFTWARE.
|
||
*
|
||
* Except as contained in this notice, the name of the Xilinx shall not be used
|
||
* in advertising or otherwise to promote the sale, use or other dealings in
|
||
* this Software without prior written authorization from Xilinx.
|
||
*
|
||
******************************************************************************/
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* @file xdevcfg.c
|
||
*
|
||
* This file contains the implementation of the interface functions for XDcfg
|
||
* driver. Refer to the header file xdevcfg.h for more detailed information.
|
||
*
|
||
* <pre>
|
||
* MODIFICATION HISTORY:
|
||
*
|
||
* Ver Who Date Changes
|
||
* ----- --- -------- ---------------------------------------------
|
||
* 1.00a hvm 02/07/11 First release
|
||
* 2.00a nm 05/31/12 Updated the driver for CR 660835 so that input length for
|
||
* source/destination to the XDcfg_InitiateDma, XDcfg_Transfer
|
||
* APIs is words (32 bit) and not bytes.
|
||
* Updated the notes for XDcfg_InitiateDma/XDcfg_Transfer APIs
|
||
* to add information that 2 LSBs of the Source/Destination
|
||
* address when equal to 2<>b01 indicate the last DMA command
|
||
* of an overall transfer.
|
||
* Updated the XDcfg_Transfer function to use the
|
||
* Destination Address passed to this API for secure transfers
|
||
* instead of using 0xFFFFFFFF for CR 662197. This issue was
|
||
* resulting in the failure of secure transfers of
|
||
* non-bitstream images.
|
||
* 2.01a nm 08/27/12 Updated the XDcfg_Transfer API to clear the
|
||
* QUARTER_PCAP_RATE_EN bit in the control register for
|
||
* non secure writes for CR 675543.
|
||
* 2.02a nm 01/31/13 Fixed CR# 679335.
|
||
* Added Setting and Clearing the internal PCAP loopback.
|
||
* Removed code for enabling/disabling AES engine as BootROM
|
||
* locks down this setting.
|
||
* Fixed CR# 681976.
|
||
* Skip Checking the PCFG_INIT in case of non-secure DMA
|
||
* loopback.
|
||
* Fixed CR# 699558.
|
||
* XDcfg_Transfer fails to transfer data in loopback mode.
|
||
* 2.03a nm 04/19/13 Fixed CR# 703728.
|
||
* Updated the register definitions as per the latest TRM
|
||
* version UG585 (v1.4) November 16, 2012.
|
||
* 3.0 kpc 21/02/14 Implemented new function XDcfg_ClearControlRegister
|
||
* 3.2 sb 08/25/14 Fixed XDcfg_PcapReadback() function
|
||
* updated driver code with != instead of ==,
|
||
* while checking for Interrupt Status with DMA and
|
||
* PCAP Done Mask
|
||
* ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
* XDCFG_INT_STS_OFFSET) &
|
||
* XDCFG_IXR_D_P_DONE_MASK) !=
|
||
* XDCFG_IXR_D_P_DONE_MASK);
|
||
*
|
||
*
|
||
* </pre>
|
||
*
|
||
******************************************************************************/
|
||
|
||
/***************************** Include Files *********************************/
|
||
|
||
#include "xdevcfg.h"
|
||
|
||
/************************** Constant Definitions *****************************/
|
||
|
||
/**************************** Type Definitions *******************************/
|
||
|
||
/***************** Macros (Inline Functions) Definitions *********************/
|
||
|
||
/************************** Function Prototypes ******************************/
|
||
|
||
/************************** Variable Definitions *****************************/
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* Initialize the Device Config Interface driver. This function
|
||
* must be called before other functions of the driver are called.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
* @param ConfigPtr is the config structure.
|
||
* @param EffectiveAddress is the base address for the device. It could be
|
||
* a virtual address if address translation is supported in the
|
||
* system, otherwise it is the physical address.
|
||
*
|
||
* @return
|
||
* - XST_SUCCESS if initialization was successful.
|
||
* - XST_DEVICE_IS_STARTED if the device has already been started.
|
||
*
|
||
* @note The very first APB access to the Device Configuration Interface
|
||
* block needs to be a write to the UNLOCK register with the value
|
||
* of 0x757BDF0D. This step is to be done once after reset, any
|
||
* other APB access has to come after this. The APB access is
|
||
* considered illegal if the step is not done or if it is done
|
||
* incorrectly. Furthermore, if any of efuse_sec_cfg[5:0] is high,
|
||
* the following additional actions would be carried out.
|
||
* In other words, if all bits are low, the following steps are not
|
||
* done.
|
||
* 1. AES is disabled
|
||
* 2. All APB writes disabled
|
||
* 3. SoC debug fully enabled
|
||
*
|
||
******************************************************************************/
|
||
int XDcfg_CfgInitialize(XDcfg *InstancePtr,
|
||
XDcfg_Config *ConfigPtr, u32 EffectiveAddress)
|
||
{
|
||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||
Xil_AssertNonvoid(ConfigPtr != NULL);
|
||
|
||
/*
|
||
* If the device is started, disallow the initialize and return a
|
||
* status indicating it is started. This allows the user to stop the
|
||
* device and reinitialize, but prevents a user from inadvertently
|
||
* initializing.
|
||
*/
|
||
if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
|
||
return XST_DEVICE_IS_STARTED;
|
||
}
|
||
|
||
/*
|
||
* Copy configuration into instance.
|
||
*/
|
||
InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
|
||
|
||
/*
|
||
* Save the base address pointer such that the registers of the block
|
||
* can be accessed and indicate it has not been started yet.
|
||
*/
|
||
InstancePtr->Config.BaseAddr = EffectiveAddress;
|
||
InstancePtr->IsStarted = 0;
|
||
|
||
|
||
/* Unlock the Device Configuration Interface */
|
||
XDcfg_Unlock(InstancePtr);
|
||
|
||
/*
|
||
* Indicate the instance is ready to use, successfully initialized.
|
||
*/
|
||
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
|
||
|
||
return XST_SUCCESS;
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The functions enables the PCAP interface by setting the PCAP mode bit in the
|
||
* control register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
*
|
||
* @return None.
|
||
*
|
||
* @note Enable FPGA programming from PCAP interface. Enabling this bit
|
||
* disables all the external interfaces from programming of FPGA
|
||
* except for ICAP. The user needs to ensure that the FPGA is
|
||
* programmed through either PCAP or ICAP.
|
||
*
|
||
*****************************************************************************/
|
||
void XDcfg_EnablePCAP(XDcfg *InstancePtr)
|
||
{
|
||
u32 CtrlReg;
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertVoid(InstancePtr != NULL);
|
||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
|
||
CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_CTRL_OFFSET);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,
|
||
(CtrlReg | XDCFG_CTRL_PCAP_MODE_MASK));
|
||
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The functions disables the PCAP interface by clearing the PCAP mode bit in
|
||
* the control register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
*
|
||
* @return None.
|
||
*
|
||
* @note None.
|
||
*
|
||
*****************************************************************************/
|
||
void XDcfg_DisablePCAP(XDcfg *InstancePtr)
|
||
{
|
||
u32 CtrlReg;
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertVoid(InstancePtr != NULL);
|
||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
|
||
CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_CTRL_OFFSET);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,
|
||
(CtrlReg & ( ~XDCFG_CTRL_PCAP_MODE_MASK)));
|
||
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function sets the contents of the Control Register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
* @param Mask is the 32 bit mask data to be written to the Register.
|
||
* The mask definitions are defined in the xdevcfg_hw.h file.
|
||
*
|
||
* @return None.
|
||
*
|
||
* @note None.
|
||
*
|
||
*****************************************************************************/
|
||
void XDcfg_SetControlRegister(XDcfg *InstancePtr, u32 Mask)
|
||
{
|
||
u32 CtrlReg;
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertVoid(InstancePtr != NULL);
|
||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
|
||
CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_CTRL_OFFSET);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,
|
||
(CtrlReg | Mask));
|
||
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function Clears the specified bit positions of the Control Register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
* @param Mask is the 32 bit value which holds the bit positions to be cleared.
|
||
*
|
||
* @return None.
|
||
*
|
||
* @note None.
|
||
*
|
||
*****************************************************************************/
|
||
void XDcfg_ClearControlRegister(XDcfg *InstancePtr, u32 Mask)
|
||
{
|
||
u32 CtrlReg;
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertVoid(InstancePtr != NULL);
|
||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
|
||
CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_CTRL_OFFSET);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,
|
||
(CtrlReg & ~Mask));
|
||
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function reads the contents of the Control Register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
*
|
||
* @return A 32-bit value representing the contents of the Control
|
||
* Register.
|
||
* Use the XDCFG_CTRL_*_MASK constants defined in xdevcfg_hw.h to
|
||
* interpret the returned value.
|
||
*
|
||
* @note None.
|
||
*
|
||
*****************************************************************************/
|
||
u32 XDcfg_GetControlRegister(XDcfg *InstancePtr)
|
||
{
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
/*
|
||
* Read the Control Register and return the value.
|
||
*/
|
||
return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_CTRL_OFFSET);
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function sets the contents of the Lock Register. These bits
|
||
* can only be set to a 1. They will be cleared after a Power On Reset.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
* @param Data is the 32 bit data to be written to the Register.
|
||
*
|
||
* @return None.
|
||
*
|
||
* @note None.
|
||
*
|
||
*****************************************************************************/
|
||
void XDcfg_SetLockRegister(XDcfg *InstancePtr, u32 Data)
|
||
{
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertVoid(InstancePtr != NULL);
|
||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_LOCK_OFFSET, Data);
|
||
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function reads the contents of the Lock Register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
*
|
||
* @return A 32-bit value representing the contents of the Lock
|
||
* Register.
|
||
* Use the XDCFG_CR_*_MASK constants defined in xdevcfg_hw.h to
|
||
* interpret the returned value.
|
||
*
|
||
* @note None.
|
||
*
|
||
*****************************************************************************/
|
||
u32 XDcfg_GetLockRegister(XDcfg *InstancePtr)
|
||
{
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
/*
|
||
* Read the Lock Register and return the value.
|
||
*/
|
||
return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_LOCK_OFFSET);
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function sets the contents of the Configuration Register with the
|
||
* given value.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
* @param Data is the 32 bit data to be written to the Register.
|
||
*
|
||
* @return None.
|
||
*
|
||
* @note None.
|
||
*
|
||
*****************************************************************************/
|
||
void XDcfg_SetConfigRegister(XDcfg *InstancePtr, u32 Data)
|
||
{
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertVoid(InstancePtr != NULL);
|
||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_CFG_OFFSET, Data);
|
||
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function reads the contents of the Configuration Register with the
|
||
* given value.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
*
|
||
* @return A 32-bit value representing the contents of the Config
|
||
* Register.
|
||
* Use the XDCFG_CFG_*_MASK constants defined in xdevcfg_hw.h to
|
||
* interpret the returned value.
|
||
*
|
||
* @note None.
|
||
*
|
||
*****************************************************************************/
|
||
u32 XDcfg_GetConfigRegister(XDcfg *InstancePtr)
|
||
{
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_CFG_OFFSET);
|
||
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function sets the contents of the Status Register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
* @param Data is the 32 bit data to be written to the Register.
|
||
*
|
||
* @return None.
|
||
*
|
||
* @note None.
|
||
*
|
||
*****************************************************************************/
|
||
void XDcfg_SetStatusRegister(XDcfg *InstancePtr, u32 Data)
|
||
{
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertVoid(InstancePtr != NULL);
|
||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET, Data);
|
||
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function reads the contents of the Status Register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
*
|
||
* @return A 32-bit value representing the contents of the Status
|
||
* Register.
|
||
* Use the XDCFG_STATUS_*_MASK constants defined in
|
||
* xdevcfg_hw.h to interpret the returned value.
|
||
*
|
||
* @note None.
|
||
*
|
||
*****************************************************************************/
|
||
u32 XDcfg_GetStatusRegister(XDcfg *InstancePtr)
|
||
{
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
/*
|
||
* Read the Status Register and return the value.
|
||
*/
|
||
return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET);
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function sets the contents of the ROM Shadow Control Register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
* @param Data is the 32 bit data to be written to the Register.
|
||
*
|
||
* @return None.
|
||
*
|
||
* @note This register is can only be written and is used to control the
|
||
* RAM shadow of 32 bit 4K page ROM pages in user mode
|
||
*
|
||
*****************************************************************************/
|
||
void XDcfg_SetRomShadowRegister(XDcfg *InstancePtr, u32 Data)
|
||
{
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertVoid(InstancePtr != NULL);
|
||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_ROM_SHADOW_OFFSET,
|
||
Data);
|
||
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function reads the contents of the Software ID Register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
*
|
||
* @return 32 Bit boot software ID.
|
||
*
|
||
* @note This register is locked for write once the system enters
|
||
* usermode. Hence API for reading the register only is provided.
|
||
*
|
||
*****************************************************************************/
|
||
u32 XDcfg_GetSoftwareIdRegister(XDcfg *InstancePtr)
|
||
{
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
/*
|
||
* Read the Software ID Register and return the value.
|
||
*/
|
||
return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_SW_ID_OFFSET);
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function sets the bit mask for the feature in Miscellaneous Control
|
||
* Register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
* @param Mask is the bit-mask of the feature to be set.
|
||
*
|
||
* @return None.
|
||
*
|
||
* @note None
|
||
*
|
||
*****************************************************************************/
|
||
void XDcfg_SetMiscControlRegister(XDcfg *InstancePtr, u32 Mask)
|
||
{
|
||
u32 RegData;
|
||
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertVoid(InstancePtr != NULL);
|
||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
|
||
RegData = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_MCTRL_OFFSET);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr, XDCFG_MCTRL_OFFSET,
|
||
(RegData | Mask));
|
||
}
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* The function reads the contents of the Miscellaneous Control Register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
*
|
||
* @return 32 Bit boot software ID.
|
||
*
|
||
* @note This register is locked for write once the system enters
|
||
* usermode. Hence API to reading the register only is provided.
|
||
*
|
||
*****************************************************************************/
|
||
u32 XDcfg_GetMiscControlRegister(XDcfg *InstancePtr)
|
||
{
|
||
/*
|
||
* Assert the arguments.
|
||
*/
|
||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
/*
|
||
* Read the Miscellaneous Control Register and return the value.
|
||
*/
|
||
return XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_MCTRL_OFFSET);
|
||
}
|
||
|
||
/******************************************************************************/
|
||
/**
|
||
*
|
||
* This function checks if DMA command queue is full.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
*
|
||
* @return XST_SUCCESS is the DMA is busy
|
||
* XST_FAILURE if the DMA is idle
|
||
*
|
||
* @note The DMA queue has a depth of two.
|
||
*
|
||
****************************************************************************/
|
||
u32 XDcfg_IsDmaBusy(XDcfg *InstancePtr)
|
||
{
|
||
|
||
u32 RegData;
|
||
|
||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
/* Read the PCAP status register for DMA status */
|
||
RegData = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_STATUS_OFFSET);
|
||
|
||
if ((RegData & XDCFG_STATUS_DMA_CMD_Q_F_MASK) ==
|
||
XDCFG_STATUS_DMA_CMD_Q_F_MASK){
|
||
return XST_SUCCESS;
|
||
}
|
||
|
||
return XST_FAILURE;
|
||
}
|
||
|
||
/******************************************************************************/
|
||
/**
|
||
*
|
||
* This function initiates the DMA transfer.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
* @param SourcePtr contains a pointer to the source memory where the data
|
||
* is to be transferred from.
|
||
* @param SrcWordLength is the number of words (32 bit) to be transferred
|
||
* for the source transfer.
|
||
* @param DestPtr contains a pointer to the destination memory
|
||
* where the data is to be transferred to.
|
||
* @param DestWordLength is the number of words (32 bit) to be transferred
|
||
* for the Destination transfer.
|
||
*
|
||
* @return None.
|
||
*
|
||
* @note It is the responsibility of the caller function to ensure that
|
||
* correct values are passed to this function.
|
||
*
|
||
* The 2 LSBs of the SourcePtr (Source)/ DestPtr (Destination)
|
||
* address when equal to 2<>b01 indicates the last DMA command of
|
||
* an overall transfer.
|
||
*
|
||
****************************************************************************/
|
||
void XDcfg_InitiateDma(XDcfg *InstancePtr, u32 SourcePtr, u32 DestPtr,
|
||
u32 SrcWordLength, u32 DestWordLength)
|
||
{
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_DMA_SRC_ADDR_OFFSET,
|
||
SourcePtr);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_DMA_DEST_ADDR_OFFSET,
|
||
DestPtr);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_DMA_SRC_LEN_OFFSET,
|
||
SrcWordLength);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_DMA_DEST_LEN_OFFSET,
|
||
DestWordLength);
|
||
}
|
||
|
||
/******************************************************************************/
|
||
/**
|
||
*
|
||
* This function Implements the DMA Read Command. This command is used to
|
||
* transfer the image data from FPGA to the external memory.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
* @param SourcePtr contains a pointer to the source memory where the data
|
||
* is to be transferred from.
|
||
* @param SrcWordLength is the number of words (32 bit) to be transferred
|
||
* for the source transfer.
|
||
* @param DestPtr contains a pointer to the destination memory
|
||
* where the data is to be transferred to.
|
||
* @param DestWordLength is the number of words (32 bit) to be transferred
|
||
* for the Destination transfer.
|
||
*
|
||
* @return - XST_INVALID_PARAM if source address/length is invalid.
|
||
* - XST_SUCCESS if DMA transfer initiated properly.
|
||
*
|
||
* @note None.
|
||
*
|
||
****************************************************************************/
|
||
static u32 XDcfg_PcapReadback(XDcfg *InstancePtr, u32 SourcePtr,
|
||
u32 SrcWordLength, u32 DestPtr,
|
||
u32 DestWordLength)
|
||
{
|
||
u32 IntrReg;
|
||
|
||
/*
|
||
* Send READ Frame command to FPGA
|
||
*/
|
||
XDcfg_InitiateDma(InstancePtr, SourcePtr, XDCFG_DMA_INVALID_ADDRESS,
|
||
SrcWordLength, 0);
|
||
|
||
/*
|
||
* Store the enabled interrupts to enable before the actual read
|
||
* transfer is initiated and Disable all the interrupts temporarily.
|
||
*/
|
||
IntrReg = XDcfg_IntrGetEnabled(InstancePtr);
|
||
XDcfg_IntrDisable(InstancePtr, XDCFG_IXR_ALL_MASK);
|
||
|
||
/*
|
||
* Wait till you get the DMA done for the read command sent
|
||
*/
|
||
while ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_INT_STS_OFFSET) &
|
||
XDCFG_IXR_D_P_DONE_MASK) !=
|
||
XDCFG_IXR_D_P_DONE_MASK);
|
||
/*
|
||
* Enable the previously stored Interrupts .
|
||
*/
|
||
XDcfg_IntrEnable(InstancePtr, IntrReg);
|
||
|
||
/*
|
||
* Initiate the DMA write command.
|
||
*/
|
||
XDcfg_InitiateDma(InstancePtr, XDCFG_DMA_INVALID_ADDRESS, (u32)DestPtr,
|
||
0, DestWordLength);
|
||
|
||
return XST_SUCCESS;
|
||
}
|
||
|
||
|
||
/****************************************************************************/
|
||
/**
|
||
*
|
||
* This function starts the DMA transfer. This function only starts the
|
||
* operation and returns before the operation may be completed.
|
||
* If the interrupt is enabled, an interrupt will be generated when the
|
||
* operation is completed, otherwise it is necessary to poll the Status register
|
||
* to determine when it is completed. It is the responsibility of the caller to
|
||
* determine when the operation is completed by handling the generated interrupt
|
||
* or polling the Status Register.
|
||
*
|
||
* @param InstancePtr is a pointer to the XDcfg instance.
|
||
* @param SourcePtr contains a pointer to the source memory where the data
|
||
* is to be transferred from.
|
||
* @param SrcWordLength is the number of words (32 bit) to be transferred
|
||
* for the source transfer.
|
||
* @param DestPtr contains a pointer to the destination memory
|
||
* where the data is to be transferred to.
|
||
* @param DestWordLength is the number of words (32 bit) to be transferred
|
||
* for the Destination transfer.
|
||
* @param TransferType contains the type of PCAP transfer being requested.
|
||
* The definitions can be found in the xdevcfg.h file.
|
||
* @return
|
||
* - XST_SUCCESS.if DMA transfer initiated successfully
|
||
* - XST_DEVICE_BUSY if DMA is busy
|
||
* - XST_INVALID_PARAM if invalid Source / Destination address
|
||
* is sent or an invalid Source / Destination length is
|
||
* sent
|
||
*
|
||
* @note It is the responsibility of the caller to ensure that the cache
|
||
* is flushed and invalidated both before the DMA operation is
|
||
* started and after the DMA operation completes if the memory
|
||
* pointed to is cached. The caller must also ensure that the
|
||
* pointers contain physical address rather than a virtual address
|
||
* if address translation is being used.
|
||
*
|
||
* The 2 LSBs of the SourcePtr (Source)/ DestPtr (Destination)
|
||
* address when equal to 2<>b01 indicates the last DMA command of
|
||
* an overall transfer.
|
||
*
|
||
*****************************************************************************/
|
||
u32 XDcfg_Transfer(XDcfg *InstancePtr,
|
||
void *SourcePtr, u32 SrcWordLength,
|
||
void *DestPtr, u32 DestWordLength,
|
||
u32 TransferType)
|
||
{
|
||
|
||
u32 CtrlReg;
|
||
|
||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||
|
||
|
||
if (XDcfg_IsDmaBusy(InstancePtr) == XST_SUCCESS) {
|
||
return XST_DEVICE_BUSY;
|
||
}
|
||
|
||
/*
|
||
* Check whether the fabric is in initialized state
|
||
*/
|
||
if ((XDcfg_ReadReg(InstancePtr->Config.BaseAddr, XDCFG_STATUS_OFFSET)
|
||
& XDCFG_STATUS_PCFG_INIT_MASK) == 0) {
|
||
/*
|
||
* We don't need to check PCFG_INIT to be high for
|
||
* non-encrypted loopback transfers.
|
||
*/
|
||
if (TransferType != XDCFG_CONCURRENT_NONSEC_READ_WRITE) {
|
||
return XST_FAILURE;
|
||
}
|
||
}
|
||
|
||
if ((TransferType == XDCFG_SECURE_PCAP_WRITE) ||
|
||
(TransferType == XDCFG_NON_SECURE_PCAP_WRITE)) {
|
||
|
||
/* Check for valid source pointer and length */
|
||
if ((!SourcePtr) || (SrcWordLength == 0)) {
|
||
return XST_INVALID_PARAM;
|
||
}
|
||
|
||
/* Clear internal PCAP loopback */
|
||
CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_MCTRL_OFFSET);
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_MCTRL_OFFSET, (CtrlReg &
|
||
~(XDCFG_MCTRL_PCAP_LPBK_MASK)));
|
||
|
||
if (TransferType == XDCFG_NON_SECURE_PCAP_WRITE) {
|
||
/*
|
||
* Clear QUARTER_PCAP_RATE_EN bit
|
||
* so that the PCAP data is transmitted every clock
|
||
*/
|
||
CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_CTRL_OFFSET);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_CTRL_OFFSET, (CtrlReg &
|
||
~XDCFG_CTRL_PCAP_RATE_EN_MASK));
|
||
|
||
}
|
||
if (TransferType == XDCFG_SECURE_PCAP_WRITE) {
|
||
/*
|
||
* AES engine handles only 8 bit data every clock cycle.
|
||
* Hence, Encrypted PCAP data which is 32 bit data can
|
||
* only be sent in every 4 clock cycles. Set the control
|
||
* register QUARTER_PCAP_RATE_EN bit to achieve this
|
||
* operation.
|
||
*/
|
||
XDcfg_SetControlRegister(InstancePtr,
|
||
XDCFG_CTRL_PCAP_RATE_EN_MASK);
|
||
}
|
||
|
||
XDcfg_InitiateDma(InstancePtr, (u32)SourcePtr,
|
||
(u32)DestPtr, SrcWordLength, DestWordLength);
|
||
|
||
}
|
||
|
||
if (TransferType == XDCFG_PCAP_READBACK) {
|
||
|
||
if ((!DestPtr) || (DestWordLength == 0)) {
|
||
|
||
return XST_INVALID_PARAM;
|
||
}
|
||
|
||
/* Clear internal PCAP loopback */
|
||
CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_MCTRL_OFFSET);
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_MCTRL_OFFSET, (CtrlReg &
|
||
~(XDCFG_MCTRL_PCAP_LPBK_MASK)));
|
||
|
||
/*
|
||
* For PCAP readback of FPGA configuration register or memory,
|
||
* the read command is first sent (written) to the FPGA fabric
|
||
* which responds by returning the required read data. Read data
|
||
* from the FPGA is captured if pcap_radata_v is active.A DMA
|
||
* read transfer is required to obtain the readback command,
|
||
* which is then sent to the FPGA, followed by a DMA write
|
||
* transfer to support this mode of operation.
|
||
*/
|
||
return XDcfg_PcapReadback(InstancePtr,
|
||
(u32)SourcePtr, SrcWordLength,
|
||
(u32)DestPtr, DestWordLength);
|
||
}
|
||
|
||
|
||
if ((TransferType == XDCFG_CONCURRENT_SECURE_READ_WRITE) ||
|
||
(TransferType == XDCFG_CONCURRENT_NONSEC_READ_WRITE)) {
|
||
|
||
if ((!SourcePtr) || (SrcWordLength == 0) ||
|
||
(!DestPtr) || (DestWordLength == 0)) {
|
||
return XST_INVALID_PARAM;
|
||
}
|
||
|
||
if (TransferType == XDCFG_CONCURRENT_NONSEC_READ_WRITE) {
|
||
/* Enable internal PCAP loopback */
|
||
CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_MCTRL_OFFSET);
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_MCTRL_OFFSET, (CtrlReg |
|
||
XDCFG_MCTRL_PCAP_LPBK_MASK));
|
||
|
||
/*
|
||
* Clear QUARTER_PCAP_RATE_EN bit
|
||
* so that the PCAP data is transmitted every clock
|
||
*/
|
||
CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_CTRL_OFFSET);
|
||
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_CTRL_OFFSET, (CtrlReg &
|
||
~XDCFG_CTRL_PCAP_RATE_EN_MASK));
|
||
|
||
}
|
||
if (TransferType == XDCFG_CONCURRENT_SECURE_READ_WRITE) {
|
||
/* Clear internal PCAP loopback */
|
||
CtrlReg = XDcfg_ReadReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_MCTRL_OFFSET);
|
||
XDcfg_WriteReg(InstancePtr->Config.BaseAddr,
|
||
XDCFG_MCTRL_OFFSET, (CtrlReg &
|
||
~(XDCFG_MCTRL_PCAP_LPBK_MASK)));
|
||
|
||
/*
|
||
* Set the QUARTER_PCAP_RATE_EN bit
|
||
* so that the PCAP data is transmitted every 4 clock
|
||
* cycles, this is required for encrypted data.
|
||
*/
|
||
XDcfg_SetControlRegister(InstancePtr,
|
||
XDCFG_CTRL_PCAP_RATE_EN_MASK);
|
||
}
|
||
|
||
XDcfg_InitiateDma(InstancePtr, (u32)SourcePtr,
|
||
(u32)DestPtr, SrcWordLength, DestWordLength);
|
||
}
|
||
|
||
return XST_SUCCESS;
|
||
}
|