Esempio n. 1
0
/**
 * Set the packet waitbound timer for this SGDMA channel. See xdmav2.h for more
 * information on interrupt coalescing and the effects of the waitbound timer.
 *
 * @param InstancePtr is a pointer to the instance to be worked on.
 * @param TimerVal is the waitbound period to set. If 0 is specified, then
 *        this feature is disabled. Maximum waitbound is 2^12 - 1. LSB is
 *        1 millisecond (approx).
 *
 * @return
 * - XST_SUCCESS if waitbound set properly.
 * - XST_NO_FEATURE if the provided instance is a non SGDMA type of DMA
 *   channel.
 ******************************************************************************/
XStatus XDmaV2_SgSetPktWaitbound(XDmaV2 * InstancePtr, u16 TimerVal)
{
	if (!IsSgDmaChannel(InstancePtr)) {
		return (XST_NO_FEATURE);
	}

	XDmaV2_mWriteReg(InstancePtr->RegBase, XDMAV2_PWB_OFFSET,
			 (u32) (TimerVal & XDMAV2_PWB_MASK));

	return (XST_SUCCESS);
}
Esempio n. 2
0
/**
 * Set the packet threshold for this SGDMA channel. This has the effect of
 * delaying processor interrupts until the given number of packets (not BDs)
 * have been processed.
 *
 * @param InstancePtr is a pointer to the instance to be worked on.
 * @param Threshold is the packet threshold to set. If 0 is specified, then
 *        this feature is disabled. Maximum threshold is 2^10 - 1.
 *
 * @return
 * - XST_SUCCESS if threshold set properly.
 * - XST_NO_FEATURE if the provided instance is a non SGDMA type of DMA
 *   channel.
 ******************************************************************************/
XStatus XDmaV2_SgSetPktThreshold(XDmaV2 * InstancePtr, u16 Threshold)
{
	if (!IsSgDmaChannel(InstancePtr)) {
		return (XST_NO_FEATURE);
	}

	XDmaV2_mWriteReg(InstancePtr->RegBase, XDMAV2_PCT_OFFSET,
			 (u32) (Threshold & XDMAV2_PCT_MASK));

	return (XST_SUCCESS);
}
Esempio n. 3
0
/**
 * Get the waitbound timer for this channel that was set with
 * XDmaV2_SgSetPktWaitbound().
 *
 * @param InstancePtr is a pointer to the instance to be worked on.
 *
 * @return Current waitbound timer as reported by HW. If the channel is not of
 *         SGDMA type then the return value is 0.
 ******************************************************************************/
u16 XDmaV2_SgGetPktWaitbound(XDmaV2 * InstancePtr)
{
	u32 Reg;

	if (!IsSgDmaChannel(InstancePtr)) {
		return (0);
	}

	Reg = XDmaV2_mReadReg(InstancePtr->RegBase, XDMAV2_PWB_OFFSET);
	Reg &= XDMAV2_PWB_MASK;
	return ((u16) Reg);
}
Esempio n. 4
0
/**
 * Get the waitbound timer for this channel that was set with
 * XDmaV3_SgSetPktWaitbound().
 *
 * @param InstancePtr is a pointer to the instance to be worked on.
 *
 * @return Current waitbound timer as reported by HW. If the channel does not
 *         include interrupt coalescing, then the return value will always be 0.
 ******************************************************************************/
u16 XDmaV3_SgGetPktWaitbound(XDmaV3 * InstancePtr)
{
	u32 Reg;

	/* Is this a SGDMA channel */
	Reg = XDmaV3_mReadReg(InstancePtr->RegBase, XDMAV3_DMASR_OFFSET);
	if (!IsSgDmaChannel(InstancePtr)) {
		return (0);
	}

	/* Get the threshold */
	Reg = XDmaV3_mReadReg(InstancePtr->RegBase, XDMAV3_SWCR_OFFSET);
	Reg &= XDMAV3_SWCR_PWB_MASK;
	Reg >>= XDMAV3_SWCR_PWB_SHIFT;
	return ((u16) Reg);
}
Esempio n. 5
0
/**
 * Set the packet waitbound timer for this SGDMA channel. See xdmav3.h for more
 * information on interrupt coalescing and the effects of the waitbound timer.
 *
 * @param InstancePtr is a pointer to the instance to be worked on.
 * @param TimerVal is the waitbound period to set. If 0 is specified, then
 *        this feature is disabled. Maximum waitbound is 2^12 - 1. LSB is
 *        1 millisecond (approx).
 *
 * @return
 * - XST_SUCCESS if waitbound set properly.
 * - XST_NO_FEATURE if this function was called on a DMA channel that does not
 *   have interrupt coalescing capabilities.
 *
 * @note This function should not be prempted by another XDmaV3 function.
 *
 ******************************************************************************/
int XDmaV3_SgSetPktWaitbound(XDmaV3 * InstancePtr, u16 TimerVal)
{
	u32 Reg;

	/* Is this a SGDMA channel */
	Reg = XDmaV3_mReadReg(InstancePtr->RegBase, XDMAV3_DMASR_OFFSET);
	if (!IsSgDmaChannel(InstancePtr)) {
		return (XST_NO_FEATURE);
	}

	/* Replace the waitbound field in the SWCR */
	Reg = XDmaV3_mReadReg(InstancePtr->RegBase, XDMAV3_SWCR_OFFSET);
	Reg &= ~XDMAV3_SWCR_PWB_MASK;
	Reg |= ((TimerVal << XDMAV3_SWCR_PWB_SHIFT) & XDMAV3_SWCR_PWB_MASK);
	XDmaV3_mWriteReg(InstancePtr->RegBase, XDMAV3_SWCR_OFFSET, Reg);

	/* Finished */
	return (XST_SUCCESS);
}
Esempio n. 6
0
/**
 * Using a memory segment allocated by the caller, create and setup the BD list
 * for the given SGDMA channel.
 *
 * @param InstancePtr is the instance to be worked on.
 * @param PhysAddr is the physical base address of user memory region.
 * @param VirtAddr is the virtual base address of the user memory region. If
 *        address translation is not being utilized, then VirtAddr should be
 *        equivalent to PhysAddr.
 * @param Alignment governs the byte alignment of individual BDs. This function
 *        will enforce a minimum alignment of 4 bytes with no maximum as long as
 *        it is specified as a power of 2.
 * @param BdCount is the number of BDs to setup in the user memory region. It is
 *        assumed the region is large enough to contain the BDs. Refer to the
 *        "SGDMA List Creation" section  in xdmav2.h for more information on list
 *        creation.
 *
 * @return
 *
 * - XST_SUCCESS if initialization was successful
 * - XST_NO_FEATURE if the provided instance is a non SGDMA type of DMA
 *   channel.
 * - XST_INVALID_PARAM under any of the following conditions: 1) PhysAddr and/or
 *   VirtAddr are not aligned to the given Alignment parameter; 2) Alignment
 *   parameter does not meet minimum requirements or is not a power of 2 value;
 *   3) BdCount is 0.
 * - XST_DMA_SG_LIST_ERROR if the memory segment containing the list spans
 *   over address 0x00000000 in virtual address space.
 *
 * @note
 *
 * Some DMA HW requires 8 or more byte alignments of BDs. Make sure the correct
 * value is passed into the Alignment parameter to meet individual DMA HW
 * requirements.
 *
 ******************************************************************************/
XStatus XDmaV2_SgListCreate(XDmaV2 * InstancePtr, u32 PhysAddr, u32 VirtAddr,
			    u32 Alignment, unsigned BdCount)
{
	int i;
	u32 BdV;
	u32 BdP;
	XDmaV2_BdRing *Ring = &InstancePtr->BdRing;
	u32 Upc;

	/* In case there is a failure prior to creating list, make sure the following
	 * attributes are 0 to prevent calls to other SG functions from doing anything
	 */
	Ring->AllCnt = 0;
	Ring->FreeCnt = 0;
	Ring->HwCnt = 0;
	Ring->PreCnt = 0;
	Ring->PostCnt = 0;

	/* Is this a SGDMA channel */
	if (!IsSgDmaChannel(InstancePtr)) {
		return (XST_NO_FEATURE);
	}

	/* Make sure Alignment parameter meets minimum requirements */
	if (Alignment < XDMABD_MINIMUM_ALIGNMENT) {
		return (XST_INVALID_PARAM);
	}

	/* Make sure Alignment is a power of 2 */
	if ((Alignment - 1) & Alignment) {
		return (XST_INVALID_PARAM);
	}

	/* Make sure PhysAddr and VirtAddr are on same Alignment */
	if ((PhysAddr % Alignment) || (VirtAddr % Alignment)) {
		return (XST_INVALID_PARAM);
	}

	/* Is BdCount is reasonable? */
	if (BdCount == 0) {
		return (XST_INVALID_PARAM);
	}

	/* Calculate the number of bytes between the start of adjacent BDs */
	Ring->Separation =
	    (sizeof(XDmaBdV2) + (Alignment - 1)) & ~(Alignment - 1);

	/* Must make sure the ring doesn't span across address 0x00000000.
	 * The design will fail if this occurs.
	 */
	if (VirtAddr > (VirtAddr + (Ring->Separation * BdCount))) {
		return (XST_DMA_SG_LIST_ERROR);
	}

	/* Initial ring setup:
	 *  - Clear the entire space
	 *  - Lay out the BDA fields the HW follows as it processes BDs
	 */
	memset((void *)VirtAddr, 0, (Ring->Separation * BdCount));

	BdV = VirtAddr;
	BdP = PhysAddr + Ring->Separation;
	for (i = 1; i < BdCount; i++) {
		XDmaV2_mWriteBd(BdV, XDMAV2_BD_BDA_OFFSET, BdP);
		BdV += Ring->Separation;
		BdP += Ring->Separation;
	}

	/* At the end of the ring, link the last BD back to the top */
	XDmaV2_mWriteBd(BdV, XDMAV2_BD_BDA_OFFSET, PhysAddr);

	/* Setup and initialize pointers and counters */
	InstancePtr->BdRing.RunState = XST_DMA_SG_IS_STOPPED;
	Ring->BaseAddr = VirtAddr;
	Ring->PhysBaseAddr = PhysAddr;
	Ring->TO = VirtAddr - PhysAddr;
	Ring->HighAddr = BdV;
	Ring->Length = Ring->HighAddr - Ring->BaseAddr + Ring->Separation;
	Ring->AllCnt = BdCount;
	Ring->FreeCnt = BdCount;
	Ring->FreeHead = (XDmaBdV2 *) VirtAddr;
	Ring->PreHead = (XDmaBdV2 *) VirtAddr;
	Ring->HwHead = (XDmaBdV2 *) VirtAddr;
	Ring->HwTail = (XDmaBdV2 *) VirtAddr;
	Ring->PostHead = (XDmaBdV2 *) VirtAddr;

	/* Sync HW with the beginning of the ring */

	XDmaV2_mWriteReg(InstancePtr->RegBase, XDMAV2_BDA_OFFSET, PhysAddr);
	/* Make sure the DMACR.SGS is 1 so that no DMA operations proceed until
	 * the start function is called.
	 */
	XDMAV2_HW_SGS_SET;

	/* As a final purging of any previous BD ring, make sure the UPC register
	 * has been cleared to 0.
	 */
	Upc = XDmaV2_mReadReg(InstancePtr->RegBase, XDMAV2_UPC_OFFSET);
	for (i = 0; i < Upc; i++) {
		XDmaV2_mWriteReg(InstancePtr->RegBase, XDMAV2_UPC_OFFSET, 1);
	}

	return (XST_SUCCESS);
}
Esempio n. 7
0
/**
 * Using a memory segment allocated by the caller, create and setup the BD list
 * for the given SGDMA channel.
 *
 * @param InstancePtr is the instance to be worked on.
 * @param PhysAddr is the physical base address of user memory region.
 * @param VirtAddr is the virtual base address of the user memory region. If
 *        address translation is not being utilized, then VirtAddr should be
 *        equivalent to PhysAddr.
 * @param Alignment governs the byte alignment of individual BDs. This function
 *        will enforce a minimum alignment of 4 bytes with no maximum as long as
 *        it is specified as a power of 2.
 * @param BdCount is the number of BDs to setup in the user memory region. It is
 *        assumed the region is large enough to contain the BDs. Refer to the
 *        "SGDMA List Creation" section  in xdmav3.h for more information on
 *        list creation.
 *
 * @return
 *
 * - XST_SUCCESS if initialization was successful
 * - XST_NO_FEATURE if the provided instance is a non SGDMA type of DMA
 *   channel.
 * - XST_INVALID_PARAM under any of the following conditions: 1) PhysAddr and/or
 *   VirtAddr are not aligned to the given Alignment parameter; 2) Alignment
 *   parameter does not meet minimum requirements or is not a power of 2 value;
 *   3) BdCount is 0.
 * - XST_DMA_SG_LIST_ERROR if the memory segment containing the list spans
 *   over address 0x00000000 in virtual address space.
 *
 * @note
 *
 * Some DMA HW requires 8 or more byte alignments of BDs. Make sure the correct
 * value is passed into the Alignment parameter to meet individual DMA HW
 * requirements.
 *
 ******************************************************************************/
int XDmaV3_SgListCreate(XDmaV3 * InstancePtr, u32 PhysAddr, u32 VirtAddr,
			u32 Alignment, unsigned BdCount)
{
	unsigned i;
	u32 BdV;
	u32 BdP;
	XDmaV3_BdRing *Ring = &InstancePtr->BdRing;

	/* In case there is a failure prior to creating list, make sure the following
	 * attributes are 0 to prevent calls to other SG functions from doing anything
	 */
	Ring->AllCnt = 0;
	Ring->FreeCnt = 0;
	Ring->HwCnt = 0;
	Ring->PreCnt = 0;
	Ring->PostCnt = 0;

	/* Is this a SGDMA channel */
	if (!IsSgDmaChannel(InstancePtr)) {
		return (XST_NO_FEATURE);
	}

	/* Make sure Alignment parameter meets minimum requirements */
	if (Alignment < XDMABDV3_MINIMUM_ALIGNMENT) {
		return (XST_INVALID_PARAM);
	}

	/* Make sure Alignment is a power of 2 */
	if ((Alignment - 1) & Alignment) {
		return (XST_INVALID_PARAM);
	}

	/* Make sure PhysAddr and VirtAddr are on same Alignment */
	if ((PhysAddr % Alignment) || (VirtAddr % Alignment)) {
		return (XST_INVALID_PARAM);
	}

	/* Is BdCount reasonable? */
	if (BdCount == 0) {
		return (XST_INVALID_PARAM);
	}

	/* Parameters are sane. Stop the HW just to be safe */
	XDmaV3_SgStop(InstancePtr);

	/* Figure out how many bytes will be between the start of adjacent BDs */
	Ring->Separation =
		(sizeof(XDmaBdV3) + (Alignment - 1)) & ~(Alignment - 1);

	/* Must make sure the ring doesn't span address 0x00000000. If it does,
	 * then the next/prev BD traversal macros will fail.
	 */
	if (VirtAddr > (VirtAddr + (Ring->Separation * BdCount) - 1)) {
		return (XST_DMA_SG_LIST_ERROR);
	}

	/* Initial ring setup:
	 *  - Clear the entire space
	 *  - Setup each BD's BDA field with the physical address of the next BD
	 *  - Set each BD's DMASR.DMADONE bit
	 */
	memset((void *) VirtAddr, 0, (Ring->Separation * BdCount));

	BdV = VirtAddr;
	BdP = PhysAddr + Ring->Separation;
	for (i = 1; i < BdCount; i++) {
		XDmaV3_mWriteBd(BdV, XDMAV3_BD_BDA_OFFSET, BdP);
		XDmaV3_mWriteBd(BdV, XDMAV3_BD_DMASR_OFFSET,
				XDMAV3_DMASR_DMADONE_MASK);
		XDMAV3_CACHE_FLUSH(BdV);
		BdV += Ring->Separation;
		BdP += Ring->Separation;
	}

	/* At the end of the ring, link the last BD back to the top */
	XDmaV3_mWriteBd(BdV, XDMAV3_BD_BDA_OFFSET, PhysAddr);

	/* Setup and initialize pointers and counters */
	InstancePtr->BdRing.RunState = XST_DMA_SG_IS_STOPPED;
	Ring->BaseAddr = VirtAddr;
	Ring->PhysBaseAddr = PhysAddr;
	Ring->HighAddr = BdV;
	Ring->Length = Ring->HighAddr - Ring->BaseAddr + Ring->Separation;
	Ring->AllCnt = BdCount;
	Ring->FreeCnt = BdCount;
	Ring->FreeHead = (XDmaBdV3 *) VirtAddr;
	Ring->PreHead = (XDmaBdV3 *) VirtAddr;
	Ring->HwHead = (XDmaBdV3 *) VirtAddr;
	Ring->HwTail = (XDmaBdV3 *) VirtAddr;
	Ring->PostHead = (XDmaBdV3 *) VirtAddr;
	Ring->BdaRestart = (XDmaBdV3 *) PhysAddr;

	/* Make sure the DMACR.SGS is 1 so that no DMA operations proceed until
	 * the start function is called.
	 */
	XDMAV3_HW_SGS_SET;

	return (XST_SUCCESS);
}