/****************************************************************************** * * Copyright (C) 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 xzdma.c * * This file contains the implementation of the interface functions for ZDMA * driver. Refer to the header file xzdma.h for more detailed information. * *
* MODIFICATION HISTORY:
*
* Ver   Who     Date     Changes
* ----- ------  -------- ------------------------------------------------------
* 1.0   vns     2/27/15  First release
* 
* ******************************************************************************/ /***************************** Include Files *********************************/ #include "xzdma.h" /************************** Function Prototypes ******************************/ static void StubCallBack(void *CallBackRef, u32 Mask); static void StubDoneCallBack(void *CallBackRef); static void XZDma_SimpleMode(XZDma *InstancePtr, XZDma_Transfer *Data); static void XZDma_ScatterGather(XZDma *InstancePtr, XZDma_Transfer *Data, u32 Num); static void XZDma_LinearMode(XZDma *InstancePtr, XZDma_Transfer *Data, XZDma_LiDscr *SrcDscrPtr,XZDma_LiDscr *DstDscrPtr, u8 IsLast); static void XZDma_ConfigLinear(XZDma_LiDscr *DscrPtr, u64 Addr, u32 Size, u32 CtrlValue); static void XZDma_LinkedListMode(XZDma *InstancePtr, XZDma_Transfer *Data, XZDma_LlDscr *SrcDscrPtr,XZDma_LlDscr *DstDscrPtr, u8 IsLast); static void XZDma_ConfigLinkedList(XZDma_LlDscr *DscrPtr, u64 Addr, u32 Size, u32 CtrlValue, u64 NextDscrAddr); static void XZDma_Enable(XZDma *InstancePtr); static void XZDma_GetConfigurations(XZDma *InstancePtr); /************************** Function Definitions *****************************/ /*****************************************************************************/ /** * * This function initializes an ZDMA core. This function must be called * prior to using an ZDMA core. Initialization of an ZDMA includes setting * up the instance data and ensuring the hardware is in a quiescent state and * resets all the hardware configurations. * * @param InstancePtr is a pointer to the XZDma instance. * @param CfgPtr is a reference to a structure containing information * about a specific XZDma instance. * @param EffectiveAddr is the device base address in the virtual memory * address space. The caller is responsible for keeping the * address mapping from EffectiveAddr to the device physical * base address unchanged once this function is invoked. * Unexpected errors may occur if the address mapping changes * after this function is called. If address translation is not * used, pass in the physical address instead. * * @return * - XST_SUCCESS if initialization was successful. * * @note None. * ******************************************************************************/ s32 XZDma_CfgInitialize(XZDma *InstancePtr, XZDma_Config *CfgPtr, u32 EffectiveAddr) { /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(CfgPtr != NULL); Xil_AssertNonvoid(EffectiveAddr != ((u32)0x00)); InstancePtr->Config.BaseAddress = CfgPtr->BaseAddress; InstancePtr->Config.DeviceId = CfgPtr->DeviceId; InstancePtr->Config.DmaType = CfgPtr->DmaType; InstancePtr->Config.BaseAddress = EffectiveAddr; InstancePtr->IsReady = (u32)(XIL_COMPONENT_IS_READY); InstancePtr->IsSgDma = FALSE; InstancePtr->Mode = XZDMA_NORMAL_MODE; InstancePtr->IntrMask = 0x00U; InstancePtr->ChannelState = XZDMA_IDLE; /* * Set all handlers to stub values, let user configure this * data later */ InstancePtr->DoneHandler = (XZDma_DoneHandler)((void *)StubDoneCallBack); InstancePtr->ErrorHandler = (XZDma_ErrorHandler)((void *)StubCallBack); XZDma_Reset(InstancePtr); XZDma_GetConfigurations(InstancePtr); return (XST_SUCCESS); } /*****************************************************************************/ /** * * This function sets the pointer type and mode in which ZDMA needs to transfer * the data. * * @param InstancePtr is a pointer to the XZDma instance. * @param IsSgDma is a variable which specifies whether transfer has to * to be done in scatter gather mode or simple mode. * - TRUE - Scatter gather pointer type * - FALSE - Simple pointer type * @param Mode is the type of the mode in which data has to be initiated * - XZDMA_NORMAL_MODE - Normal data transfer from source to * destination (Valid for both Scatter * gather and simple types) * - XZDMA_WRONLY_MODE - Write only mode (Valid only for Simple) * - XZDMA_RDONLY_MODE - Read only mode (Valid only for Simple) * * @return * - XST_SUCCESS - If mode has been set successfully. * - XST_FAILURE - If mode has not been set. * * @note Mode cannot be changed while ZDMA is not in IDLE state. * ******************************************************************************/ s32 XZDma_SetMode(XZDma *InstancePtr, u8 IsSgDma, XZDma_Mode Mode) { u32 Data; s32 Status; /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid((IsSgDma == TRUE) || (IsSgDma == FALSE)); Xil_AssertNonvoid(Mode <= XZDMA_RDONLY_MODE); if (InstancePtr->ChannelState != XZDMA_IDLE) { Status = XST_FAILURE; } else { Data = XZDma_ReadReg(InstancePtr->Config.BaseAddress, XZDMA_CH_CTRL0_OFFSET); /* Simple mode */ if (IsSgDma != TRUE) { Data = (Data & (~XZDMA_CTRL0_POINT_TYPE_MASK)); if (Mode == XZDMA_NORMAL_MODE) { Data &= (~XZDMA_CTRL0_MODE_MASK); } else if (Mode == XZDMA_WRONLY_MODE) { Data |= XZDMA_CTRL0_WRONLY_MASK; } else { Data |= XZDMA_CTRL0_RDONLY_MASK; } XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_CTRL0_OFFSET, Data); InstancePtr->IsSgDma = FALSE; InstancePtr->Mode = Mode; } else { if (Mode != XZDMA_NORMAL_MODE) { Status = XST_FAILURE; } else { Data |= (XZDMA_CTRL0_POINT_TYPE_MASK); Data &= ~(XZDMA_CTRL0_MODE_MASK); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_CTRL0_OFFSET, Data); InstancePtr->IsSgDma = TRUE; InstancePtr->Mode = Mode; } } Status = XST_SUCCESS; } return Status; } /*****************************************************************************/ /** * * This function sets the descriptor type and descriptor pointer's start address * of both source and destination based on the memory allocated by user and also * calculates no of descriptors(BDs) can be created in the allocated memory. * * @param InstancePtr is a pointer to the XZDma instance. * @param TypeOfDscr is a variable which specifies descriptor type * whether Linear or linked list type of descriptor. * - XZDMA_LINEAR - Linear type of descriptor. * - XZDMA_LINKEDLIST- Linked list type of descriptor. * @param Dscr_MemPtr is a pointer to the allocated memory for creating * descriptors. It Should be aligned to 64 bytes. * * @param NoOfBytes specifies the number of bytes allocated for * descriptors * * @return The Count of the descriptors can be created. * * @note User should allocate the memory for descriptors which should * be capable of how many transfers he wish to do in one start. * For Linear mode each descriptor needs 128 bit memory so for * one data transfer it requires 2*128 = 256 bits i.e. 32 bytes * Similarly for Linked list mode for each descriptor it needs * 256 bit, so for one data transfer it require 2*256 = 512 bits * i.e. 64 bytes. * ******************************************************************************/ u32 XZDma_CreateBDList(XZDma *InstancePtr, XZDma_DscrType TypeOfDscr, UINTPTR Dscr_MemPtr, u32 NoOfBytes) { XZDma_LiDscr *LocalLinearPtr = (XZDma_LiDscr *)(void *)Dscr_MemPtr; XZDma_LlDscr *LocalLinklistPtr = (XZDma_LlDscr *)(void *)Dscr_MemPtr; /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid((TypeOfDscr == XZDMA_LINEAR) || (TypeOfDscr == XZDMA_LINKEDLIST)); Xil_AssertNonvoid(Dscr_MemPtr != 0x00); Xil_AssertNonvoid(NoOfBytes != 0x00U); InstancePtr->Descriptor.DscrType = TypeOfDscr; if (TypeOfDscr == XZDMA_LINEAR) { InstancePtr->Descriptor.SrcDscrPtr = (void *)Dscr_MemPtr; LocalLinearPtr = ((LocalLinearPtr + (NoOfBytes >> 1)) + 1U); InstancePtr->Descriptor.DstDscrPtr = (void *)LocalLinearPtr; InstancePtr->Descriptor.DscrCount = (NoOfBytes >> 1) / sizeof(XZDma_LiDscr); } else { InstancePtr->Descriptor.SrcDscrPtr = (void *)Dscr_MemPtr; LocalLinklistPtr = ((LocalLinklistPtr + (NoOfBytes >> 1)) + 1U); InstancePtr->Descriptor.DstDscrPtr = (void *)LocalLinklistPtr; InstancePtr->Descriptor.DscrCount = (NoOfBytes >> 1) / sizeof(XZDma_LlDscr); } Xil_DCacheInvalidateRange((INTPTR)Dscr_MemPtr, NoOfBytes); return (InstancePtr->Descriptor.DscrCount); } /*****************************************************************************/ /** * * This function sets the data attributes and control configurations of a * ZDMA core based on the inputs provided. * * @param InstancePtr is a pointer to the XZDma instance. * @param Configure is a pointer to the XZDma_ChDataConfig structure * which has all the configuration fields. * The fields of the structure are: * - OverFetch - Allows over fetch or not * - 0 - Not allowed to over-fetch on SRC * - 1 - Allowed to over-fetch on SRC * - SrcIssue - Outstanding transaction on SRC * - Range is 1 to 32 * - SrcBurstType - Burst Type for SRC AXI transaction * - XZDMA_FIXED_BURST - Fixed burst * - XZDMA_INCR_BURST - Incremental burst * - SrcBurstLen - AXI Length for Data Read. * - Range of values is (1,2,4,8,16). * - DstBurstType - Burst Type for SRC AXI transaction * - XZDMA_FIXED_BURST - Fixed burst * - XZDMA_INCR_BURST - Incremental burst * - DstBurstLen - AXI Length for Data write. * - Range of values is (1,2,4,8,16). * - SrcCache - AXI cache bits for Data read * - SrcQos - Configurable QoS bits for AXI Data read * - DstCache - AXI cache bits for Data write * - DstQos - configurable QoS bits for AXI Data write * * @return * - XST_FAILURE If ZDMA Core is not in Idle state and * - XST_SUCCESS If Configurations are made successfully * * @note * - These configurations will last till we modify or Reset * by XZDma_Reset(XZDma *InstancePtr). * - Configurations should be modified only when ZDMA channel * is IDLE this can be confirmed by using * XZDma_ChannelState(XZDma *InstancePtr) API. * ******************************************************************************/ s32 XZDma_SetChDataConfig(XZDma *InstancePtr, XZDma_DataConfig *Configure) { u32 Data; s32 Status; /* Verify arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(Configure != NULL); if (InstancePtr->ChannelState != XZDMA_IDLE) { Status = XST_FAILURE; } else { InstancePtr->DataConfig.DstBurstType = Configure->DstBurstType; InstancePtr->DataConfig.DstBurstLen = Configure->DstBurstLen; InstancePtr->DataConfig.SrcBurstType = Configure->SrcBurstType; InstancePtr->DataConfig.SrcBurstLen = Configure->SrcBurstLen; InstancePtr->DataConfig.OverFetch = Configure->OverFetch; InstancePtr->DataConfig.SrcIssue = Configure->SrcIssue; InstancePtr->DataConfig.SrcCache = Configure->SrcCache; InstancePtr->DataConfig.SrcQos = Configure->SrcQos; InstancePtr->DataConfig.DstCache = Configure->DstCache; InstancePtr->DataConfig.DstQos = Configure->DstQos; /* Setting over fetch */ Data = XZDma_ReadReg(InstancePtr->Config.BaseAddress, XZDMA_CH_CTRL0_OFFSET); Data |= (((u32)(Configure->OverFetch) << XZDMA_CTRL0_OVR_FETCH_SHIFT) & XZDMA_CTRL0_OVR_FETCH_MASK); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_CTRL0_OFFSET, Data); /* Setting source issue */ Data = XZDma_ReadReg(InstancePtr->Config.BaseAddress, XZDMA_CH_CTRL1_OFFSET); Data = (u32)(Configure->SrcIssue & XZDMA_CTRL1_SRC_ISSUE_MASK); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_CTRL1_OFFSET, Data); /* Setting Burst length and burst type */ Data = XZDma_ReadReg(InstancePtr->Config.BaseAddress, XZDMA_CH_DATA_ATTR_OFFSET); Data = (Data & (~(XZDMA_DATA_ATTR_ARBURST_MASK | XZDMA_DATA_ATTR_ARLEN_MASK | XZDMA_DATA_ATTR_AWBURST_MASK | XZDMA_DATA_ATTR_AWLEN_MASK | XZDMA_DATA_ATTR_ARCACHE_MASK | XZDMA_DATA_ATTR_AWCACHE_MASK | XZDMA_DATA_ATTR_AWQOS_MASK | XZDMA_DATA_ATTR_ARQOS_MASK))); Data |= ((((u32)(Configure->SrcBurstType) << XZDMA_DATA_ATTR_ARBURST_SHIFT) & XZDMA_DATA_ATTR_ARBURST_MASK) | (((u32)(Configure->SrcCache) << XZDMA_DATA_ATTR_ARCACHE_SHIFT) & XZDMA_DATA_ATTR_ARCACHE_MASK) | (((u32)(Configure->SrcQos) << XZDMA_DATA_ATTR_ARQOS_SHIFT) & XZDMA_DATA_ATTR_ARQOS_MASK) | (((u32)(Configure->SrcBurstLen) << XZDMA_DATA_ATTR_ARLEN_SHIFT) & XZDMA_DATA_ATTR_ARLEN_MASK) | (((u32)(Configure->DstBurstType) << XZDMA_DATA_ATTR_AWBURST_SHIFT) & XZDMA_DATA_ATTR_AWBURST_MASK) | (((u32)(Configure->DstCache) << XZDMA_DATA_ATTR_AWCACHE_SHIFT) & XZDMA_DATA_ATTR_AWCACHE_MASK) | (((u32)(Configure->DstQos) << XZDMA_DATA_ATTR_AWQOS_SHIFT) & XZDMA_DATA_ATTR_AWQOS_MASK) | (((u32)(Configure->DstBurstLen)) & XZDMA_DATA_ATTR_AWLEN_MASK)); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_DATA_ATTR_OFFSET, Data); Status = XST_SUCCESS; } return Status; } /*****************************************************************************/ /** * * This function gets the data attributes and control configurations of a * ZDMA core. * * @param InstancePtr is a pointer to the XZDma instance. * @param Configure is a pointer to the XZDma_ChDataConfig structure * which has all the configuration fields. * The fields of the structure are: * - OverFetch - Allows over fetch or not * - 0 - Not allowed to over-fetch on SRC * - 1 - Allowed to over-fetch on SRC * - SrcIssue - Outstanding transaction on SRC * - Range is 1 to 32 * - SrcBurstType - Burst Type for SRC AXI transaction * - XZDMA_FIXED_BURST - Fixed burst * - XZDMA_INCR_BURST - Incremental burst * - SrcBurstLen - AXI Length for Data Read. * - Can be max of 16 to be compatible with AXI3 * - DstBurstType - Burst Type for SRC AXI transaction * - XZDMA_FIXED_BURST - Fixed burst * - XZDMA_INCR_BURST - Incremental burst * - DstBurstLen - AXI Length for Data write. * - Can be max of 16 to be compatible with AXI3 * - SrcCache - AXI cache bits for Data read * - SrcQos - Configurable QoS bits for AXI Data read * - DstCache - AXI cache bits for Data write * - DstQos - Configurable QoS bits for AXI Data write * * @return None * * @note None. * ******************************************************************************/ void XZDma_GetChDataConfig(XZDma *InstancePtr, XZDma_DataConfig *Configure) { /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Configure != NULL); Configure->SrcBurstType = InstancePtr->DataConfig.SrcBurstType; Configure->SrcCache = InstancePtr->DataConfig.SrcCache; Configure->SrcQos = InstancePtr->DataConfig.SrcQos; Configure->SrcBurstLen = InstancePtr->DataConfig.SrcBurstLen; Configure->DstBurstType = InstancePtr->DataConfig.DstBurstType; Configure->DstCache = InstancePtr->DataConfig.DstCache; Configure->DstQos = InstancePtr->DataConfig.DstQos; Configure->DstBurstLen = InstancePtr->DataConfig.DstBurstLen; Configure->OverFetch = InstancePtr->DataConfig.OverFetch; Configure->SrcIssue = InstancePtr->DataConfig.SrcIssue; } /*****************************************************************************/ /** * * This function sets the descriptor attributes based on the inputs provided * in the structure. * * @param InstancePtr is a pointer to the XZDma instance. * @param Configure is a pointer to the XZDma_ChDscrConfig structure * which has all the configuration fields. * The fields of the structure are: * - AxCoherent - AXI transactions generated for the descriptor. * - 0 - Non coherent * - 1 - Coherent * - AXCache - AXI cache bit used for DSCR fetch * (both on SRC and DST Side) * - AXQos - QoS bit used for DSCR fetch * (both on SRC and DST Side) * * @return * - XST_FAILURE If ZDMA core is not in Idle state and * - XST_SUCCESS If Configurations are made successfully * * @note None. * ******************************************************************************/ s32 XZDma_SetChDscrConfig(XZDma *InstancePtr, XZDma_DscrConfig *Configure) { u32 Data; s32 Status; /* Verify arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(Configure != NULL); if (InstancePtr->ChannelState != XZDMA_IDLE) { Status = XST_FAILURE; } else { InstancePtr->DscrConfig.AXCache = Configure->AXCache; InstancePtr->DscrConfig.AXQos = Configure->AXQos; InstancePtr->DscrConfig.AxCoherent = Configure->AxCoherent; Data = ((((u32)(Configure->AxCoherent) << XZDMA_DSCR_ATTR_AXCOHRNT_SHIFT) & XZDMA_DSCR_ATTR_AXCOHRNT_MASK) | (((u32)(Configure->AXCache) << XZDMA_DSCR_ATTR_AXCACHE_SHIFT) & XZDMA_DSCR_ATTR_AXCACHE_MASK) | (((u32)Configure->AXQos) & XZDMA_DSCR_ATTR_AXQOS_MASK)); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_DSCR_ATTR_OFFSET, Data); Status = XST_SUCCESS; } return Status; } /*****************************************************************************/ /** * * This function gets the descriptor attributes of the channel. * * @param InstancePtr is a pointer to the XZDma instance. * @param Configure is a pointer to the XZDma_ChDscrConfig structure * which has all the configuration fields. * The fields of the structure are: * - AxCoherent - AXI transactions generated for the descriptor. * - 0 - Non coherent * - 1 - Coherent * - AXCache - AXI cache bit used for DSCR fetch * (both on SRC and DST Side) * - AXQos - QoS bit used for DSCR fetch * (both on SRC and DST Side) * * @return None. * * @note None. * ******************************************************************************/ void XZDma_GetChDscrConfig(XZDma *InstancePtr, XZDma_DscrConfig *Configure) { /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Configure != NULL); Configure->AXCache = InstancePtr->DscrConfig.AXCache; Configure->AXQos = InstancePtr->DscrConfig.AXQos; Configure->AxCoherent = InstancePtr->DscrConfig.AxCoherent; } /*****************************************************************************/ /** * * This function preloads the buffers which will be used in write only mode. * In write only mode the data in the provided buffer will be written in * destination address for specified size. * * @param InstancePtr is a pointer to the XZDma instance. * @param Buffer is a pointer to an array of 64/128 bit data. * i.e. pointer to 32 bit array of size 2/4 * - Array of Size 2 for ADMA * - Array of Size 4 for GDMA * * @return None. * * @note Valid only in simple mode. * Prior to call this function ZDMA instance should be set in * Write only mode by using * XZDma_SetMode(XZDma *InstancePtr, u8 IsSgDma, * XZDma_Mode Mode) * To initiate data transfer after this API need to call * XZDma_Start(XZDma *InstancePtr, XZDma_Transfer *Data, u32 Num) * In which only destination fields has to be filled. * ******************************************************************************/ void XZDma_WOData(XZDma *InstancePtr, u32 *Buffer) { u32 *LocBuf = Buffer; /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Buffer != NULL); if (InstancePtr->Config.DmaType == (u8)0) { XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_WR_ONLY_WORD0_OFFSET, *LocBuf); LocBuf++; XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_WR_ONLY_WORD1_OFFSET, *LocBuf); LocBuf++; XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_WR_ONLY_WORD2_OFFSET, *LocBuf); LocBuf++; XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_WR_ONLY_WORD3_OFFSET, *LocBuf); } else { XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_WR_ONLY_WORD0_OFFSET, *LocBuf); LocBuf++; XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_WR_ONLY_WORD1_OFFSET, *LocBuf); } } /*****************************************************************************/ /** * * This function resume the paused state of ZDMA core and starts the transfer * from where it has paused. * * @param InstancePtr is a pointer to the XZDma instance. * * @return None. * * @note Valid only for scatter gather mode. * ******************************************************************************/ void XZDma_Resume(XZDma *InstancePtr) { u32 Value; /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsSgDma == TRUE); Xil_AssertVoid(InstancePtr->ChannelState == XZDMA_PAUSE); Value = XZDma_ReadReg(InstancePtr->Config.BaseAddress, XZDMA_CH_CTRL0_OFFSET) & (~XZDMA_CTRL0_CONT_ADDR_MASK); Value |= XZDMA_CTRL0_CONT_MASK; InstancePtr->ChannelState = XZDMA_BUSY; XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_CTRL0_OFFSET, Value); } /*****************************************************************************/ /** * * This function resets the ZDMA core. * * @param InstancePtr is a pointer to the XZDma instance. * * @return None. * * @note This function resets all the configurations made previously. * Disables all the interrupts and clears interrupt status. * *****************************************************************************/ void XZDma_Reset(XZDma *InstancePtr) { /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->ChannelState == XZDMA_IDLE); /* Disable's the channel */ XZDma_DisableCh(InstancePtr); /* Disables all interrupts */ XZDma_DisableIntr(InstancePtr, XZDMA_IXR_ALL_INTR_MASK); XZDma_IntrClear(InstancePtr, XZDMA_IXR_ALL_INTR_MASK); InstancePtr->IntrMask = 0x00U; /* All configurations are being reset */ XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_CTRL0_OFFSET, XZDMA_CTRL0_RESET_VALUE); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_CTRL1_OFFSET, XZDMA_CTRL1_RESET_VALUE); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_DATA_ATTR_OFFSET, XZDMA_DATA_ATTR_RESET_VALUE); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_DSCR_ATTR_OFFSET, XZDMA_DSCR_ATTR_RESET_VALUE); /* Clears total byte */ XZDma_TotalByteClear(InstancePtr); /* Clears interrupt count of both source and destination channels */ (void)XZDma_GetSrcIntrCnt(InstancePtr); (void)XZDma_GetDstIntrCnt(InstancePtr); InstancePtr->ChannelState = XZDMA_IDLE; } /*****************************************************************************/ /** * * This function returns the state of ZDMA core. * * @param InstancePtr is a pointer to the XZDma instance. * * @return This function returns state of ZDMA core * - XZDMA_IDLE - If ZDMA core is in idle state. * - XZDMA_PAUSE - If ZDMA is in paused state. * - XZDMA_BUSY - If ZDMA is in busy state. * @note None. * C-style signature: * XZDmaState XZDma_ChannelState(XZDma *InstancePtr) * ******************************************************************************/ XZDmaState XZDma_ChannelState(XZDma *InstancePtr) { XZDmaState Status; u32 Value; /* Verify arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Value = XZDma_ReadReg(InstancePtr->Config.BaseAddress, (XZDMA_CH_STS_OFFSET)) & (XZDMA_STS_ALL_MASK); if ((Value == XZDMA_STS_DONE_MASK) || (Value == XZDMA_STS_DONE_ERR_MASK)) { Status = XZDMA_IDLE; } else if (Value == XZDMA_STS_PAUSE_MASK) { Status = XZDMA_PAUSE; } else { Status = XZDMA_BUSY; } return Status; } /*****************************************************************************/ /** * * This function sets all the required fields for initiating data transfer. Data * transfer elements needs to be passed through structure pointer. * Data transfer can be done in any of the three modes (simple, Linear or Linked * List) based on the selected mode but before calling this API make sure that * ZDMA is in Idle state. * * @param InstancePtr is a pointer to the XZDma instance. * @param Data is a pointer of array to the XZDma_Transfer structure which * has all the configuration fields for initiating data transfer. * The fields of the structure are: * - SrcAddr - Source address * - DstAddr - Destination address * - Size - size of the data to be transferred in bytes * - SrcCoherent - AXI transactions generated to process the * descriptor payload for source channel * - 0 - Non coherent * - 1 - Coherent * - DstCoherent - AXI transactions generated to process the * descriptor payload for destination channel * - 0 - Non coherent * - 1 - Coherent * - Pause - Valid only for scatter gather mode. * Will pause after completion of this descriptor. * @param Num specifies number of array elements of Data pointer. * - For simple mode Num should be equal to 1 * - For Scatter gather mode (either linear or linked list) Num * can be any choice. (But based on which memory should be * allocated by Application) It should be less than the return * value of XZDma_CreateBDList. * * @return * - XST_SUCCESS - if ZDMA initiated the transfer. * - XST_FAILURE - if ZDMA has not initiated data transfer. * * @note After Pause to resume the transfer need to use the following * API * - XZDma_Resume * User should provide allocated memory and descriptor type in * scatter gather mode through the following API before calling * the start API. * - XZDma_SetDescriptorType(XZDma *InstancePtr, * XZDma_DscrType TypeOfDscr, UINTPTR Dscr_MemPtr, * u32 NoOfBytes) * ******************************************************************************/ s32 XZDma_Start(XZDma *InstancePtr, XZDma_Transfer *Data, u32 Num) { s32 Status; /* Verify arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(Data != NULL); Xil_AssertNonvoid(Num != 0x00U); if ((InstancePtr->ChannelState == XZDMA_BUSY) && (Num >= InstancePtr->Descriptor.DscrCount)) { Status = XST_FAILURE; } else { if (InstancePtr->IsSgDma != TRUE) { XZDma_SimpleMode(InstancePtr, Data); Status = XST_SUCCESS; } else { XZDma_ScatterGather(InstancePtr, Data, Num); Status = XST_SUCCESS; } XZDma_Enable(InstancePtr); } return Status; } /*****************************************************************************/ /** * * This static function sets all the required fields for initiating data * transfer in simple mode. * * @param InstancePtr is a pointer to the XZDma instance. * @param Data is a pointer of array to the XZDma_Transfer structure * which has all the configuration fields for initiating data * transfer. * * @return None. * * @note None. * ******************************************************************************/ static void XZDma_SimpleMode(XZDma *InstancePtr, XZDma_Transfer *Data) { u32 Value; /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Data != NULL); XZDma_WriteReg((InstancePtr->Config.BaseAddress), XZDMA_CH_SRC_DSCR_WORD0_OFFSET, (Data->SrcAddr & XZDMA_WORD0_LSB_MASK)); XZDma_WriteReg((InstancePtr->Config.BaseAddress), XZDMA_CH_SRC_DSCR_WORD1_OFFSET, (((u64)Data->SrcAddr >> XZDMA_WORD1_MSB_SHIFT) & XZDMA_WORD1_MSB_MASK)); XZDma_WriteReg((InstancePtr->Config.BaseAddress), XZDMA_CH_DST_DSCR_WORD0_OFFSET, (Data->DstAddr & XZDMA_WORD0_LSB_MASK)); XZDma_WriteReg((InstancePtr->Config.BaseAddress), XZDMA_CH_DST_DSCR_WORD1_OFFSET, (((u64)Data->DstAddr >> XZDMA_WORD1_MSB_SHIFT) & XZDMA_WORD1_MSB_MASK)); XZDma_WriteReg((InstancePtr->Config.BaseAddress), XZDMA_CH_SRC_DSCR_WORD2_OFFSET, (Data->Size & XZDMA_WORD2_SIZE_MASK)); XZDma_WriteReg((InstancePtr->Config.BaseAddress), XZDMA_CH_DST_DSCR_WORD2_OFFSET, (Data->Size & XZDMA_WORD2_SIZE_MASK)); Value = (u32)(Data->SrcCoherent & XZDMA_WORD3_COHRNT_MASK); XZDma_WriteReg((InstancePtr->Config.BaseAddress), XZDMA_CH_SRC_DSCR_WORD3_OFFSET, Value); Value = (u32)(Data->DstCoherent & XZDMA_WORD3_COHRNT_MASK); XZDma_WriteReg((InstancePtr->Config.BaseAddress), XZDMA_CH_DST_DSCR_WORD3_OFFSET, Value); } /*****************************************************************************/ /** * * This static function sets all the required fields for initiating data * transfer in scatter gather mode. * * @param InstancePtr is a pointer to the XZDma instance. * @param Data is a pointer of array to the XZDma_Transfer structure * which has all the configuration fields for initiating data * transfer. * @param Num specifies number of array elements of Data pointer. * * @return None. * * @note None. * ******************************************************************************/ static void XZDma_ScatterGather(XZDma *InstancePtr, XZDma_Transfer *Data, u32 Num) { u32 Count = 0x00U; u8 Last; XZDma_Transfer *LocalData = Data; XZDma_LiDscr *LiSrcDscr = (XZDma_LiDscr *)(void *)(InstancePtr->Descriptor.SrcDscrPtr); XZDma_LiDscr *LiDstDscr = (XZDma_LiDscr *)(void *)(InstancePtr->Descriptor.DstDscrPtr); XZDma_LlDscr *LlSrcDscr = (XZDma_LlDscr *)(void *)(InstancePtr->Descriptor.SrcDscrPtr); XZDma_LlDscr *LlDstDscr = (XZDma_LlDscr *)(void *)(InstancePtr->Descriptor.DstDscrPtr); /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Data != NULL); Xil_AssertVoid(Num != 0x00U); if (InstancePtr->Descriptor.DscrType == XZDMA_LINEAR) { Last = FALSE; do { if (Count == (Num- 1)) { Last = TRUE; } XZDma_LinearMode(InstancePtr, LocalData, LiSrcDscr, LiDstDscr, Last); Count++; LiSrcDscr++; LiDstDscr++; LocalData++; } while(Count < Num); } else { Last = FALSE; do { if (Count == (Num - 1)) { Last = TRUE; } XZDma_LinkedListMode(InstancePtr, LocalData, LlSrcDscr, LlDstDscr, Last); Count++; LlDstDscr++; LlSrcDscr++; LocalData++; } while(Count < Num); } XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_SRC_START_LSB_OFFSET, ((UINTPTR)(InstancePtr->Descriptor.SrcDscrPtr) & XZDMA_WORD0_LSB_MASK)); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_SRC_START_MSB_OFFSET, (((u64)(UINTPTR)(InstancePtr->Descriptor.SrcDscrPtr) >> XZDMA_WORD1_MSB_SHIFT) & XZDMA_WORD1_MSB_MASK)); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_DST_START_LSB_OFFSET, ((UINTPTR)(InstancePtr->Descriptor.DstDscrPtr) & XZDMA_WORD0_LSB_MASK)); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_DST_START_MSB_OFFSET, (((u64)(UINTPTR)(InstancePtr->Descriptor.DstDscrPtr) >> XZDMA_WORD1_MSB_SHIFT) & XZDMA_WORD1_MSB_MASK)); } /*****************************************************************************/ /** * * This static function sets all the required fields for initiating data * transfer in Linear descriptor type. * * @param InstancePtr is a pointer to the XZDma instance. * @param Data is a pointer of array to the XZDma_Transfer structure which * has all the configuration fields for initiating data transfer. * @param SrcDscrPtr is descriptor pointer of source in which Data fields * has to be filled. * @param DstDscrPtr is descriptor pointer of destination in which Data * fields has to be filled. * @param IsLast specifies whether provided descriptor pointer is last * one or not. * - XZDMA_TRUE - If descriptor is last * - XZDMA_FALSE - If descriptor is not last * * @return None. * * @note None. * ******************************************************************************/ static void XZDma_LinearMode(XZDma *InstancePtr, XZDma_Transfer *Data, XZDma_LiDscr *SrcDscrPtr, XZDma_LiDscr *DstDscrPtr, u8 IsLast) { u32 Value; /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Data != NULL); Xil_AssertVoid(SrcDscrPtr != NULL); Xil_AssertVoid(DstDscrPtr != NULL); Xil_AssertVoid((IsLast == TRUE) || (IsLast == FALSE)); if (Data->Pause == TRUE) { Value = XZDMA_WORD3_CMD_PAUSE_MASK; } else if (IsLast == TRUE) { Value = XZDMA_WORD3_CMD_STOP_MASK; } else { Value = XZDMA_WORD3_CMD_NXTVALID_MASK; } if (Data->SrcCoherent == TRUE) { Value |= XZDMA_WORD3_COHRNT_MASK; } XZDma_ConfigLinear(SrcDscrPtr, (u64)Data->SrcAddr, Data->Size, Value); Value = 0U; if (Data->DstCoherent == TRUE) { Value |= XZDMA_WORD3_COHRNT_MASK; } XZDma_ConfigLinear(DstDscrPtr, (u64)Data->DstAddr, Data->Size, Value); } /*****************************************************************************/ /** * * This static function sets all the required fields for initiating data * transfer in Linear descriptor type. * * @param DscrPtr is a pointer to source/destination descriptor. * @param Addr is a 64 bit variable which denotes the address of data. * @param Size specifies the amount of the data to be transferred. * @param CtrlValue contains all the control fields of descriptor. * * @return None. * * @note None. * ******************************************************************************/ static void XZDma_ConfigLinear(XZDma_LiDscr *DscrPtr, u64 Addr, u32 Size, u32 CtrlValue) { /* Verify arguments */ Xil_AssertVoid(DscrPtr != NULL); Xil_AssertVoid(Addr != 0x00U); DscrPtr->Address = Addr; DscrPtr->Size = Size & XZDMA_WORD2_SIZE_MASK; DscrPtr->Cntl = CtrlValue; Xil_DCacheFlushRange((UINTPTR)DscrPtr, sizeof(XZDma_LlDscr)); } /*****************************************************************************/ /** * * This static function sets all the required fields for initiating data * transfer in Linked list descriptor type. * * @param InstancePtr is a pointer to the XZDma instance. * @param Data is a pointer of array to the XZDma_Transfer structure which * has all the configuration fields for initiating data transfer. * @param SrcDscrPtr is descriptor pointer of source in which Data fields * has to be filled. * @param DstDscrPtr is descriptor pointer of destination in which Data * fields has to be filled. * @param IsLast specifies whether provided descriptor pointer is last * one or not. * - TRUE - If descriptor is last * - FALSE - If descriptor is not last * * @return None. * * @note None. * ******************************************************************************/ static void XZDma_LinkedListMode(XZDma *InstancePtr, XZDma_Transfer *Data, XZDma_LlDscr *SrcDscrPtr,XZDma_LlDscr *DstDscrPtr, u8 IsLast) { u32 Value; XZDma_LlDscr *NextSrc = SrcDscrPtr; XZDma_LlDscr *NextDst = DstDscrPtr; u64 NextSrcAdrs = 0x00U; u64 NextDstAdrs = 0x00U; /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Data != NULL); Xil_AssertVoid(SrcDscrPtr != NULL); Xil_AssertVoid(DstDscrPtr != NULL); Xil_AssertVoid((IsLast == TRUE) || (IsLast == FALSE)); NextDst++; NextSrc++; if (Data->Pause == TRUE) { Value = XZDMA_WORD3_CMD_PAUSE_MASK; if (IsLast != TRUE) { NextSrcAdrs = (u64)(UINTPTR)NextSrc; NextDstAdrs = (u64)(UINTPTR)NextDst; } } else if (IsLast == TRUE) { Value = XZDMA_WORD3_CMD_STOP_MASK; } else { Value = XZDMA_WORD3_CMD_NXTVALID_MASK; NextSrcAdrs = (u64)(UINTPTR)NextSrc; NextDstAdrs = (u64)(UINTPTR)NextDst; } if (Data->SrcCoherent == TRUE) { Value |= XZDMA_WORD3_COHRNT_MASK; } XZDma_ConfigLinkedList(SrcDscrPtr, (u64)Data->SrcAddr, Data->Size, Value, NextSrcAdrs); Value = 0U; if (Data->DstCoherent == TRUE) { Value |= XZDMA_WORD3_COHRNT_MASK; } XZDma_ConfigLinkedList(DstDscrPtr, (u64)Data->DstAddr, Data->Size, Value, NextDstAdrs); } /*****************************************************************************/ /** * * This static function sets all the required fields for initiating data * transfer in Linked list descriptor type. * * @param DscrPtr is a pointer to source/destination descriptor. * @param Addr is a 64 bit variable which denotes the address of data. * @param Size specifies the amount of the data to be transferred. * @param CtrlValue contains all the control fields of descriptor. * @param NextDscrAddr is the address of next descriptor. * * @return None. * * @note None. * ******************************************************************************/ static void XZDma_ConfigLinkedList(XZDma_LlDscr *DscrPtr, u64 Addr, u32 Size, u32 CtrlValue, u64 NextDscrAddr) { /* Verify arguments */ Xil_AssertVoid(DscrPtr != NULL); Xil_AssertVoid(Addr != 0x00U); DscrPtr->Address = Addr; DscrPtr->Size = Size & XZDMA_WORD2_SIZE_MASK; DscrPtr->Cntl = CtrlValue; DscrPtr->NextDscr = NextDscrAddr; DscrPtr->Reserved = 0U; Xil_DCacheFlushRange((UINTPTR)DscrPtr, sizeof(XZDma_LlDscr)); } /*****************************************************************************/ /** * This static function enable's all the interrupts which user intended to * enable and enables the ZDMA channel for initiating data transfer. * * @param InstancePtr is a pointer to the XZDma instance. * @return None. * * @note None. * ******************************************************************************/ static void XZDma_Enable(XZDma *InstancePtr) { /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); XZDma_WriteReg(InstancePtr->Config.BaseAddress, XZDMA_CH_IEN_OFFSET, (InstancePtr->IntrMask & XZDMA_IXR_ALL_INTR_MASK)); InstancePtr->ChannelState = XZDMA_BUSY; XZDma_EnableCh(InstancePtr); } /*****************************************************************************/ /** * This static function gets all the reset configurations of ZDMA. * * @param InstancePtr is a pointer to the XZDma instance. * * @return None. * * @note None. * ******************************************************************************/ static void XZDma_GetConfigurations(XZDma *InstancePtr) { /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); InstancePtr->DataConfig.SrcIssue = (u8)XZDMA_CTRL1_SRC_ISSUE_MASK; InstancePtr->DataConfig.SrcBurstType = XZDMA_INCR_BURST; InstancePtr->DataConfig.SrcBurstLen = 0xFU; InstancePtr->DataConfig.OverFetch = 1U; InstancePtr->DataConfig.DstBurstType = XZDMA_INCR_BURST; InstancePtr->DataConfig.DstBurstLen = 0xFU; InstancePtr->DataConfig.SrcCache = 0x2U; InstancePtr->DataConfig.DstCache = 0x2U; InstancePtr->DataConfig.SrcQos = 0x0U; InstancePtr->DataConfig.DstQos = 0x0U; InstancePtr->DscrConfig.AXCache = 0U; InstancePtr->DscrConfig.AXQos = 0U; InstancePtr->DscrConfig.AxCoherent = 0U; } /*****************************************************************************/ /** * * This routine is a stub for the asynchronous callbacks. The stub is here in * case the upper layer forgot to set the handlers. On initialization, All * handlers are set to this callback. It is considered an error for this * handler to be invoked. * * @param CallBackRef is a callback reference passed in by the upper * layer when setting the callback functions, and passed back to * the upper layer when the callback is invoked. * @param Mask is the type of the interrupts to enable. Use OR'ing of * XZDMA_IXR_DMA_*_MASK constants defined in xzdma_hw.h to create * this parameter value. * * @return None. * * @note None. * ******************************************************************************/ static void StubCallBack(void *CallBackRef, u32 Mask) { /* Verify arguments. */ Xil_AssertVoid(CallBackRef != NULL); Xil_AssertVoid(Mask != (u32)0x00); Xil_AssertVoidAlways(); } /*****************************************************************************/ /** * * This routine is a stub for the DMA done callback. The stub is here in * case the upper layer forgot to set the handlers. On initialization, Done * handler are set to this callback. * * @param CallBackRef is a callback reference passed in by the upper * layer when setting the callback functions, and passed back to * the upper layer when the callback is invoked. * * @return None. * * @note None. * ******************************************************************************/ static void StubDoneCallBack(void *CallBackRef) { /* Verify arguments. */ Xil_AssertVoid(CallBackRef != NULL); Xil_AssertVoidAlways(); }