diff options
Diffstat (limited to 'board/xilinx/common/xdma_channel.c')
| -rw-r--r-- | board/xilinx/common/xdma_channel.c | 738 | 
1 files changed, 738 insertions, 0 deletions
| diff --git a/board/xilinx/common/xdma_channel.c b/board/xilinx/common/xdma_channel.c new file mode 100644 index 000000000..25f1e2602 --- /dev/null +++ b/board/xilinx/common/xdma_channel.c @@ -0,0 +1,738 @@ +/****************************************************************************** +* +*     Author: Xilinx, Inc. +* +* +*     This program is free software; you can redistribute it and/or modify it +*     under the terms of the GNU General Public License as published by the +*     Free Software Foundation; either version 2 of the License, or (at your +*     option) any later version. +* +* +*     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A +*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS +*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD, +*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE +*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING +*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. +*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO +*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY +*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM +*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND +*     FITNESS FOR A PARTICULAR PURPOSE. +* +* +*     Xilinx hardware products are not intended for use in life support +*     appliances, devices, or systems. Use in such applications is +*     expressly prohibited. +* +* +*     (c) Copyright 2002-2004 Xilinx Inc. +*     All rights reserved. +* +* +*     You should have received a copy of the GNU General Public License along +*     with this program; if not, write to the Free Software Foundation, Inc., +*     675 Mass Ave, Cambridge, MA 02139, USA. +* +* FILENAME: +* +* xdma_channel.c +* +* DESCRIPTION: +* +* This file contains the DMA channel component. This component supports +* a distributed DMA design in which each device can have it's own dedicated +* DMA channel, as opposed to a centralized DMA design. This component +* performs processing for DMA on all devices. +* +* See xdma_channel.h for more information about this component. +* +* NOTES: +* +* None. +* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xdma_channel.h" +#include "xbasic_types.h" +#include "xio.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_Initialize +* +* DESCRIPTION: +* +* This function initializes a DMA channel.  This function must be called +* prior to using a DMA channel.  Initialization of a channel includes setting +* up the registers base address, and resetting the channel such that it's in a +* known state.  Interrupts for the channel are disabled when the channel is +* reset. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* BaseAddress contains the base address of the registers for the DMA channel. +* +* RETURN VALUE: +* +* XST_SUCCESS indicating initialization was successful. +* +* NOTES: +* +* None. +* +******************************************************************************/ +XStatus +XDmaChannel_Initialize(XDmaChannel * InstancePtr, u32 BaseAddress) +{ +	/* assert to verify input arguments, don't assert base address */ + +	XASSERT_NONVOID(InstancePtr != NULL); + +	/* setup the base address of the registers for the DMA channel such +	 * that register accesses can be done +	 */ +	InstancePtr->RegBaseAddress = BaseAddress; + +	/* initialize the scatter gather list such that it indicates it has not +	 * been created yet and the DMA channel is ready to use (initialized) +	 */ +	InstancePtr->GetPtr = NULL; +	InstancePtr->PutPtr = NULL; +	InstancePtr->CommitPtr = NULL; +	InstancePtr->LastPtr = NULL; + +	InstancePtr->TotalDescriptorCount = 0; +	InstancePtr->ActiveDescriptorCount = 0; +	InstancePtr->IsReady = XCOMPONENT_IS_READY; + +	/* initialize the version of the component +	 */ +	XVersion_FromString(&InstancePtr->Version, "1.00a"); + +	/* reset the DMA channel such that it's in a known state and ready +	 * and indicate the initialization occured with no errors, note that +	 * the is ready variable must be set before this call or reset will assert +	 */ +	XDmaChannel_Reset(InstancePtr); + +	return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_IsReady +* +* DESCRIPTION: +* +* This function determines if a DMA channel component has been successfully +* initialized such that it's ready to use. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* TRUE if the DMA channel component is ready, FALSE otherwise. +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_IsReady(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments used by the base component */ + +	XASSERT_NONVOID(InstancePtr != NULL); + +	return InstancePtr->IsReady == XCOMPONENT_IS_READY; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetVersion +* +* DESCRIPTION: +* +* This function gets the software version for the specified DMA channel +* component. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* A pointer to the software version of the specified DMA channel. +* +* NOTES: +* +* None. +* +******************************************************************************/ +XVersion * +XDmaChannel_GetVersion(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* return a pointer to the version of the DMA channel */ + +	return &InstancePtr->Version; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SelfTest +* +* DESCRIPTION: +* +* This function performs a self test on the specified DMA channel.  This self +* test is destructive as the DMA channel is reset and a register default is +* verified. +* +* ARGUMENTS: +* +* InstancePtr is a pointer to the DMA channel to be operated on. +* +* RETURN VALUE: +* +* XST_SUCCESS is returned if the self test is successful, or one of the +* following errors. +* +*	XST_DMA_RESET_REGISTER_ERROR 		Indicates the control register value +*										after a reset was not correct +* +* NOTES: +* +* This test does not performs a DMA transfer to test the channel because the +* DMA hardware will not currently allow a non-local memory transfer to non-local +* memory (memory copy), but only allows a non-local memory to or from the device +* memory (typically a FIFO). +* +******************************************************************************/ + +#define XDC_CONTROL_REG_RESET_MASK  0x98000000UL	/* control reg reset value */ + +XStatus +XDmaChannel_SelfTest(XDmaChannel * InstancePtr) +{ +	u32 ControlReg; + +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* reset the DMA channel such that it's in a known state before the test +	 * it resets to no interrupts enabled, the desired state for the test +	 */ +	XDmaChannel_Reset(InstancePtr); + +	/* this should be the first test to help prevent a lock up with the polling +	 * loop that occurs later in the test, check the reset value of the DMA +	 * control register to make sure it's correct, return with an error if not +	 */ +	ControlReg = XDmaChannel_GetControl(InstancePtr); +	if (ControlReg != XDC_CONTROL_REG_RESET_MASK) { +		return XST_DMA_RESET_REGISTER_ERROR; +	} + +	return XST_SUCCESS; +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_Reset +* +* DESCRIPTION: +* +* This function resets the DMA channel. This is a destructive operation such +* that it should not be done while a channel is being used.  If the DMA channel +* is transferring data into other blocks, such as a FIFO, it may be necessary +* to reset other blocks.  This function does not modify the contents of a +* scatter gather list for a DMA channel such that the user is responsible for +* getting buffer descriptors from the list if necessary. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +void +XDmaChannel_Reset(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* reset the DMA channel such that it's in a known state, the reset +	 * register is self clearing such that it only has to be set +	 */ +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_RST_REG_OFFSET, +		  XDC_RESET_MASK); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetControl +* +* DESCRIPTION: +* +* This function gets the control register contents of the DMA channel. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* The control register contents of the DMA channel. One or more of the +* following values may be contained the register.  Each of the values are +* unique bit masks. +* +*	XDC_DMACR_SOURCE_INCR_MASK	Increment the source address +*	XDC_DMACR_DEST_INCR_MASK	Increment the destination address +*	XDC_DMACR_SOURCE_LOCAL_MASK Local source address +*	XDC_DMACR_DEST_LOCAL_MASK	Local destination address +*	XDC_DMACR_SG_ENABLE_MASK	Scatter gather enable +*	XDC_DMACR_GEN_BD_INTR_MASK	Individual buffer descriptor interrupt +*	XDC_DMACR_LAST_BD_MASK		Last buffer descriptor in a packet +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_GetControl(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* return the contents of the DMA control register */ + +	return XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SetControl +* +* DESCRIPTION: +* +* This function sets the control register of the specified DMA channel. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* Control contains the value to be written to the control register of the DMA +* channel. One or more of the following values may be contained the register. +* Each of the values are unique bit masks such that they may be ORed together +* to enable multiple bits or inverted and ANDed to disable multiple bits. +* +*	XDC_DMACR_SOURCE_INCR_MASK	Increment the source address +*	XDC_DMACR_DEST_INCR_MASK	Increment the destination address +*	XDC_DMACR_SOURCE_LOCAL_MASK Local source address +*	XDC_DMACR_DEST_LOCAL_MASK	Local destination address +*	XDC_DMACR_SG_ENABLE_MASK	Scatter gather enable +*	XDC_DMACR_GEN_BD_INTR_MASK	Individual buffer descriptor interrupt +*	XDC_DMACR_LAST_BD_MASK		Last buffer descriptor in a packet +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +void +XDmaChannel_SetControl(XDmaChannel * InstancePtr, u32 Control) +{ +	/* assert to verify input arguments except the control which can't be +	 * asserted since all values are valid +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* set the DMA control register to the specified value */ + +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_DMAC_REG_OFFSET, Control); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetStatus +* +* DESCRIPTION: +* +* This function gets the status register contents of the DMA channel. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* The status register contents of the DMA channel. One or more of the +* following values may be contained the register. Each of the values are +* unique bit masks. +* +*	XDC_DMASR_BUSY_MASK			The DMA channel is busy +*	XDC_DMASR_BUS_ERROR_MASK	A bus error occurred +*	XDC_DMASR_BUS_TIMEOUT_MASK	A bus timeout occurred +*	XDC_DMASR_LAST_BD_MASK		The last buffer descriptor of a packet +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_GetStatus(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* return the contents of the DMA status register */ + +	return XIo_In32(InstancePtr->RegBaseAddress + XDC_DMAS_REG_OFFSET); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SetIntrStatus +* +* DESCRIPTION: +* +* This function sets the interrupt status register of the specified DMA channel. +* Setting any bit of the interrupt status register will clear the bit to +* indicate the interrupt processing has been completed. The definitions of each +* bit in the register match the definition of the bits in the interrupt enable +* register. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* Status contains the value to be written to the status register of the DMA +* channel.  One or more of the following values may be contained the register. +* Each of the values are unique bit masks such that they may be ORed together +* to enable multiple bits or inverted and ANDed to disable multiple bits. +* +*	XDC_IXR_DMA_DONE_MASK		The dma operation is done +*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error +*	XDC_IXR_PKT_DONE_MASK	    A packet is complete +*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached +*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached +*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed +*	XDC_IXR_BD_MASK				A buffer descriptor is done +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +void +XDmaChannel_SetIntrStatus(XDmaChannel * InstancePtr, u32 Status) +{ +	/* assert to verify input arguments except the status which can't be +	 * asserted since all values are valid +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* set the interrupt status register with the specified value such that +	 * all bits which are set in the register are cleared effectively clearing +	 * any active interrupts +	 */ +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET, Status); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetIntrStatus +* +* DESCRIPTION: +* +* This function gets the interrupt status register of the specified DMA channel. +* The interrupt status register indicates which interrupts are active +* for the DMA channel.  If an interrupt is active, the status register must be +* set (written) with the bit set for each interrupt which has been processed +* in order to clear the interrupts.  The definitions of each bit in the register +* match the definition of the bits in the interrupt enable register. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* The interrupt status register contents of the specified DMA channel. +* One or more of the following values may be contained the register. +* Each of the values are unique bit masks. +* +*	XDC_IXR_DMA_DONE_MASK		The dma operation is done +*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error +*	XDC_IXR_PKT_DONE_MASK	    A packet is complete +*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached +*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached +*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed +*	XDC_IXR_SG_END_MASK			Current descriptor was the end of the list +*	XDC_IXR_BD_MASK				A buffer descriptor is done +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_GetIntrStatus(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* return the contents of the interrupt status register */ + +	return XIo_In32(InstancePtr->RegBaseAddress + XDC_IS_REG_OFFSET); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_SetIntrEnable +* +* DESCRIPTION: +* +* This function sets the interrupt enable register of the specified DMA +* channel.  The interrupt enable register contains bits which enable +* individual interrupts for the DMA channel.  The definitions of each bit +* in the register match the definition of the bits in the interrupt status +* register. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* Enable contains the interrupt enable register contents to be written +* in the DMA channel. One or more of the following values may be contained +* the register. Each of the values are unique bit masks such that they may be +* ORed together to enable multiple bits or inverted and ANDed to disable +* multiple bits. +* +*	XDC_IXR_DMA_DONE_MASK		The dma operation is done +*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error +*	XDC_IXR_PKT_DONE_MASK	    A packet is complete +*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached +*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached +*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed +*	XDC_IXR_SG_END_MASK			Current descriptor was the end of the list +*	XDC_IXR_BD_MASK				A buffer descriptor is done +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* None. +* +******************************************************************************/ +void +XDmaChannel_SetIntrEnable(XDmaChannel * InstancePtr, u32 Enable) +{ +	/* assert to verify input arguments except the enable which can't be +	 * asserted since all values are valid +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* set the interrupt enable register to the specified value */ + +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_IE_REG_OFFSET, Enable); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_GetIntrEnable +* +* DESCRIPTION: +* +* This function gets the interrupt enable of the DMA channel.  The +* interrupt enable contains flags which enable individual interrupts for the +* DMA channel. The definitions of each bit in the register match the definition +* of the bits in the interrupt status register. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* RETURN VALUE: +* +* The interrupt enable of the DMA channel.  One or more of the following values +* may be contained the register. Each of the values are unique bit masks. +* +*	XDC_IXR_DMA_DONE_MASK		The dma operation is done +*	XDC_IXR_DMA_ERROR_MASK	    The dma operation had an error +*	XDC_IXR_PKT_DONE_MASK	    A packet is complete +*	XDC_IXR_PKT_THRESHOLD_MASK 	The packet count threshold reached +*	XDC_IXR_PKT_WAIT_BOUND_MASK The packet wait bound reached +*	XDC_IXR_SG_DISABLE_ACK_MASK The scatter gather disable completed +*	XDC_IXR_BD_MASK				A buffer descriptor is done +* +* NOTES: +* +* None. +* +******************************************************************************/ +u32 +XDmaChannel_GetIntrEnable(XDmaChannel * InstancePtr) +{ +	/* assert to verify input arguments */ + +	XASSERT_NONVOID(InstancePtr != NULL); +	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* return the contents of the interrupt enable register */ + +	return XIo_In32(InstancePtr->RegBaseAddress + XDC_IE_REG_OFFSET); +} + +/****************************************************************************** +* +* FUNCTION: +* +* XDmaChannel_Transfer +* +* DESCRIPTION: +* +* This function starts the DMA channel transferring data from a memory source +* to a memory destination. This function only starts the operation and returns +* before the operation may be complete.  If the interrupt is enabled, an +* interrupt will be generated when the operation is complete, otherwise it is +* necessary to poll the channel status to determine when it's complete.  It is +* the responsibility of the caller to determine when the operation is complete +* by handling the generated interrupt or polling the status.  It is also the +* responsibility of the caller to ensure that the DMA channel is not busy with +* another transfer before calling this function. +* +* ARGUMENTS: +* +* InstancePtr contains a pointer to the DMA channel to operate on. +* +* SourcePtr contains a pointer to the source memory where the data is to +* be tranferred from and must be 32 bit aligned. +* +* DestinationPtr contains a pointer to the destination memory where the data +* is to be transferred and must be 32 bit aligned. +* +* ByteCount contains the number of bytes to transfer during the DMA operation. +* +* RETURN VALUE: +* +* None. +* +* NOTES: +* +* The DMA h/w will not currently allow a non-local memory transfer to non-local +* memory (memory copy), but only allows a non-local memory to or from the device +* memory (typically a FIFO). +* +* It is the responsibility of the caller to ensure that the cache is +* flushed and invalidated both before and after the DMA operation completes +* if the memory pointed to is cached. The caller must also ensure that the +* pointers contain a physical address rather than a virtual address +* if address translation is being used. +* +******************************************************************************/ +void +XDmaChannel_Transfer(XDmaChannel * InstancePtr, +		     u32 * SourcePtr, u32 * DestinationPtr, u32 ByteCount) +{ +	/* assert to verify input arguments and the alignment of any arguments +	 * which have expected alignments +	 */ +	XASSERT_VOID(InstancePtr != NULL); +	XASSERT_VOID(SourcePtr != NULL); +	XASSERT_VOID(((u32) SourcePtr & 3) == 0); +	XASSERT_VOID(DestinationPtr != NULL); +	XASSERT_VOID(((u32) DestinationPtr & 3) == 0); +	XASSERT_VOID(ByteCount != 0); +	XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); + +	/* setup the source and destination address registers for the transfer */ + +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_SA_REG_OFFSET, +		  (u32) SourcePtr); + +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_DA_REG_OFFSET, +		  (u32) DestinationPtr); + +	/* start the DMA transfer to copy from the source buffer to the +	 * destination buffer by writing the length to the length register +	 */ +	XIo_Out32(InstancePtr->RegBaseAddress + XDC_LEN_REG_OFFSET, ByteCount); +} |