embeddedsw/XilinxProcessorIPLib/drivers/axicdma/src/xaxicdma.h
Jagannadha Sutradharudu Teki 2c8f92039d embeddesw: Add initial code support
Added initial support Xilinx Embedded Software.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
2014-06-24 16:45:01 +05:30

562 lines
22 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 xaxicdma.h
*
* This is the driver API for the AXI CDMA engine.
*
* For a full description of the features of the AXI CDMA engine, please
* refer to the hardware specification. This driver supports the following
* features:
*
* - Simple DMA transfer
* - Scatter gather (SG) DMA transfer
* - Interrupt for error or completion of transfers
* - For SG DMA transfer:
* - Programmable interrupt coalescing
* - Programmable delay timer counter
* - Managing the buffer descriptors (BDs)
*
* <b>Two Hardware Building Modes</b>
*
* The hardware can be built in two modes:
*
* - <b>Simple only mode</b>, in this mode, only simple transfers are
* supported by the hardware. The functionality is similar to the XPS
* Central DMA, however, the driver API to do the transfer is slightly
* different.
*
* - <b>Hybrid mode</b>, in this mode, the hardware supports both the simple
* transfer and the SG transfer. However, only one kind of transfer can be
* active at a time. If an SG transfer is ongoing in the hardware, a
* submission of a simple transfer fails. If a simple transfer is ongoing in
* the hardware, a submission of an SG transfer is successful, however the
* SG transfer will not start until the simple transfer is done.
*
* <b>Transactions</b>
*
* The hardware supports two types of transfers, the simple DMA transfer and
* the scatter gather (SG) DMA transfer.
*
* A simple DMA transfer only needs source buffer address, destination buffer
* address and transfer length to do a DMA transfer. Only one transfer can be
* submitted to the hardware at a time.
*
* A SG DMA transfer requires setting up a buffer descriptor (BD), which keeps
* the transfer information, including source buffer address, destination
* buffer address, and transfer length. The hardware updates the BD for the
* completion status of the transfer. BDs that are connected to each other can
* be submitted to the hardware at once, therefore, the SG DMA transfer has
* better performance when the application is doing multiple transfers each
* time.
*
* <b>Callback Function</b>
*
* Each transfer, for which the application cares about its completion, should
* provide with the driver its callback function. The signature of the
* callback function is as the following:
*
* void XAxiCdma_CallBackFn(void *CallBackRef, u32 IrqMask, int *NumPtr);
*
* Where the CallBackRef is a reference pointer that the application passes to
* the driver along with the callback function. The driver passes IrqMask to
* the application when it calls this callback. The NumPtr is only used in SG
* mode to track how many BDs still left for this callback function.
*
* The callback function is set upon transfer submission:
*
* - Simple transfer callback function setup:
*
* <b>Only set the callback function if in interrupt mode.</b>
*
* For simple transfers, the callback function along with the callback
* reference pointer is passed to the driver through the submission of the
* simple transfer:
*
* XAxiCdma_SimpleTransfer(...)
*
* - SG transfer callback function setup:
* For SG transfers, the callback function and the callback reference
* pointer are set through the transfer submission call:
*
* XAxiCdma_BdRingToHw(...)
*
* <b>Simple Transfers</b>
*
* For an application that only does one DMA transfer at a time, and the DMA
* engine is exclusively used by this application, simple DMA transfer is
* sufficient.
*
* Using the simple DMA transfer has the advantage of ease of use comparing to
* SG DMA transfer. For an individual DMA transfer, simple DMA transfer is
* also faster because of simplicity in software and hardware.
*
* <b>Scatter Gather (SG) Transfers</b>
*
* For an application that has multiple DMA transfers sometimes, or the DMA
* engine is shared by multiple applications, using SG DMA transfer yields
* better performance over all applications.
*
* The SG DMA transfer provides queuing of multiple transfers, therefore, it
* provides better performance because the hardware can continuously work on
* all submitted transfers without software intervention.
*
* The down side of using the SG DMA transfer is that you have to manage the
* memory for the buffer descriptors (BD), and setup BDs for the transfers.
*
* <b>Interrupts</b>
*
* The driver handles the interrupts.
*
* The completion of a transfer, that has a callback function associated with,
* will trigger the driver to call the callback function. The IrqMask that is
* passed through the callback function notifies the application about the
* completion status of the transfer.
*
* <b>Interrupt Coalescing for SG Transfers</b>
*
* For SG transfers, the application can program the interrupt coalescing
* threshold to reduce the frequency of interrupts. If the number of transfers
* does not match well with the interrupt coalescing threshold, the completion
* of the last transfer will not trigger the completion interrupt. However,
* after the specified delay count time, the delay interrupt will fire.
*
* By default, the interrupt threshold for the hardware is one, which is one
* interrupt per BD completion.
*
* <b>Delay Interrupt for SG Transfers</b>
*
* Delay interrupt is to signal the application about inactivity of transfers.
* If the delay interrupt is enabled, the delay timer starts counting down
* once a transfer has started. If the interval between transfers is longer
* than the delay counter, the delay interrupt is fired.
*
* By default, the delay counter is zero, which means the delay interrupt is
* disabled. To enable delay interrupt, the delay interrupt enable bit must be
* set and the delay counter must be set to a value between 1 to 255.
*
* <b>BD management for SG DMA Transfers </b>
*
* BD is shared by the software and the hardware. To use BD for SG DMA
* transfers, the application needs to use the driver API to do the following:
*
* - Setup the BD ring:
* - XAxiCdma_BdRingCreate(...)
*
* Note that the memory for the BD ring is allocated and is later
* de-allocated by the application.
*
* - Request BD from the BD ring, more than one BDs can be requested at once:
* - XAxiCdma_BdRingAlloc(...)
*
* - Prepare BDs for the transfer, one BD at a time:
* - XAxiCdma_BdSetSrcBufAddr(...)
* - XAxiCdma_BdSetDstBufAddr(...)
* - XAxiCdma_BdSetLength(...)
*
* - Submit all prepared BDs to the hardware:
* - XAxiCdma_BdRingToHw(...)
*
* - Upon transfer completion, the application can request completed BDs from
* the hardware:
* - XAxiCdma_BdRingFromHw(...)
*
* - After the application has finished using the BDs, it should free the
* BDs back to the free pool:
* - XAxiCdma_BdRingFree(...)
*
* The driver also provides API functions to get the status of a completed
* BD, along with get functions for other fields in the BD.
*
* The following two diagrams show the correct flow of BDs:
*
* The first diagram shows a complete cycle for BDs, starting from
* requesting the BDs to freeing the BDs.
* <pre>
*
* XAxiCdma_BdRingAlloc() XAxiCdma_BdRingToHw()
* Free ------------------------> Pre-process ----------------------> Hardware
* |
* /|\ |
* | XAxiCdma_BdRingFree() XAxiCdma_BdRingFromHw() |
* +--------------------------- Post-process <----------------------+
*
* </pre>
*
* The second diagram shows when a DMA transfer is to be cancelled before
* enqueuing to the hardware, application can return the requested BDs to the
* free group using XAxiCdma_BdRingUnAlloc().
* <pre>
*
* XAxiCdma_BdRingUnAlloc()
* Free <----------------------- Pre-process
*
* </pre>
*
* <b>Physical/Virtual Addresses</b>
*
* Addresses for the transfer buffers are physical addresses.
*
* For SG transfers, the next BD pointer in a BD is also a physical address.
*
* However, application's reference to a BD and to the transfer buffers are
* through virtual addresses.
*
* The application is responsible to translate the virtual addresses of its
* transfer buffers to physical addresses before handing them to the driver.
*
* For systems where MMU is not used, or MMU is a direct mapping, then the
* physical address and the virtual address are the same.
*
* <b>Cache Coherency</b>
*
* To prevent cache and memory inconsistency:
* - Flush the transmit buffer range before the transfer
* - Invalidate the receive buffer range before passing it to the hardware and
* before passing it to the application
*
* For SG transfers:
* - Flush the BDs once the preparation setup is done
* - Invalidate the memory region for BDs when BDs are retrieved from the
* hardware.
*
* <b>BD alignment for SG Transfers</b>
*
* The hardware has requirement for the minimum alignment of the BDs,
* XAXICDMA_BD_MINIMUM_ALIGNMENT. It is OK to have an alignment larger than the
* required minimum alignment, however, it must be multiple of the minimum
* alignment. The alignment is passed into XAxiCdma_BdRingCreate().
*
* <b>Error Handling</b>
*
* The hardware halts upon all error conditions. The driver will reset the
* hardware once the error occurs.
*
* The IrqMask argument in the callback function notifies the application about
* error conditions for the transfer.
*
* <b>Mutual Exclusion</b>
*
* The driver does not provide mutual exclusion mechanisms, it is up to the
* upper layer to handle this.
*
* <b>Hardware Defaults & Exclusive Use</b>
*
* The hardware is in the following condition on start or after a reset:
*
* - All interrupts are disabled.
* - The engine is in simple mode.
* - Interrupt coalescing counter is one.
* - Delay counter is 0.
*
* The driver has exclusive use of the hardware registers and BDs. Accessing
* the hardware registers or the BDs should always go through the driver API
* functions.
*
* <b>Hardware Features That User Should Be Aware of</b>
*
* For performance reasons, the driver does not check the submission of
* transfers during run time. It is the user's responsibility to submit
* approrpiate transfers to the hardware. The following hardware features
* should be considerred when submitting a transfer:
*
* . Whether the hardware supports unaligned transfers, reflected through
* C_INCLUDE_DRE in system.mhs file. Submitting unaligned transfers while the
* hardware does not support it, causes errors upon transfer submission.
* Aligned transfer is in respect to word length, and word length is defined
* through the building parameter XPAR_AXI_CDMA_0_M_AXI_DATA_WIDTH.
*
* . Memory range of the transfer addresses. Transfer data to executable
* memory can crash the system.
*
* . Lite mode. To save hardware resources (drastically), you may select
* "lite" mode build of the hardware. However, with lite mode, the following
* features are _not_ supported:
* - Cross page boundary transfer. Each transfer must be restrictly inside
* one page; otherwise, slave error occurs.
* - Unaligned transfer.
* - Data width larger than 64 bit
* - Maximum transfer length each time is limited to data_width * burst_len
*
* <pre>
* MODIFICATION HISTORY:
*
* . Updated the debug print on type casting to avoid warnings on u32. Cast
* u32 to (unsigned int) to use the %x format.
*
* Ver Who Date Changes
* ----- ---- -------- -------------------------------------------------------
* 1.00a jz 07/08/10 First release
* 2.01a rkv 01/25/11 Added TCL script to generate Test App code for peripheral
* tests.
* Replaced with "\r\n" in place on "\n\r" in printf
* statements. Made some minor modifications for Doxygen
* 2.02a srt 01/18/13 Added support for Key Hole feature (CR: 687217).
* Updated DDR base address for IPI designs (CR 703656).
* 2.03a srt 04/13/13 Removed Warnings (CR 705006).
* Added logic to check if DDR is present in the test app
* tcl file. (CR 700806)
* 3.0 adk 19/12/13 Updated as per the New Tcl API's
* </pre>
*****************************************************************************/
#ifndef XAXICDMA_H_ /* prevent circular inclusions */
#define XAXICDMA_H_
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xaxicdma_bd.h"
#ifdef __MICROBLAZE__
#include "xenv.h"
#else
#include <string.h>
#include "xil_cache.h"
#endif
/************************** Constant Definitions *****************************/
#define XAXICDMA_COALESCE_NO_CHANGE 0xFFFFFFFF
#define XAXICDMA_ALL_BDS 0x7FFFFFFF /* 2147 Million */
/* Constants for engine mode: simple/SG
*/
#define XAXICDMA_SG_MODE 1
#define XAXICDMA_SIMPLE_MODE 2
/* Maximum active SG interrupt handler this driver can manage
*
* The limitation comes from the interrupt handler. It is now one interrupt
* handler for one transfer. It is possible to simplify, as in most use cases,
* to have one interrupt handler for all SG transfers
*/
#define XAXICDMA_MAXIMUM_MAX_HANDLER 20
/* Constants of KeyHole feature selection: Write/Read
*/
#define XAXICDMA_KEYHOLE_READ 0
#define XAXICDMA_KEYHOLE_WRITE 1
/**************************** Type Definitions *******************************/
/**
* @name Call Back function
*
* If interrupt is enabled, and the application wants to be notified about the
* completion of a transfer, the application should register its call back
* function to the driver.
*
* The call back function is registered through the transfer submission.
*
* @param CallBackRef is the call back reference passed in by application. A
* NULL pointer is acceptable.
*
* @param IrqMask is the interrupt mask regarding this completion
* @param NumBdPtr is the pointer to number of BDs this handler should handle,
* for simple transfer, it is ignored.
*/
typedef void (*XAxiCdma_CallBackFn)(void *CallBackRef, u32 IrqMask,
int *NumBdPtr);
/**
* @name XAxiCdma_IntrHandlerList
*
* Interrupt handler list for scatter gather transfers
*
* @{
*/
typedef struct {
XAxiCdma_CallBackFn CallBackFn; /**< Callback function */
void *CallBackRef; /**< Callback reference pointer */
volatile int NumBds; /**< Number of BDs this handler cares */
}XAxiCdma_IntrHandlerList;
/**
* @name XAxiCdma_Config
*
* The hardware configuration structure, to be passed to the driver by the
* user, or by tools if using XPS.
*
* @{
*/
typedef struct {
u32 DeviceId; /**< Unique ID of this instance */
u32 BaseAddress; /**< Physical address of this instance */
int HasDRE; /**< Whether support unaligned transfers */
int IsLite; /**< Whether hardware build is lite mode */
int DataWidth; /**< Length of a word in bits */
int BurstLen; /**< Burst length */
}XAxiCdma_Config;
/**
* @name XAxiCdma
*
* The structure to hold the driver instance data. An instance of this
* structure corresponds to one DMA engine.
*
* @{
*/
typedef struct {
u32 BaseAddr; /**< Virtual base address of the DMA engine */
int Initialized; /**< The driver/engine in working state */
int SimpleOnlyBuild; /**< Whether hardware is simple only build */
int HasDRE; /**< Whether support unaligned transfers */
int IsLite; /**< Whether hardware is in lite mode */
int WordLength; /**< Length of a word in bytes */
int MaxTransLen; /**< Length hardware supports */
int SimpleNotDone; /**< Flag that a simple transfer is ongoing */
int SGWaiting; /**< Flag that SG transfers are waiting */
/* BD ring fields for SG transfer */
u32 FirstBdPhysAddr; /**< Physical address of 1st BD in list */
u32 FirstBdAddr; /**< Virtual address of 1st BD in list */
u32 LastBdAddr; /**< Virtual address of last BD in the list */
u32 BdRingTotalLen; /**< Total size of ring in bytes */
u32 BdSeparation; /**< Distance between adjacent BDs in bytes */
XAxiCdma_Bd *FreeBdHead; /**< First BD in the free group */
XAxiCdma_Bd *PreBdHead; /**< First BD in the pre-work group */
XAxiCdma_Bd *HwBdHead; /**< First BD in the work group */
XAxiCdma_Bd *HwBdTail; /**< Last BD in the work group */
XAxiCdma_Bd *PostBdHead; /**< First BD in the post-work group */
XAxiCdma_Bd *BdaRestart; /**< BD to load when hardware restarted */
int FreeBdCnt; /**< Number of allocatable BDs */
int PreBdCnt; /**< Number of BDs in pre-work group */
int HwBdCnt; /**< Number of BDs in work group */
int PostBdCnt; /**< Number of BDs in post-work group */
int AllBdCnt; /**< Total Number of BDs */
/* Callback function for simple transfer*/
XAxiCdma_CallBackFn SimpleCallBackFn; /**< Callback function for simple
transfer */
void *SimpleCallBackRef; /**< Callback reference pointer */
int SgHandlerHead; /**< First active sg transfer handler */
int SgHandlerTail; /**< Last active sg transfer handler */
XAxiCdma_IntrHandlerList Handlers[XAXICDMA_MAXIMUM_MAX_HANDLER];
/**< List of interrupt handlers */
}XAxiCdma;
/* @} */
/***************** Macros (Inline Functions) Definitions *********************/
/*****************************************************************************/
/*
* Macros to flush and invalidate cache for BDs should they be
* located in cached memory. These macros may NOPs if the underlying
* XCACHE_FLUSH_DCACHE_RANGE and XCACHE_INVALIDATE_DCACHE_RANGE macros are not
* implemented or they do nothing.
*****************************************************************************/
#ifdef __MICROBLAZE__
#ifdef XCACHE_FLUSH_DCACHE_RANGE
#define XAXICDMA_CACHE_FLUSH(BdPtr) \
XCACHE_FLUSH_DCACHE_RANGE((BdPtr), XAXICDMA_BD_HW_NUM_BYTES)
#else
#define XAXICDMA_CACHE_FLUSH(BdPtr)
#endif
#ifdef XCACHE_INVALIDATE_DCACHE_RANGE
#define XAXICDMA_CACHE_INVALIDATE(BdPtr) \
XCACHE_INVALIDATE_DCACHE_RANGE((BdPtr), XAXICDMA_BD_HW_NUM_BYTES)
#else
#define XAXICDMA_CACHE_INVALIDATE(BdPtr)
#endif
#else /* __MICROBLAZE__*/
#define XAXICDMA_CACHE_FLUSH(BdPtr) \
Xil_DCacheFlushRange((BdPtr), XAXICDMA_BD_HW_NUM_BYTES);
#define XAXICDMA_CACHE_INVALIDATE(BdPtr) \
Xil_DCacheInvalidateRange((BdPtr), XAXICDMA_BD_HW_NUM_BYTES)
#endif
/************************** Function Prototypes ******************************/
XAxiCdma_Config *XAxiCdma_LookupConfig(u32 DeviceId);
int XAxiCdma_CfgInitialize(XAxiCdma *InstancePtr, XAxiCdma_Config *CfgPtr,
u32 EffectiveAddr);
void XAxiCdma_Reset(XAxiCdma *InstancePtr);
int XAxiCdma_ResetIsDone(XAxiCdma *InstancePtr);
int XAxiCdma_IsBusy(XAxiCdma *InstancePtr);
int XAxiCdma_SetCoalesce(XAxiCdma *InstancePtr, u32 Counter, u32 Delay);
void XAxiCdma_GetCoalesce(XAxiCdma *InstancePtr, u32 *CounterPtr,
u32 *DelayPtr);
u32 XAxiCdma_GetError(XAxiCdma *InstancePtr);
void XAxiCdma_IntrEnable(XAxiCdma *InstancePtr, u32 Mask);
u32 XAxiCdma_IntrGetEnabled(XAxiCdma *InstancePtr);
void XAxiCdma_IntrDisable(XAxiCdma *InstancePtr, u32 Mask);
void XAxiCdma_IntrHandler(void *HandlerRef);
int XAxiCdma_SimpleTransfer(XAxiCdma *InstancePtr, u32 SrcAddr, u32 DstAddr,
int Length, XAxiCdma_CallBackFn SimpleCallBack, void *CallbackRef);
int XAxiCdma_SelectKeyHole(XAxiCdma *InstancePtr, u32 Direction, u32 Select);
/* BD ring API functions
*/
int XAxiCdma_BdRingCntCalc(u32 Alignment, u32 Bytes, u32 BuffAddr);
int XAxiCdma_BdRingMemCalc(u32 Alignment, int NumBd);
int XAxiCdma_BdRingGetCnt(XAxiCdma *InstancePtr);
int XAxiCdma_BdRingGetFreeCnt(XAxiCdma *InstancePtr);
void XAxiCdma_BdRingSnapShotCurrBd(XAxiCdma *InstancePtr);
XAxiCdma_Bd *XAxiCdma_BdRingGetCurrBd(XAxiCdma *InstancePtr);
XAxiCdma_Bd *XAxiCdma_BdRingNext(XAxiCdma *InstancePtr, XAxiCdma_Bd *BdPtr);
XAxiCdma_Bd *XAxiCdma_BdRingPrev(XAxiCdma *InstancePtr, XAxiCdma_Bd *BdPtr);
int XAxiCdma_BdRingCreate(XAxiCdma *InstancePtr, u32 PhysAddr,
u32 VirtAddr, u32 Alignment, int BdCount);
int XAxiCdma_BdRingClone(XAxiCdma *InstancePtr, XAxiCdma_Bd * TemplateBdPtr);
int XAxiCdma_BdRingAlloc(XAxiCdma *InstancePtr, int NumBd,
XAxiCdma_Bd ** BdSetPtr);
int XAxiCdma_BdRingUnAlloc(XAxiCdma *InstancePtr, int NumBd,
XAxiCdma_Bd * BdSetPtr);
int XAxiCdma_BdRingToHw(XAxiCdma *InstancePtr, int NumBd,
XAxiCdma_Bd * BdSetPtr, XAxiCdma_CallBackFn CallBack,
void *CallBackRef);
int XAxiCdma_BdRingFromHw(XAxiCdma *InstancePtr, int BdLimit,
XAxiCdma_Bd ** BdSetPtr);
int XAxiCdma_BdRingFree(XAxiCdma *InstancePtr, int NumBd,
XAxiCdma_Bd * BdSetPtr);
/* Debug utility function
*/
void XAxiCdma_DumpRegisters(XAxiCdma *InstancePtr);
#ifdef __cplusplus
}
#endif
#endif /* prevent circular inclusions */