/****************************************************************************** * * 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. * *
* 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);
*
*
* 
* ******************************************************************************/ /***************************** 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; }