diff --git a/XilinxProcessorIPLib/drivers/axivdma/data/axivdma.mdd b/XilinxProcessorIPLib/drivers/axivdma/data/axivdma.mdd new file mode 100755 index 00000000..6ffd7489 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/data/axivdma.mdd @@ -0,0 +1,43 @@ +############################################################################### +# +# 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. +# +############################################################################## + +OPTION psf_version = 2.1; + +BEGIN driver axivdma + + OPTION supported_peripherals = (axi_vdma_v[4-9]_[0-9][0-9]_[a-z] axi_vdma_v[4-9]_[0-9]); + OPTION driver_state = ACTIVE; + OPTION copyfiles = all; + OPTION VERSION = 5.1; + OPTION NAME = axivdma; + +END driver diff --git a/XilinxProcessorIPLib/drivers/axivdma/data/axivdma.tcl b/XilinxProcessorIPLib/drivers/axivdma/data/axivdma.tcl new file mode 100755 index 00000000..bdc3f38c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/data/axivdma.tcl @@ -0,0 +1,204 @@ +############################################################################### +# +# 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 axivdma_v2_1_0.tcl +# +# +#
+# MODIFICATION HISTORY:
+#
+# Ver   Who  Date     Changes
+# ----- ---- -------- -------------------------------------------------------
+# 3.00a srt  08/26/11 Added new parameters for Flush on Frame Sync and Line
+#		      Buffer Thresholds.
+# 4.00a srt  11/21/11 Added new parameters for Genlock Source and Fsync
+#		      Source Selection.
+# 4.03a srt  01/18/13 Added TDATA_WIDTH parameters (CR: 691866)
+# 4.04a srt  03/01/13 Added DEBUG_INFO parameters (CR: 703738)
+# 4.05a srt  05/01/3  Merged v4.03a driver with v4.04a driver.
+#		         Driver v4.03a - Supports VDMA IPv5.04a XPS release
+#		         Driver v4.04a - Supports VDMA IPv6.00a IPI release
+#	              The parameters C_ENABLE_DEBUG_* are only available in
+#		      VDMA IPv6.00a. These parameters should be set to '1'
+#		      for older versions of IP (XPS) and added this logic in
+#		      this file.
+#  5.0     adk    10/12/13 Updated as per the New Tcl API's
+# 
+# +############################################################################## + + +#uses "xillib.tcl" + +proc generate {drv_handle} { + xdefine_vdma_include_file $drv_handle "xparameters.h" "XAxiVdma" "NUM_INSTANCES" "DEVICE_ID" "C_BASEADDR" "C_HIGHADDR" "C_NUM_FSTORES" "C_INCLUDE_MM2S" "C_INCLUDE_MM2S_DRE" "C_M_AXI_MM2S_DATA_WIDTH" "C_INCLUDE_S2MM" "C_INCLUDE_S2MM_DRE" "C_M_AXI_S2MM_DATA_WIDTH" "C_AXI_MM2S_ACLK_FREQ_HZ" "C_AXI_S2MM_ACLK_FREQ_HZ" "C_MM2S_GENLOCK_MODE" "C_MM2S_GENLOCK_NUM_MASTERS" "C_S2MM_GENLOCK_MODE" "C_S2MM_GENLOCK_NUM_MASTERS" "C_INCLUDE_SG" "C_ENABLE_VIDPRMTR_READS" "C_USE_FSYNC" "C_FLUSH_ON_FSYNC" "C_MM2S_LINEBUFFER_DEPTH" "C_S2MM_LINEBUFFER_DEPTH" "C_INCLUDE_INTERNAL_GENLOCK" "C_S2MM_SOF_ENABLE" "C_M_AXIS_MM2S_TDATA_WIDTH" "C_S_AXIS_S2MM_TDATA_WIDTH" "C_ENABLE_DEBUG_INFO_1" "C_ENABLE_DEBUG_INFO_5" "C_ENABLE_DEBUG_INFO_6" "C_ENABLE_DEBUG_INFO_7" "C_ENABLE_DEBUG_INFO_9" "C_ENABLE_DEBUG_INFO_13" "C_ENABLE_DEBUG_INFO_14" "C_ENABLE_DEBUG_INFO_15" "C_ENABLE_DEBUG_ALL" + xdefine_vdma_canonical_xpars $drv_handle "xparameters.h" "AxiVdma" "DEVICE_ID" "C_BASEADDR" "C_HIGHADDR" "C_NUM_FSTORES" "C_INCLUDE_MM2S" "C_INCLUDE_MM2S_DRE" "C_M_AXI_MM2S_DATA_WIDTH" "C_INCLUDE_S2MM" "C_INCLUDE_S2MM_DRE" "C_M_AXI_S2MM_DATA_WIDTH" "C_AXI_MM2S_ACLK_FREQ_HZ" "C_AXI_S2MM_ACLK_FREQ_HZ" "C_MM2S_GENLOCK_MODE" "C_MM2S_GENLOCK_NUM_MASTERS" "C_S2MM_GENLOCK_MODE" "C_S2MM_GENLOCK_NUM_MASTERS" "C_INCLUDE_SG" "C_ENABLE_VIDPRMTR_READS" "C_USE_FSYNC" "C_FLUSH_ON_FSYNC" "C_MM2S_LINEBUFFER_DEPTH" "C_S2MM_LINEBUFFER_DEPTH" "C_INCLUDE_INTERNAL_GENLOCK" "C_S2MM_SOF_ENABLE" "C_M_AXIS_MM2S_TDATA_WIDTH" "C_S_AXIS_S2MM_TDATA_WIDTH" "C_ENABLE_DEBUG_INFO_1" "C_ENABLE_DEBUG_INFO_5" "C_ENABLE_DEBUG_INFO_6" "C_ENABLE_DEBUG_INFO_7" "C_ENABLE_DEBUG_INFO_9" "C_ENABLE_DEBUG_INFO_13" "C_ENABLE_DEBUG_INFO_14" "C_ENABLE_DEBUG_INFO_15" "C_ENABLE_DEBUG_ALL" + xdefine_config_file $drv_handle "xaxivdma_g.c" "XAxiVdma" "DEVICE_ID" "C_BASEADDR" "C_NUM_FSTORES" "C_INCLUDE_MM2S" "C_INCLUDE_MM2S_DRE" "C_M_AXI_MM2S_DATA_WIDTH" "C_INCLUDE_S2MM" "C_INCLUDE_S2MM_DRE" "C_M_AXI_S2MM_DATA_WIDTH" "C_INCLUDE_SG" "C_ENABLE_VIDPRMTR_READS" "C_USE_FSYNC" "C_FLUSH_ON_FSYNC" "C_MM2S_LINEBUFFER_DEPTH" "C_S2MM_LINEBUFFER_DEPTH" "C_MM2S_GENLOCK_MODE" "C_S2MM_GENLOCK_MODE" "C_INCLUDE_INTERNAL_GENLOCK" "C_S2MM_SOF_ENABLE" "C_M_AXIS_MM2S_TDATA_WIDTH" "C_S_AXIS_S2MM_TDATA_WIDTH" "C_ENABLE_DEBUG_INFO_1" "C_ENABLE_DEBUG_INFO_5" "C_ENABLE_DEBUG_INFO_6" "C_ENABLE_DEBUG_INFO_7" "C_ENABLE_DEBUG_INFO_9" "C_ENABLE_DEBUG_INFO_13" "C_ENABLE_DEBUG_INFO_14" "C_ENABLE_DEBUG_INFO_15" "C_ENABLE_DEBUG_ALL" +} + + +proc xdefine_vdma_include_file {drv_handle file_name drv_string args} { + # Open include file + set file_handle [hsi::utils::open_include_file $file_name] + + # Get all peripherals connected to this driver + set periphs [hsi::utils::get_common_driver_ips $drv_handle] + + # Handle special cases + set arg "NUM_INSTANCES" + set posn [lsearch -exact $args $arg] + if {$posn > -1} { + puts $file_handle "/* Definitions for driver [string toupper [get_property NAME $drv_handle]] */" + # Define NUM_INSTANCES + puts $file_handle "#define [hsi::utils::get_driver_param_name $drv_string $arg] [llength $periphs]" + set args [lreplace $args $posn $posn] + } + # Check if it is a driver parameter + + lappend newargs + foreach arg $args { + set value [get_property CONFIG.$arg $drv_handle] + if {[llength $value] == 0} { + lappend newargs $arg + } else { + puts $file_handle "#define [hsi::utils::get_driver_param_name $drv_string $arg] [get_property CONFIG.$arg $drv_handle]" + } + } + set args $newargs + + # Print all parameters for all peripherals + set device_id 0 + foreach periph $periphs { + puts $file_handle "" + puts $file_handle "/* Definitions for peripheral [string toupper [get_property NAME $periph]] */" + foreach arg $args { + if {[string compare -nocase "DEVICE_ID" $arg] == 0} { + set value $device_id + incr device_id + } else { + set value [::hsi::utils::get_param_value $periph $arg] + } + if {[llength $value] == 0} { + set value 0 + } + # Check for *_ENABLE_DEBUG_* parameters. These parameters are applicable + # to VDMA IPv6.00a (IPI release). For all the previous versions these + # parameters should be set. + if {[string first "ENABLE_DEBUG" $arg] >= 0} { + set foundparam [::hsi::utils::get_param_value $periph $arg] + if {[llength $foundparam] == 0} { + set value 1 + } + } + set value [hsi::utils::format_addr_string $value $arg] + if {[string compare -nocase "HW_VER" $arg] == 0} { + puts $file_handle "#define [hsi::utils::get_ip_param_name $periph $arg] \"$value\"" + } else { + puts $file_handle "#define [hsi::utils::get_ip_param_name $periph $arg] $value" + } + } + puts $file_handle "" + } + puts $file_handle "\n/******************************************************************/\n" + close $file_handle +} + +proc xdefine_vdma_canonical_xpars {drv_handle file_name drv_string args} { + # Open include file + set file_handle [hsi::utils::open_include_file $file_name] + + # Get all the peripherals connected to this driver + set periphs [hsi::utils::get_common_driver_ips $drv_handle] + + # Get the names of all the peripherals connected to this driver + foreach periph $periphs { + set peripheral_name [string toupper [get_property NAME $periph]] + lappend peripherals $peripheral_name + } + + # Get possible canonical names for all the peripherals connected to this + # driver + set device_id 0 + foreach periph $periphs { + set canonical_name [string toupper [format "%s_%s" $drv_string $device_id]] + lappend canonicals $canonical_name + + # Create a list of IDs of the peripherals whose hardware instance name + # doesn't match the canonical name. These IDs can be used later to + # generate canonical definitions + if { [lsearch $peripherals $canonical_name] < 0 } { + lappend indices $device_id + } + incr device_id + } + + set i 0 + foreach periph $periphs { + set periph_name [string toupper [get_property NAME $periph]] + + # Generate canonical definitions only for the peripherals whose + # canonical name is not the same as hardware instance name + if { [lsearch $canonicals $periph_name] < 0 } { + puts $file_handle "/* Canonical definitions for peripheral $periph_name */" + set canonical_name [format "%s_%s" $drv_string [lindex $indices $i]] + + foreach arg $args { + set lvalue [hsi::utils::get_driver_param_name $canonical_name $arg] + + # The commented out rvalue is the name of the instance-specific constant + # set rvalue [hsi::utils::get_driver_param_name $periph $arg] + # The rvalue set below is the actual value of the parameter + set rvalue [::hsi::utils::get_param_value $periph $arg] + if {[llength $rvalue] == 0} { + set rvalue 0 + } + # Check for *_ENABLE_DEBUG_* parameters. These parameters are applicable + # to VDMA IPv6.00a (IPI release). For all the previous versions these + # parameters should be set. + if {[string first "ENABLE_DEBUG" $arg] >= 0} { + set foundparam [::hsi::utils::get_param_value $periph $arg] + if {[llength $foundparam] == 0} { + set rvalue 1 + } + } + set rvalue [hsi::utils::format_addr_string $rvalue $arg] + + puts $file_handle "#define $lvalue $rvalue" + + } + puts $file_handle "" + incr i + } + } + + puts $file_handle "\n/******************************************************************/\n" + close $file_handle +} diff --git a/XilinxProcessorIPLib/drivers/axivdma/examples/index.html b/XilinxProcessorIPLib/drivers/axivdma/examples/index.html new file mode 100755 index 00000000..7d86c0f4 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/examples/index.html @@ -0,0 +1,17 @@ + + + + + +Driver example applications + + + +

Example Applications for the driver axivdma_v5_0

+
+ +

Copyright � 1995-2014 Xilinx, Inc. All rights reserved.

+ + \ No newline at end of file diff --git a/XilinxProcessorIPLib/drivers/axivdma/examples/xaxivdma_example_intr.c b/XilinxProcessorIPLib/drivers/axivdma/examples/xaxivdma_example_intr.c new file mode 100644 index 00000000..26ac2357 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/examples/xaxivdma_example_intr.c @@ -0,0 +1,911 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 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 xaxivdma_example_intr.c + * + * This example demonstrates how to use the AXI Video DMA with other video IPs + * to do video frame transfers. This example does not work by itself. It needs + * two other Video IPs, one for writing video frames to the memory and one for + * reading video frames from the memory. + * + * To see the debug print, you need a Uart16550 or uartlite in your system, + * and please set "-DDEBUG" in your compiler options. You need to rebuild your + * software executable. + * + * @note + * The values of DDR_BASE_ADDR and DDR_HIGH_ADDR should be as per the HW system. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a jz   07/26/10 First release
+ * 1.01a jz   09/26/10 Updated callback function signature
+ * 2.00a jz   12/10/10 Added support for direct register access mode, v3 core
+ * 2.01a rvp  01/22/11 Renamed the example file to be consistent
+ * 		       Added support to the example to use SCU GIC interrupt
+ *		       controller for ARM, some functions in this example have
+ *		       changed.
+ *       rkv  03/28/11 Updated to support for frame store register.
+ * 3.00a srt  08/26/11 Added support for Flush on Frame Sync Feature.
+ * 4.00a srt  03/06/12 Modified interrupt support for Zynq.
+ * 4.02a srt  09/25/12 Fixed CR 677704
+ *		       Description - Arguments misused in function
+ *                     XAxiVdma_IntrEnable().
+ * 4.03a srt  03/01/13 Updated DDR base address for IPI designs (CR 703656).
+ * 
+ * + * *************************************************************************** + */ + +#include "xaxivdma.h" +#include "xparameters.h" +#include "xil_exception.h" + +#ifdef XPAR_INTC_0_DEVICE_ID +#include "xintc.h" +#else +#include "xscugic.h" +#endif + +#ifndef __MICROBLAZE__ +#include "xpseudo_asm_gcc.h" +#include "xreg_cortexa9.h" +#endif + +#if defined(XPAR_UARTNS550_0_BASEADDR) +#include "xuartns550_l.h" /* to use uartns550 */ +#endif + +/******************** Constant Definitions **********************************/ + +/* + * Device related constants. These need to defined as per the HW system. + */ +#define DMA_DEVICE_ID XPAR_AXIVDMA_0_DEVICE_ID + +#ifdef XPAR_INTC_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#define WRITE_INTR_ID XPAR_INTC_0_AXIVDMA_0_S2MM_INTROUT_VEC_ID +#define READ_INTR_ID XPAR_INTC_0_AXIVDMA_0_MM2S_INTROUT_VEC_ID +#else +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#define WRITE_INTR_ID XPAR_FABRIC_AXIVDMA_0_S2MM_INTROUT_VEC_ID +#define READ_INTR_ID XPAR_FABRIC_AXIVDMA_0_MM2S_INTROUT_VEC_ID +#endif + +#ifdef XPAR_V6DDR_0_S_AXI_BASEADDR +#define DDR_BASE_ADDR XPAR_V6DDR_0_S_AXI_BASEADDR +#define DDR_HIGH_ADDR XPAR_V6DDR_0_S_AXI_HIGHADDR +#elif XPAR_S6DDR_0_S0_AXI_BASEADDR +#define DDR_BASE_ADDR XPAR_S6DDR_0_S0_AXI_BASEADDR +#define DDR_HIGH_ADDR XPAR_S6DDR_0_S0_AXI_HIGHADDR +#elif XPAR_AXI_7SDDR_0_S_AXI_BASEADDR +#define DDR_BASE_ADDR XPAR_AXI_7SDDR_0_S_AXI_BASEADDR +#define DDR_HIGH_ADDR XPAR_AXI_7SDDR_0_S_AXI_HIGHADDR +#elif XPAR_MIG7SERIES_0_BASEADDR +#define DDR_BASE_ADDR XPAR_MIG7SERIES_0_BASEADDR +#define DDR_HIGH_ADDR XPAR_MIG7SERIES_0_HIGHADDR +#else +#warning CHECK FOR THE VALID DDR ADDRESS IN XPARAMETERS.H, \ + DEFAULT SET TO 0x01000000 +#define DDR_BASE_ADDR 0x01000000 +#define DDR_HIGH_ADDR 0x0F000000 +#endif + +/* Memory space for the frame buffers + * + * This example only needs one set of frame buffers, because one video IP is + * to write to the frame buffers, and the other video IP is to read from the + * frame buffers. + * + * For 16 frames of 1080p, it needs 0x07E90000 memory for frame buffers + */ +#define MEM_BASE_ADDR (DDR_BASE_ADDR + 0x01000000) +#define MEM_HIGH_ADDR DDR_HIGH_ADDR +#define MEM_SPACE (MEM_HIGH_ADDR - MEM_BASE_ADDR) + +/* Read channel and write channel start from the same place + * + * One video IP write to the memory region, the other video IP read from it + */ +#define READ_ADDRESS_BASE MEM_BASE_ADDR +#define WRITE_ADDRESS_BASE MEM_BASE_ADDR + +/* Frame size related constants + */ +#define FRAME_HORIZONTAL_LEN 0x1E00 /* 1920 pixels, each pixel 4 bytes */ +#define FRAME_VERTICAL_LEN 0x438 /* 1080 pixels */ + +/* Subframe to be transferred by Video DMA + * + *|<----------------- FRAME_HORIZONTAL_LEN ---------------------->| + * -------------------------------------------------------------------- + *| | ^ + *| | | + *| |<-SUBFRAME_HORIZONTAL_SIZE ->| | FRAME_ + *| ----------------------------------- | VERTICAL_ + *| |/////////////////////////////| ^ | LEN + *| |/////////////////////////////| | | | + *| |/////////////////////////////| | | | + *| |/////////////////////////////| SUBFRAME_ | | + *| |/////////////////////////////| VERTICAL_ | | + *| |/////////////////////////////| SIZE | | + *| |/////////////////////////////| | | | + *| |/////////////////////////////| v | | + *| ---------------------------------- | | + *| | v + *-------------------------------------------------------------------- + * + * Note that SUBFRAME_HORIZONTAL_SIZE and SUBFRAME_VERTICAL_SIZE must ensure + * to be inside the frame. + */ +#define SUBFRAME_START_OFFSET (FRAME_HORIZONTAL_LEN * 5 + 32) +#define SUBFRAME_HORIZONTAL_SIZE 100 +#define SUBFRAME_VERTICAL_SIZE 100 + +/* Number of frames to work on, this is to set the frame count threshold + * + * We multiply 15 to the num stores is to increase the intervals between + * interrupts. If you are using fsync, then it is not necessary. + */ +#define NUMBER_OF_READ_FRAMES 8 +#define NUMBER_OF_WRITE_FRAMES 8 + +/* Number of frames to transfer + * + * This is used to monitor the progress of the test, test purpose only + */ +#define NUM_TEST_FRAME_SETS 10 + +/* Delay timer counter + * + * WARNING: If you are using fsync, please increase the delay counter value + * to be 255. Because with fsync, the inter-frame delay is long. If you do not + * care about inactivity of the hardware, set this counter to be 0, which + * disables delay interrupt. + */ +#define DELAY_TIMER_COUNTER 10 + +/* + * Device instance definitions + */ +XAxiVdma AxiVdma; + +#ifdef XPAR_INTC_0_DEVICE_ID +static XIntc Intc; /* Instance of the Interrupt Controller */ +#else +static XScuGic Intc; /* Instance of the Interrupt Controller */ +#endif + +/* Data address + * + * Read and write sub-frame use the same settings + */ +static u32 ReadFrameAddr; +static u32 WriteFrameAddr; +static u32 BlockStartOffset; +static u32 BlockHoriz; +static u32 BlockVert; + +/* DMA channel setup + */ +static XAxiVdma_DmaSetup ReadCfg; +static XAxiVdma_DmaSetup WriteCfg; + +/* Transfer statics + */ +static int ReadDone; +static int ReadError; +static int WriteDone; +static int WriteError; + +/******************* Function Prototypes ************************************/ + + + +static int ReadSetup(XAxiVdma *InstancePtr); +static int WriteSetup(XAxiVdma * InstancePtr); +static int StartTransfer(XAxiVdma *InstancePtr); + +static int SetupIntrSystem(XAxiVdma *AxiVdmaPtr, u16 ReadIntrId, + u16 WriteIntrId); + +static void DisableIntrSystem(u16 ReadIntrId, u16 WriteIntrId); + +/* Interrupt call back functions + */ +static void ReadCallBack(void *CallbackRef, u32 Mask); +static void ReadErrorCallBack(void *CallbackRef, u32 Mask); +static void WriteCallBack(void *CallbackRef, u32 Mask); +static void WriteErrorCallBack(void *CallbackRef, u32 Mask); + + +#if defined(XPAR_UARTNS550_0_BASEADDR) +/*****************************************************************************/ +/* +* +* Uart16550 setup routine, need to set baudrate to 9600 and data bits to 8 +* +* +******************************************************************************/ +static void Uart550_Setup(void) +{ + + /* Set the baudrate to be predictable + */ + XUartNs550_SetBaud(XPAR_UARTNS550_0_BASEADDR, + XPAR_XUARTNS550_CLOCK_HZ, 9600); + + XUartNs550_SetLineControlReg(XPAR_UARTNS550_0_BASEADDR, + XUN_LCR_8_DATA_BITS); + +} +#endif + +/*****************************************************************************/ +/** +* +* Main function +* +* This function is the main entry point of the example on DMA core. It sets up +* DMA engine to be ready to receive and send frames, and start the transfers. +* It waits for the transfer of the specified number of frame sets, and check +* for transfer errors. +* +* @return +* - XST_SUCCESS if example finishes successfully +* - XST_FAILURE if example fails. +* +* @note None. +* +******************************************************************************/ +int main(void) +{ + int Status; + XAxiVdma_Config *Config; + XAxiVdma_FrameCounter FrameCfg; + +#if defined(XPAR_UARTNS550_0_BASEADDR) + Uart550_Setup(); +#endif + + WriteDone = 0; + ReadDone = 0; + WriteError = 0; + ReadError = 0; + + ReadFrameAddr = READ_ADDRESS_BASE; + WriteFrameAddr = WRITE_ADDRESS_BASE; + BlockStartOffset = SUBFRAME_START_OFFSET; + BlockHoriz = SUBFRAME_HORIZONTAL_SIZE; + BlockVert = SUBFRAME_VERTICAL_SIZE; + + xil_printf("\r\n--- Entering main() --- \r\n"); + + /* The information of the XAxiVdma_Config comes from hardware build. + * The user IP should pass this information to the AXI DMA core. + */ + Config = XAxiVdma_LookupConfig(DMA_DEVICE_ID); + if (!Config) { + xil_printf( + "No video DMA found for ID %d\r\n", DMA_DEVICE_ID); + + return XST_FAILURE; + } + + /* Initialize DMA engine */ + Status = XAxiVdma_CfgInitialize(&AxiVdma, Config, Config->BaseAddress); + if (Status != XST_SUCCESS) { + + xil_printf( + "Configuration Initialization failed %d\r\n", Status); + + return XST_FAILURE; + } + + Status = XAxiVdma_SetFrmStore(&AxiVdma, NUMBER_OF_READ_FRAMES, + XAXIVDMA_READ); + if (Status != XST_SUCCESS) { + + xil_printf( + "Setting Frame Store Number Failed in Read Channel" + " %d\r\n", Status); + + return XST_FAILURE; + } + + Status = XAxiVdma_SetFrmStore(&AxiVdma, NUMBER_OF_WRITE_FRAMES, + XAXIVDMA_WRITE); + if (Status != XST_SUCCESS) { + + xil_printf( + "Setting Frame Store Number Failed in Write Channel" + " %d\r\n", Status); + + return XST_FAILURE; + } + + /* Setup frame counter and delay counter for both channels + * + * This is to monitor the progress of the test only + * + * WARNING: In free-run mode, interrupts may overwhelm the system. + * In that case, it is better to disable interrupts. + */ + FrameCfg.ReadFrameCount = NUMBER_OF_READ_FRAMES; + FrameCfg.WriteFrameCount = NUMBER_OF_WRITE_FRAMES; + FrameCfg.ReadDelayTimerCount = DELAY_TIMER_COUNTER; + FrameCfg.WriteDelayTimerCount = DELAY_TIMER_COUNTER; + + Status = XAxiVdma_SetFrameCounter(&AxiVdma, &FrameCfg); + if (Status != XST_SUCCESS) { + xil_printf( + "Set frame counter failed %d\r\n", Status); + + if(Status == XST_VDMA_MISMATCH_ERROR) + xil_printf("DMA Mismatch Error\r\n"); + + return XST_FAILURE; + } + + /* + * Setup your video IP that writes to the memory + */ + + + /* Setup the write channel + */ + Status = WriteSetup(&AxiVdma); + if (Status != XST_SUCCESS) { + xil_printf( + "Write channel setup failed %d\r\n", Status); + if(Status == XST_VDMA_MISMATCH_ERROR) + xil_printf("DMA Mismatch Error\r\n"); + + return XST_FAILURE; + } + + + /* + * Setup your video IP that reads from the memory + */ + + /* Setup the read channel + */ + Status = ReadSetup(&AxiVdma); + if (Status != XST_SUCCESS) { + xil_printf( + "Read channel setup failed %d\r\n", Status); + if(Status == XST_VDMA_MISMATCH_ERROR) + xil_printf("DMA Mismatch Error\r\n"); + + return XST_FAILURE; + } + + Status = SetupIntrSystem(&AxiVdma, READ_INTR_ID, WRITE_INTR_ID); + if (Status != XST_SUCCESS) { + + xil_printf( + "Setup interrupt system failed %d\r\n", Status); + + return XST_FAILURE; + } + + /* Register callback functions + */ + XAxiVdma_SetCallBack(&AxiVdma, XAXIVDMA_HANDLER_GENERAL, ReadCallBack, + (void *)&AxiVdma, XAXIVDMA_READ); + + XAxiVdma_SetCallBack(&AxiVdma, XAXIVDMA_HANDLER_ERROR, + ReadErrorCallBack, (void *)&AxiVdma, XAXIVDMA_READ); + + XAxiVdma_SetCallBack(&AxiVdma, XAXIVDMA_HANDLER_GENERAL, + WriteCallBack, (void *)&AxiVdma, XAXIVDMA_WRITE); + + XAxiVdma_SetCallBack(&AxiVdma, XAXIVDMA_HANDLER_ERROR, + WriteErrorCallBack, (void *)&AxiVdma, XAXIVDMA_WRITE); + + /* Enable your video IP interrupts if needed + */ + + /* Start the DMA engine to transfer + */ + Status = StartTransfer(&AxiVdma); + if (Status != XST_SUCCESS) { + if(Status == XST_VDMA_MISMATCH_ERROR) + xil_printf("DMA Mismatch Error\r\n"); + return XST_FAILURE; + } + + /* Enable DMA read and write channel interrupts + * + * If interrupts overwhelms the system, please do not enable interrupt + */ + XAxiVdma_IntrEnable(&AxiVdma, XAXIVDMA_IXR_ALL_MASK, XAXIVDMA_WRITE); + XAxiVdma_IntrEnable(&AxiVdma, XAXIVDMA_IXR_ALL_MASK, XAXIVDMA_READ); + + /* Every set of frame buffer finish causes a completion interrupt + */ + while ((WriteDone < NUM_TEST_FRAME_SETS) && !ReadError && + (ReadDone < NUM_TEST_FRAME_SETS) && !WriteError) { + /* NOP */ + } + + if (ReadError || WriteError) { + xil_printf("Test has transfer error %d/%d\r\n", + ReadError, WriteError); + + Status = XST_FAILURE; + } + else { + xil_printf("Test passed\r\n"); + } + + xil_printf("--- Exiting main() --- \r\n"); + + DisableIntrSystem(READ_INTR_ID, WRITE_INTR_ID); + + if (Status != XST_SUCCESS) { + if(Status == XST_VDMA_MISMATCH_ERROR) + xil_printf("DMA Mismatch Error\r\n"); + return XST_FAILURE; + } + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* +* This function sets up the read channel +* +* @param InstancePtr is the instance pointer to the DMA engine. +* +* @return XST_SUCCESS if the setup is successful, XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +static int ReadSetup(XAxiVdma *InstancePtr) +{ + int Index; + u32 Addr; + int Status; + + ReadCfg.VertSizeInput = SUBFRAME_VERTICAL_SIZE; + ReadCfg.HoriSizeInput = SUBFRAME_HORIZONTAL_SIZE; + + ReadCfg.Stride = FRAME_HORIZONTAL_LEN; + ReadCfg.FrameDelay = 0; /* This example does not test frame delay */ + + ReadCfg.EnableCircularBuf = 1; + ReadCfg.EnableSync = 0; /* No Gen-Lock */ + + ReadCfg.PointNum = 0; /* No Gen-Lock */ + ReadCfg.EnableFrameCounter = 0; /* Endless transfers */ + + ReadCfg.FixedFrameStoreAddr = 0; /* We are not doing parking */ + + Status = XAxiVdma_DmaConfig(InstancePtr, XAXIVDMA_READ, &ReadCfg); + if (Status != XST_SUCCESS) { + xil_printf( + "Read channel config failed %d\r\n", Status); + + return XST_FAILURE; + } + + /* Initialize buffer addresses + * + * These addresses are physical addresses + */ + Addr = READ_ADDRESS_BASE + BlockStartOffset; + for(Index = 0; Index < NUMBER_OF_READ_FRAMES; Index++) { + ReadCfg.FrameStoreStartAddr[Index] = Addr; + + Addr += FRAME_HORIZONTAL_LEN * FRAME_VERTICAL_LEN; + } + + /* Set the buffer addresses for transfer in the DMA engine + * The buffer addresses are physical addresses + */ + Status = XAxiVdma_DmaSetBufferAddr(InstancePtr, XAXIVDMA_READ, + ReadCfg.FrameStoreStartAddr); + if (Status != XST_SUCCESS) { + xil_printf( + "Read channel set buffer address failed %d\r\n", Status); + + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function sets up the write channel +* +* @param InstancePtr is the instance pointer to the DMA engine. +* +* @return XST_SUCCESS if the setup is successful, XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +static int WriteSetup(XAxiVdma * InstancePtr) +{ + int Index; + u32 Addr; + int Status; + + WriteCfg.VertSizeInput = SUBFRAME_VERTICAL_SIZE; + WriteCfg.HoriSizeInput = SUBFRAME_HORIZONTAL_SIZE; + + WriteCfg.Stride = FRAME_HORIZONTAL_LEN; + WriteCfg.FrameDelay = 0; /* This example does not test frame delay */ + + WriteCfg.EnableCircularBuf = 1; + WriteCfg.EnableSync = 0; /* No Gen-Lock */ + + WriteCfg.PointNum = 0; /* No Gen-Lock */ + WriteCfg.EnableFrameCounter = 0; /* Endless transfers */ + + WriteCfg.FixedFrameStoreAddr = 0; /* We are not doing parking */ + + Status = XAxiVdma_DmaConfig(InstancePtr, XAXIVDMA_WRITE, &WriteCfg); + if (Status != XST_SUCCESS) { + xil_printf( + "Write channel config failed %d\r\n", Status); + + return XST_FAILURE; + } + + /* Initialize buffer addresses + * + * Use physical addresses + */ + Addr = WRITE_ADDRESS_BASE + BlockStartOffset; + for(Index = 0; Index < NUMBER_OF_WRITE_FRAMES; Index++) { + WriteCfg.FrameStoreStartAddr[Index] = Addr; + + Addr += FRAME_HORIZONTAL_LEN * FRAME_VERTICAL_LEN; + } + + /* Set the buffer addresses for transfer in the DMA engine + */ + Status = XAxiVdma_DmaSetBufferAddr(InstancePtr, XAXIVDMA_WRITE, + WriteCfg.FrameStoreStartAddr); + if (Status != XST_SUCCESS) { + xil_printf( + "Write channel set buffer address failed %d\r\n", Status); + + return XST_FAILURE; + } + + /* Clear data buffer + */ + memset((void *)WriteFrameAddr, 0, + FRAME_HORIZONTAL_LEN * FRAME_VERTICAL_LEN * NUMBER_OF_WRITE_FRAMES); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function starts the DMA transfers. Since the DMA engine is operating +* in circular buffer mode, video frames will be transferred continuously. +* +* @param InstancePtr points to the DMA engine instance +* +* @return XST_SUCCESS if both read and write start succesfully +* XST_FAILURE if one or both directions cannot be started +* +* @note None. +* +******************************************************************************/ +static int StartTransfer(XAxiVdma *InstancePtr) +{ + int Status; + + Status = XAxiVdma_DmaStart(InstancePtr, XAXIVDMA_WRITE); + if (Status != XST_SUCCESS) { + xil_printf( + "Start Write transfer failed %d\r\n", Status); + + return XST_FAILURE; + } + + Status = XAxiVdma_DmaStart(InstancePtr, XAXIVDMA_READ); + if (Status != XST_SUCCESS) { + xil_printf( + "Start read transfer failed %d\r\n", Status); + + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/* +* +* This function setups the interrupt system so interrupts can occur for the +* DMA. This function assumes INTC component exists in the hardware system. +* +* @param AxiDmaPtr is a pointer to the instance of the DMA engine +* @param ReadIntrId is the read channel Interrupt ID. +* @param WriteIntrId is the write channel Interrupt ID. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +static int SetupIntrSystem(XAxiVdma *AxiVdmaPtr, u16 ReadIntrId, + u16 WriteIntrId) +{ + int Status; + +#ifdef XPAR_INTC_0_DEVICE_ID + XIntc *IntcInstancePtr =&Intc; + + + /* Initialize the interrupt controller and connect the ISRs */ + Status = XIntc_Initialize(IntcInstancePtr, INTC_DEVICE_ID); + if (Status != XST_SUCCESS) { + + xil_printf( "Failed init intc\r\n"); + return XST_FAILURE; + } + + Status = XIntc_Connect(IntcInstancePtr, ReadIntrId, + (XInterruptHandler)XAxiVdma_ReadIntrHandler, AxiVdmaPtr); + if (Status != XST_SUCCESS) { + + xil_printf( + "Failed read channel connect intc %d\r\n", Status); + return XST_FAILURE; + } + + Status = XIntc_Connect(IntcInstancePtr, WriteIntrId, + (XInterruptHandler)XAxiVdma_WriteIntrHandler, AxiVdmaPtr); + if (Status != XST_SUCCESS) { + + xil_printf( + "Failed write channel connect intc %d\r\n", Status); + return XST_FAILURE; + } + + /* Start the interrupt controller */ + Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE); + if (Status != XST_SUCCESS) { + + xil_printf( "Failed to start intc\r\n"); + return XST_FAILURE; + } + + /* Enable interrupts from the hardware */ + XIntc_Enable(IntcInstancePtr, ReadIntrId); + XIntc_Enable(IntcInstancePtr, WriteIntrId); + + Xil_ExceptionInit(); + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)XIntc_InterruptHandler, + (void *)IntcInstancePtr); + + Xil_ExceptionEnable(); + +#else + + XScuGic *IntcInstancePtr = &Intc; /* Instance of the Interrupt Controller */ + XScuGic_Config *IntcConfig; + + + /* + * Initialize the interrupt controller driver so that it is ready to + * use. + */ + IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); + if (NULL == IntcConfig) { + return XST_FAILURE; + } + + Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, + IntcConfig->CpuBaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + XScuGic_SetPriorityTriggerType(IntcInstancePtr, ReadIntrId, 0xA0, 0x3); + XScuGic_SetPriorityTriggerType(IntcInstancePtr, WriteIntrId, 0xA0, 0x3); + + /* + * Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. + */ + Status = XScuGic_Connect(IntcInstancePtr, ReadIntrId, + (Xil_InterruptHandler)XAxiVdma_ReadIntrHandler, + AxiVdmaPtr); + if (Status != XST_SUCCESS) { + return Status; + } + + Status = XScuGic_Connect(IntcInstancePtr, WriteIntrId, + (Xil_InterruptHandler)XAxiVdma_WriteIntrHandler, + AxiVdmaPtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* + * Enable the interrupt for the DMA device. + */ + XScuGic_Enable(IntcInstancePtr, ReadIntrId); + XScuGic_Enable(IntcInstancePtr, WriteIntrId); + + Xil_ExceptionInit(); + + /* + * Connect the interrupt controller interrupt handler to the hardware + * interrupt handling logic in the processor. + */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + IntcInstancePtr); + + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnable(); + + +#endif + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function disables the interrupts +* +* @param ReadIntrId is interrupt ID associated w/ DMA read channel +* @param WriteIntrId is interrupt ID associated w/ DMA write channel +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void DisableIntrSystem(u16 ReadIntrId, u16 WriteIntrId) +{ + +#ifdef XPAR_INTC_0_DEVICE_ID + XIntc *IntcInstancePtr =&Intc; + + /* Disconnect the interrupts for the DMA TX and RX channels */ + XIntc_Disconnect(IntcInstancePtr, ReadIntrId); + XIntc_Disconnect(IntcInstancePtr, WriteIntrId); +#else + XScuGic *IntcInstancePtr = &Intc; + + XScuGic_Disable(IntcInstancePtr, ReadIntrId); + XScuGic_Disable(IntcInstancePtr, WriteIntrId); + + XScuGic_Disconnect(IntcInstancePtr, ReadIntrId); + XScuGic_Disconnect(IntcInstancePtr, WriteIntrId); +#endif +} + +/*****************************************************************************/ +/* + * Call back function for read channel + * + * This callback only clears the interrupts and updates the transfer status. + * + * @param CallbackRef is the call back reference pointer + * @param Mask is the interrupt mask passed in from the driver + * + * @return None +* +******************************************************************************/ +static void ReadCallBack(void *CallbackRef, u32 Mask) +{ + + if (Mask & XAXIVDMA_IXR_FRMCNT_MASK) { + ReadDone += 1; + } +} + +/*****************************************************************************/ +/* + * Call back function for read channel error interrupt + * + * @param CallbackRef is the call back reference pointer + * @param Mask is the interrupt mask passed in from the driver + * + * @return None +* +******************************************************************************/ +static void ReadErrorCallBack(void *CallbackRef, u32 Mask) +{ + + if (Mask & XAXIVDMA_IXR_ERROR_MASK) { + ReadError += 1; + } +} + +/*****************************************************************************/ +/* + * Call back function for write channel + * + * This callback only clears the interrupts and updates the transfer status. + * + * @param CallbackRef is the call back reference pointer + * @param Mask is the interrupt mask passed in from the driver + * + * @return None +* +******************************************************************************/ +static void WriteCallBack(void *CallbackRef, u32 Mask) +{ + + if (Mask & XAXIVDMA_IXR_FRMCNT_MASK) { + WriteDone += 1; + } +} + +/*****************************************************************************/ +/* +* Call back function for write channel error interrupt +* +* @param CallbackRef is the call back reference pointer +* @param Mask is the interrupt mask passed in from the driver +* +* @return None +* +******************************************************************************/ +static void WriteErrorCallBack(void *CallbackRef, u32 Mask) +{ + + if (Mask & XAXIVDMA_IXR_ERROR_MASK) { + WriteError += 1; + } +} diff --git a/XilinxProcessorIPLib/drivers/axivdma/src/Makefile b/XilinxProcessorIPLib/drivers/axivdma/src/Makefile new file mode 100644 index 00000000..a837e191 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/src/Makefile @@ -0,0 +1,27 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES=*.c +INCLUDEFILES=*.h + +libs: + echo "Compiling axivdma" + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OUTS} + make clean + +include: + ${CP} $(INCLUDEFILES) $(INCLUDEDIR) + +clean: + rm -rf $(OUTS) diff --git a/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma.c b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma.c new file mode 100644 index 00000000..a4f909be --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma.c @@ -0,0 +1,1388 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 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 xaxivdma.c +* +* Implementation of the driver API functions for the AXI Video DMA engine. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   08/16/10 First release
+* 2.00a jz   12/10/10 Added support for direct register access mode, v3 core
+* 2.01a jz   01/19/11 Added ability to re-assign BD addresses
+* 	rkv  03/28/11 Added support for frame store register.
+* 3.00a srt  08/26/11 Added support for Flush on Frame Sync and dynamic
+*		      programming of Line Buffer Thresholds and added API
+*		      XAxiVdma_SetLineBufThreshold.
+* 4.00a srt  11/21/11 - XAxiVdma_CfgInitialize API is modified to use the
+*			EffectiveAddr.
+*		      - Added APIs:
+*			XAxiVdma_FsyncSrcSelect()
+*			XAxiVdma_GenLockSourceSelect()
+* 4.01a srt  06/13/12 - Added APIs:
+*			XAxiVdma_GetDmaChannelErrors()
+*			XAxiVdma_ClearDmaChannelErrors()
+* 4.02a srt  09/25/12 - Fixed CR 678734
+* 			XAxiVdma_SetFrmStore function changed to remove
+*                       Reset logic after setting number of frame stores.
+* 4.03a srt  01/18/13 - Updated logic of GenLockSourceSelect() & FsyncSrcSelect()
+*                       APIs for newer versions of IP (CR: 691052).
+*		      - Modified CfgInitialize() API to initialize
+*			StreamWidth parameters. (CR 691866)
+* 4.04a srt  03/03/13 - Support for *_ENABLE_DEBUG_INFO_* debug configuration
+*			parameters (CR: 703738)
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xaxivdma.h" +#include "xaxivdma_i.h" + +/************************** Constant Definitions *****************************/ +/* The polling upon starting the hardware + * + * We have the assumption that reset is fast upon hardware start + */ +#define INITIALIZATION_POLLING 100000 + +/*****************************************************************************/ +/** + * Get a channel + * + * @param InstancePtr is the DMA engine to work on + * @param Direction is the direction for the channel to get + * + * @return + * The pointer to the channel. Upon error, return NULL. + * + * @note + * Since this function is internally used, we assume Direction is valid + *****************************************************************************/ +XAxiVdma_Channel *XAxiVdma_GetChannel(XAxiVdma *InstancePtr, + u16 Direction) +{ + + if (Direction == XAXIVDMA_READ) { + return &(InstancePtr->ReadChannel); + } + else if (Direction == XAXIVDMA_WRITE) { + return &(InstancePtr->WriteChannel); + } + else { + xdbg_printf(XDBG_DEBUG_ERROR, + "Invalid direction %x\r\n", Direction); + + return NULL; + } +} + +static int XAxiVdma_Major(XAxiVdma *InstancePtr) { + u32 Reg; + + Reg = XAxiVdma_ReadReg(InstancePtr->BaseAddr, XAXIVDMA_VERSION_OFFSET); + + return (int)((Reg & XAXIVDMA_VERSION_MAJOR_MASK) >> + XAXIVDMA_VERSION_MAJOR_SHIFT); +} + +/*****************************************************************************/ +/** + * Initialize the driver with hardware configuration + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param CfgPtr is the pointer to the hardware configuration structure + * @param EffectiveAddr is the virtual address map for the device + * + * @return + * - XST_SUCCESS if everything goes fine + * - XST_FAILURE if reset the hardware failed, need system reset to recover + * + * @note + * If channel fails reset, then it will be set as invalid + *****************************************************************************/ +int XAxiVdma_CfgInitialize(XAxiVdma *InstancePtr, XAxiVdma_Config *CfgPtr, + u32 EffectiveAddr) +{ + XAxiVdma_Channel *RdChannel; + XAxiVdma_Channel *WrChannel; + int Polls; + + /* Validate parameters */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + + /* Initially, no interrupt callback functions + */ + InstancePtr->ReadCallBack.CompletionCallBack = 0x0; + InstancePtr->ReadCallBack.ErrCallBack = 0x0; + InstancePtr->WriteCallBack.CompletionCallBack = 0x0; + InstancePtr->WriteCallBack.ErrCallBack = 0x0; + + InstancePtr->BaseAddr = EffectiveAddr; + InstancePtr->MaxNumFrames = CfgPtr->MaxFrameStoreNum; + InstancePtr->HasMm2S = CfgPtr->HasMm2S; + InstancePtr->HasS2Mm = CfgPtr->HasS2Mm; + InstancePtr->UseFsync = CfgPtr->UseFsync; + InstancePtr->InternalGenLock = CfgPtr->InternalGenLock; + + if (XAxiVdma_Major(InstancePtr) < 3) { + InstancePtr->HasSG = 1; + } + else { + InstancePtr->HasSG = CfgPtr->HasSG; + } + + /* The channels are not valid until being initialized + */ + RdChannel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_READ); + RdChannel->IsValid = 0; + + WrChannel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_WRITE); + WrChannel->IsValid = 0; + + if (InstancePtr->HasMm2S) { + RdChannel->ChanBase = InstancePtr->BaseAddr + XAXIVDMA_TX_OFFSET; + RdChannel->InstanceBase = InstancePtr->BaseAddr; + RdChannel->HasSG = InstancePtr->HasSG; + RdChannel->IsRead = 1; + RdChannel->StartAddrBase = InstancePtr->BaseAddr + + XAXIVDMA_MM2S_ADDR_OFFSET; + + RdChannel->NumFrames = CfgPtr->MaxFrameStoreNum; + + /* Flush on Sync */ + RdChannel->FlushonFsync = CfgPtr->FlushonFsync; + + /* Dynamic Line Buffers Depth */ + RdChannel->LineBufDepth = CfgPtr->Mm2SBufDepth; + if(RdChannel->LineBufDepth > 0) { + RdChannel->LineBufThreshold = + XAxiVdma_ReadReg(RdChannel->ChanBase, + XAXIVDMA_BUFTHRES_OFFSET); + xdbg_printf(XDBG_DEBUG_GENERAL, + "Read Channel Buffer Threshold %d bytes\n\r", + RdChannel->LineBufThreshold); + } + RdChannel->HasDRE = CfgPtr->HasMm2SDRE; + RdChannel->WordLength = CfgPtr->Mm2SWordLen >> 3; + RdChannel->StreamWidth = CfgPtr->Mm2SStreamWidth >> 3; + + /* Internal GenLock */ + RdChannel->GenLock = CfgPtr->Mm2SGenLock; + + /* Debug Info Parameter flags */ + if (!CfgPtr->EnableAllDbgFeatures) { + if (CfgPtr->Mm2SThresRegEn) { + RdChannel->DbgFeatureFlags |= + XAXIVDMA_ENABLE_DBG_THRESHOLD_REG; + } + + if (CfgPtr->Mm2SFrmStoreRegEn) { + RdChannel->DbgFeatureFlags |= + XAXIVDMA_ENABLE_DBG_FRMSTORE_REG; + } + + if (CfgPtr->Mm2SDlyCntrEn) { + RdChannel->DbgFeatureFlags |= + XAXIVDMA_ENABLE_DBG_DLY_CNTR; + } + + if (CfgPtr->Mm2SFrmCntrEn) { + RdChannel->DbgFeatureFlags |= + XAXIVDMA_ENABLE_DBG_FRM_CNTR; + } + + } else { + RdChannel->DbgFeatureFlags = + XAXIVDMA_ENABLE_DBG_ALL_FEATURES; + } + + XAxiVdma_ChannelInit(RdChannel); + + XAxiVdma_ChannelReset(RdChannel); + + /* At time of initialization, no transfers are going on, + * reset is expected to be quick + */ + Polls = INITIALIZATION_POLLING; + + while (Polls && XAxiVdma_ChannelResetNotDone(RdChannel)) { + Polls -= 1; + } + + if (!Polls) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Read channel reset failed %x\n\r", + (unsigned int)XAxiVdma_ChannelGetStatus(RdChannel)); + + return XST_FAILURE; + } + } + + if (InstancePtr->HasS2Mm) { + WrChannel->ChanBase = InstancePtr->BaseAddr + XAXIVDMA_RX_OFFSET; + WrChannel->InstanceBase = InstancePtr->BaseAddr; + WrChannel->HasSG = InstancePtr->HasSG; + WrChannel->IsRead = 0; + WrChannel->StartAddrBase = InstancePtr->BaseAddr + + XAXIVDMA_S2MM_ADDR_OFFSET; + WrChannel->NumFrames = CfgPtr->MaxFrameStoreNum; + + /* Flush on Sync */ + WrChannel->FlushonFsync = CfgPtr->FlushonFsync; + + /* Dynamic Line Buffers Depth */ + WrChannel->LineBufDepth = CfgPtr->S2MmBufDepth; + if(WrChannel->LineBufDepth > 0) { + WrChannel->LineBufThreshold = + XAxiVdma_ReadReg(WrChannel->ChanBase, + XAXIVDMA_BUFTHRES_OFFSET); + xdbg_printf(XDBG_DEBUG_GENERAL, + "Write Channel Buffer Threshold %d bytes\n\r", + WrChannel->LineBufThreshold); + } + WrChannel->HasDRE = CfgPtr->HasS2MmDRE; + WrChannel->WordLength = CfgPtr->S2MmWordLen >> 3; + WrChannel->StreamWidth = CfgPtr->S2MmStreamWidth >> 3; + + /* Internal GenLock */ + WrChannel->GenLock = CfgPtr->S2MmGenLock; + + /* Frame Sync Source Selection*/ + WrChannel->S2MmSOF = CfgPtr->S2MmSOF; + + /* Debug Info Parameter flags */ + if (!CfgPtr->EnableAllDbgFeatures) { + if (CfgPtr->S2MmThresRegEn) { + WrChannel->DbgFeatureFlags |= + XAXIVDMA_ENABLE_DBG_THRESHOLD_REG; + } + + if (CfgPtr->S2MmFrmStoreRegEn) { + WrChannel->DbgFeatureFlags |= + XAXIVDMA_ENABLE_DBG_FRMSTORE_REG; + } + + if (CfgPtr->S2MmDlyCntrEn) { + WrChannel->DbgFeatureFlags |= + XAXIVDMA_ENABLE_DBG_DLY_CNTR; + } + + if (CfgPtr->S2MmFrmCntrEn) { + WrChannel->DbgFeatureFlags |= + XAXIVDMA_ENABLE_DBG_FRM_CNTR; + } + + } else { + WrChannel->DbgFeatureFlags = + XAXIVDMA_ENABLE_DBG_ALL_FEATURES; + } + + XAxiVdma_ChannelInit(WrChannel); + + XAxiVdma_ChannelReset(WrChannel); + + /* At time of initialization, no transfers are going on, + * reset is expected to be quick + */ + Polls = INITIALIZATION_POLLING; + + while (Polls && XAxiVdma_ChannelResetNotDone(WrChannel)) { + Polls -= 1; + } + + if (!Polls) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Write channel reset failed %x\n\r", + (unsigned int)XAxiVdma_ChannelGetStatus(WrChannel)); + + return XST_FAILURE; + } + } + + InstancePtr->IsReady = XAXIVDMA_DEVICE_READY; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * This function resets one DMA channel + * + * The registers will be default values after the reset + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return + * None + * + * @note + * Due to undeterminism of system delays, check the reset status through + * XAxiVdma_ResetNotDone(). If direction is invalid, do nothing. + *****************************************************************************/ +void XAxiVdma_Reset(XAxiVdma *InstancePtr, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return; + } + + if (Channel->IsValid) { + XAxiVdma_ChannelReset(Channel); + + return; + } +} + +/*****************************************************************************/ +/** + * This function checks one DMA channel for reset completion + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return + * - 0 if reset is done + * - 1 if reset is ongoing + * + * @note + * We do not check for channel validity, because channel is marked as invalid + * before reset is done + *****************************************************************************/ +int XAxiVdma_ResetNotDone(XAxiVdma *InstancePtr, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + /* If dirction is invalid, reset is never done + */ + if (!Channel) { + return 1; + } + + return XAxiVdma_ChannelResetNotDone(Channel); +} + +/*****************************************************************************/ +/** + * Check whether a DMA channel is busy + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return + * - Non-zero if the channel is busy + * - Zero if the channel is idle + * + *****************************************************************************/ +int XAxiVdma_IsBusy(XAxiVdma *InstancePtr, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return 0; + } + + if (Channel->IsValid) { + return XAxiVdma_ChannelIsBusy(Channel); + } + else { + /* An invalid channel is never busy + */ + return 0; + } +} + +/*****************************************************************************/ +/** + * Get the current frame that hardware is working on + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return + * The current frame that the hardware is working on + * + * @note + * If returned frame number is out of range, then the channel is invalid + *****************************************************************************/ +u32 XAxiVdma_CurrFrameStore(XAxiVdma *InstancePtr, u16 Direction) +{ + u32 Rc; + + Rc = XAxiVdma_ReadReg(InstancePtr->BaseAddr, XAXIVDMA_PARKPTR_OFFSET); + + if (Direction == XAXIVDMA_READ) { + Rc &= XAXIVDMA_PARKPTR_READSTR_MASK; + return (Rc >> XAXIVDMA_READSTR_SHIFT); + } + else if (Direction == XAXIVDMA_WRITE) { + Rc &= XAXIVDMA_PARKPTR_WRTSTR_MASK; + return (Rc >> XAXIVDMA_WRTSTR_SHIFT); + } + else { + return 0xFFFFFFFF; + } +} + +/*****************************************************************************/ +/** + * Get the version of the hardware + * + * @param InstancePtr is the pointer to the DMA engine to work on + * + * @return + * The version of the hardware + * + *****************************************************************************/ +u32 XAxiVdma_GetVersion(XAxiVdma *InstancePtr) +{ + return XAxiVdma_ReadReg(InstancePtr->BaseAddr, XAXIVDMA_VERSION_OFFSET); +} + +/*****************************************************************************/ +/** + * Get the status of a channel + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return + * The status of the channel + * + * @note + * An invalid return value indicates that channel is invalid + *****************************************************************************/ +u32 XAxiVdma_GetStatus(XAxiVdma *InstancePtr, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return 0xFFFFFFFF; + } + + if (Channel->IsValid) { + return XAxiVdma_ChannelGetStatus(Channel); + } + else { + return 0xFFFFFFFF; + } +} + +/*****************************************************************************/ +/** + * Configure Line Buffer Threshold + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param LineBufThreshold is the value to set threshold + * @param Direction is the DMA channel to work on + * + * @return + * - XST_SUCCESS if successful + * - XST_FAILURE otherwise + * - XST_NO_FEATURE if access to Threshold register is disabled + *****************************************************************************/ +int XAxiVdma_SetLineBufThreshold(XAxiVdma *InstancePtr, int LineBufThreshold, + u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!(Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_THRESHOLD_REG)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Threshold Register is disabled\n\r"); + return XST_NO_FEATURE; + } + + if(Channel->LineBufThreshold) { + if((LineBufThreshold < Channel->LineBufDepth) && + (LineBufThreshold % Channel->StreamWidth == 0)) { + XAxiVdma_WriteReg(Channel->ChanBase, + XAXIVDMA_BUFTHRES_OFFSET, LineBufThreshold); + + xdbg_printf(XDBG_DEBUG_GENERAL, + "Line Buffer Threshold set to %x\n\r", + XAxiVdma_ReadReg(Channel->ChanBase, + XAXIVDMA_BUFTHRES_OFFSET)); + } + else { + xdbg_printf(XDBG_DEBUG_ERROR, + "Invalid Line Buffer Threshold\n\r"); + return XST_FAILURE; + } + } + else { + xdbg_printf(XDBG_DEBUG_ERROR, + "Failed to set Threshold\n\r"); + return XST_FAILURE; + } + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** + * Configure Frame Sync Source and valid only when C_USE_FSYNC is enabled. + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Source is the value to set the source of Frame Sync + * @param Direction is the DMA channel to work on + * + * @return + * - XST_SUCCESS if successful + * - XST_FAILURE if C_USE_FSYNC is disabled. + * + *****************************************************************************/ +int XAxiVdma_FsyncSrcSelect(XAxiVdma *InstancePtr, u32 Source, + u16 Direction) +{ + XAxiVdma_Channel *Channel; + u32 CrBits; + u32 UseFsync; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (Direction == XAXIVDMA_WRITE) { + UseFsync = ((InstancePtr->UseFsync == 1) || + (InstancePtr->UseFsync == 3)) ? 1 : 0; + } else { + UseFsync = ((InstancePtr->UseFsync == 1) || + (InstancePtr->UseFsync == 2)) ? 1 : 0; + } + + if (UseFsync) { + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, + XAXIVDMA_CR_OFFSET); + + switch (Source) { + case XAXIVDMA_CHAN_FSYNC: + /* Same Channel Frame Sync */ + CrBits &= ~(XAXIVDMA_CR_FSYNC_SRC_MASK); + break; + + case XAXIVDMA_CHAN_OTHER_FSYNC: + /* The other Channel Frame Sync */ + CrBits |= (XAXIVDMA_CR_FSYNC_SRC_MASK & ~(1 << 6)); + break; + + case XAXIVDMA_S2MM_TUSER_FSYNC: + /* S2MM TUser Sync */ + if (Channel->S2MmSOF) { + CrBits |= (XAXIVDMA_CR_FSYNC_SRC_MASK + & ~(1 << 5)); + } + else + return XST_FAILURE; + break; + } + + XAxiVdma_WriteReg(Channel->ChanBase, + XAXIVDMA_CR_OFFSET, CrBits); + + return XST_SUCCESS; + } + + xdbg_printf(XDBG_DEBUG_ERROR, + "This bit is not valid for this configuration\n\r"); + return XST_FAILURE; +} + +/*****************************************************************************/ +/** + * Configure Gen Lock Source + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Source is the value to set the source of Gen Lock + * @param Direction is the DMA channel to work on + * + * @return + * - XST_SUCCESS if successful + * - XST_FAILURE if the channel is in GenLock Master Mode. + * if C_INCLUDE_INTERNAL_GENLOCK is disabled. + * + *****************************************************************************/ +int XAxiVdma_GenLockSourceSelect(XAxiVdma *InstancePtr, u32 Source, + u16 Direction) +{ + XAxiVdma_Channel *Channel, *XChannel; + u32 CrBits; + + if (InstancePtr->HasMm2S && InstancePtr->HasS2Mm && + InstancePtr->InternalGenLock) { + if (Direction == XAXIVDMA_WRITE) { + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + XChannel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_READ); + } else { + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + XChannel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_WRITE); + } + + if ((Channel->GenLock == XAXIVDMA_GENLOCK_MASTER && + XChannel->GenLock == XAXIVDMA_GENLOCK_SLAVE) || + (Channel->GenLock == XAXIVDMA_GENLOCK_SLAVE && + XChannel->GenLock == XAXIVDMA_GENLOCK_MASTER) || + (Channel->GenLock == XAXIVDMA_DYN_GENLOCK_MASTER && + XChannel->GenLock == XAXIVDMA_DYN_GENLOCK_SLAVE) || + (Channel->GenLock == XAXIVDMA_DYN_GENLOCK_SLAVE && + XChannel->GenLock == XAXIVDMA_DYN_GENLOCK_MASTER)) { + + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, + XAXIVDMA_CR_OFFSET); + + if (Source == XAXIVDMA_INTERNAL_GENLOCK) + CrBits |= XAXIVDMA_CR_GENLCK_SRC_MASK; + else if (Source == XAXIVDMA_EXTERNAL_GENLOCK) + CrBits &= ~XAXIVDMA_CR_GENLCK_SRC_MASK; + else { + xdbg_printf(XDBG_DEBUG_ERROR, + "Invalid argument\n\r"); + return XST_FAILURE; + } + + XAxiVdma_WriteReg(Channel->ChanBase, + XAXIVDMA_CR_OFFSET, CrBits); + + return XST_SUCCESS; + } + } + + xdbg_printf(XDBG_DEBUG_ERROR, + "This bit is not valid for this configuration\n\r"); + return XST_FAILURE; +} + +/*****************************************************************************/ +/** + * Start parking mode on a certain frame + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param FrameIndex is the frame to park on + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return + * - XST_SUCCESS if everything is fine + * - XST_INVALID_PARAM if + * . channel is invalid + * . FrameIndex is invalid + * . Direction is invalid + *****************************************************************************/ +int XAxiVdma_StartParking(XAxiVdma *InstancePtr, int FrameIndex, + u16 Direction) +{ + XAxiVdma_Channel *Channel; + u32 FrmBits; + u32 RegValue; + int Status; + + if (FrameIndex > XAXIVDMA_FRM_MAX) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Invalid frame to park on %d\r\n", FrameIndex); + + return XST_INVALID_PARAM; + } + + if (Direction == XAXIVDMA_READ) { + FrmBits = FrameIndex & + XAXIVDMA_PARKPTR_READREF_MASK; + + RegValue = XAxiVdma_ReadReg(InstancePtr->BaseAddr, + XAXIVDMA_PARKPTR_OFFSET); + + RegValue &= ~XAXIVDMA_PARKPTR_READREF_MASK; + + RegValue |= FrmBits; + + XAxiVdma_WriteReg(InstancePtr->BaseAddr, + XAXIVDMA_PARKPTR_OFFSET, RegValue); + } + else if (Direction == XAXIVDMA_WRITE) { + FrmBits = FrameIndex << XAXIVDMA_WRTREF_SHIFT; + + FrmBits &= XAXIVDMA_PARKPTR_WRTREF_MASK; + + RegValue = XAxiVdma_ReadReg(InstancePtr->BaseAddr, + XAXIVDMA_PARKPTR_OFFSET); + + RegValue &= ~XAXIVDMA_PARKPTR_WRTREF_MASK; + + RegValue |= FrmBits; + + XAxiVdma_WriteReg(InstancePtr->BaseAddr, + XAXIVDMA_PARKPTR_OFFSET, RegValue); + } + else { + /* Invalid direction, do nothing + */ + return XST_INVALID_PARAM; + } + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (Channel->IsValid) { + Status = XAxiVdma_ChannelStartParking(Channel); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Failed to start channel %x\r\n", + (unsigned int)Channel); + + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Exit parking mode, the channel will return to circular buffer mode + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return + * None + * + * @note + * If channel is invalid, then do nothing + *****************************************************************************/ +void XAxiVdma_StopParking(XAxiVdma *InstancePtr, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return; + } + + if (Channel->IsValid) { + XAxiVdma_ChannelStopParking(Channel); + } + + return; +} + +/*****************************************************************************/ +/** + * Start frame count enable on one channel + * + * This is needed to start limiting the number of frames to transfer so that + * software can check the data etc after hardware stops transfer. + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return + * None + * + *****************************************************************************/ +void XAxiVdma_StartFrmCntEnable(XAxiVdma *InstancePtr, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (Channel->IsValid) { + XAxiVdma_ChannelStartFrmCntEnable(Channel); + } +} + +/*****************************************************************************/ +/** + * Set BD addresses to be different. + * + * In some systems, it is convenient to put BDs into a certain region of the + * memory. This function enables that. + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param BdAddrPhys is the physical starting address for BDs + * @param BdAddrVirt is the Virtual starting address for BDs. For systems that + * do not use MMU, then virtual address is the same as physical address + * @param NumBds is the number of BDs to setup with. This is required to be + * the same as the number of frame stores for that channel + * @param Direction is the channel direction + * + * @return + * - XST_SUCCESS for a successful setup + * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used + * - XST_INVALID_PARAM if parameters not valid + * - XST_DEVICE_NOT_FOUND if the channel is invalid + * + * @notes + * We assume that the memory region starting from BdAddrPhys and BdAddrVirt are + * large enough to hold all the BDs. + *****************************************************************************/ +int XAxiVdma_SetBdAddrs(XAxiVdma *InstancePtr, u32 BdAddrPhys, u32 BdAddrVirt, + int NumBds, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (Channel->IsValid) { + if (NumBds != Channel->AllCnt) { + return XST_INVALID_PARAM; + } + + if (BdAddrPhys & (XAXIVDMA_BD_MINIMUM_ALIGNMENT - 1)) { + return XST_INVALID_PARAM; + } + + if (BdAddrVirt & (XAXIVDMA_BD_MINIMUM_ALIGNMENT - 1)) { + return XST_INVALID_PARAM; + } + + return XAxiVdma_ChannelSetBdAddrs(Channel, BdAddrPhys, BdAddrVirt); + } + else { + return XST_DEVICE_NOT_FOUND; + } +} + +/*****************************************************************************/ +/** + * Start a write operation + * + * Write corresponds to send data from device to memory + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param DmaConfigPtr is the pointer to the setup structure + * + * @return + * - XST_SUCCESS for a successful submission + * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used + * - XST_INVAID_PARAM if parameters in config structure not valid + * - XST_DEVICE_NOT_FOUND if the channel is invalid + * + *****************************************************************************/ +int XAxiVdma_StartWriteFrame(XAxiVdma *InstancePtr, + XAxiVdma_DmaSetup *DmaConfigPtr) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_WRITE); + + if (Channel->IsValid) { + return XAxiVdma_ChannelStartTransfer(Channel, + (XAxiVdma_ChannelSetup *)DmaConfigPtr); + } + else { + return XST_DEVICE_NOT_FOUND; + } +} + +/*****************************************************************************/ +/** + * Start a read operation + * + * Read corresponds to send data from memory to device + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param DmaConfigPtr is the pointer to the setup structure + * + * @return + * - XST_SUCCESS for a successful submission + * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used + * - XST_INVAID_PARAM if parameters in config structure not valid + * - XST_DEVICE_NOT_FOUND if the channel is invalid + * + *****************************************************************************/ +int XAxiVdma_StartReadFrame(XAxiVdma *InstancePtr, + XAxiVdma_DmaSetup *DmaConfigPtr) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_READ); + + if (Channel->IsValid) { + return XAxiVdma_ChannelStartTransfer(Channel, + (XAxiVdma_ChannelSetup *)DmaConfigPtr); + } + else { + return XST_DEVICE_NOT_FOUND; + } +} + +/*****************************************************************************/ +/** + * Configure one DMA channel using the configuration structure + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the DMA channel to work on + * @param DmaConfigPtr is the pointer to the setup structure + * + * @return + * - XST_SUCCESS if successful + * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used + * - XST_INVAID_PARAM if buffer address not valid, for example, unaligned + * address with no DRE built in the hardware, or Direction invalid + * - XST_DEVICE_NOT_FOUND if the channel is invalid + * + *****************************************************************************/ +int XAxiVdma_DmaConfig(XAxiVdma *InstancePtr, u16 Direction, + XAxiVdma_DmaSetup *DmaConfigPtr) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return XST_INVALID_PARAM; + } + + + if (Channel->IsValid) { + + return XAxiVdma_ChannelConfig(Channel, + (XAxiVdma_ChannelSetup *)DmaConfigPtr); + } + else { + return XST_DEVICE_NOT_FOUND; + } +} + +/*****************************************************************************/ +/** + * Configure buffer addresses for one DMA channel + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the DMA channel to work on + * @param BufferAddrSet is the set of addresses for the transfers + * + * @return + * - XST_SUCCESS if successful + * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used + * - XST_INVAID_PARAM if buffer address not valid, for example, unaligned + * address with no DRE built in the hardware, or Direction invalid + * - XST_DEVICE_NOT_FOUND if the channel is invalid + * + *****************************************************************************/ +int XAxiVdma_DmaSetBufferAddr(XAxiVdma *InstancePtr, u16 Direction, + u32 *BufferAddrSet) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return XST_INVALID_PARAM; + } + + if (Channel->IsValid) { + return XAxiVdma_ChannelSetBufferAddr(Channel, BufferAddrSet, + Channel->NumFrames); + } + else { + return XST_DEVICE_NOT_FOUND; + } +} + +/*****************************************************************************/ +/** + * Start one DMA channel + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the DMA channel to work on + * + * @return + * - XST_SUCCESS if channel started successfully + * - XST_FAILURE otherwise + * - XST_DEVICE_NOT_FOUND if the channel is invalid + * - XST_INVALID_PARAM if Direction invalid + * + *****************************************************************************/ +int XAxiVdma_DmaStart(XAxiVdma *InstancePtr, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return XST_INVALID_PARAM; + } + + if (Channel->IsValid) { + return XAxiVdma_ChannelStart(Channel); + } + else { + return XST_DEVICE_NOT_FOUND; + } +} + +/*****************************************************************************/ +/** + * Stop one DMA channel + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the DMA channel to work on + * + * @return + * None + * + * @note + * If channel is invalid, then do nothing on that channel + *****************************************************************************/ +void XAxiVdma_DmaStop(XAxiVdma *InstancePtr, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return; + } + + if (Channel->IsValid) { + XAxiVdma_ChannelStop(Channel); + } + + return; +} + +/*****************************************************************************/ +/** + * Dump registers of one DMA channel + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the DMA channel to work on + * + * @return + * None + * + * @note + * If channel is invalid, then do nothing on that channel + *****************************************************************************/ +void XAxiVdma_DmaRegisterDump(XAxiVdma *InstancePtr, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return; + } + + if (Channel->IsValid) { + XAxiVdma_ChannelRegisterDump(Channel); + } + + return; +} + +/*****************************************************************************/ +/** + * Set the frame counter and delay counter for both channels + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param CfgPtr is the pointer to the configuration structure + * + * @return + * - XST_SUCCESS if setup finishes successfully + * - XST_INVALID_PARAM if the configuration structure has invalid values + * - Others if setting channel frame counter fails + * + * @note + * If channel is invalid, then do nothing on that channel + *****************************************************************************/ +int XAxiVdma_SetFrameCounter(XAxiVdma *InstancePtr, + XAxiVdma_FrameCounter *CfgPtr) +{ + int Status; + XAxiVdma_Channel *Channel; + + /* Validate parameters */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XAXIVDMA_DEVICE_READY); + Xil_AssertNonvoid(CfgPtr != NULL); + + if ((CfgPtr->ReadFrameCount == 0) || + (CfgPtr->WriteFrameCount == 0)) { + + return XST_INVALID_PARAM; + } + + Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_READ); + + if (Channel->IsValid) { + + Status = XAxiVdma_ChannelSetFrmCnt(Channel, CfgPtr->ReadFrameCount, + CfgPtr->ReadDelayTimerCount); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Setting read channel frame counter " + "failed with %d\r\n", Status); + + return Status; + } + } + + Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_WRITE); + + if (Channel->IsValid) { + + Status = XAxiVdma_ChannelSetFrmCnt(Channel, + CfgPtr->WriteFrameCount, + CfgPtr->WriteDelayTimerCount); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Setting write channel frame counter " + "failed with %d\r\n", Status); + + return Status; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Get the frame counter and delay counter for both channels + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param CfgPtr is the configuration structure to contain return values + * + * @return + * None + * + * @note + * If returned frame counter value is 0, then the channel is not valid + *****************************************************************************/ +void XAxiVdma_GetFrameCounter(XAxiVdma *InstancePtr, + XAxiVdma_FrameCounter *CfgPtr) +{ + XAxiVdma_Channel *Channel; + u8 FrmCnt; + u8 DlyCnt; + + /* Validate parameters */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XAXIVDMA_DEVICE_READY); + Xil_AssertVoid(CfgPtr != NULL); + + /* Use a zero frame counter value to indicate failure + */ + FrmCnt = 0; + + Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_READ); + + if (Channel->IsValid) { + XAxiVdma_ChannelGetFrmCnt(Channel, &FrmCnt, &DlyCnt); + } + + CfgPtr->ReadFrameCount = FrmCnt; + CfgPtr->ReadDelayTimerCount = DlyCnt; + + /* Use a zero frame counter value to indicate failure + */ + FrmCnt = 0; + + Channel = XAxiVdma_GetChannel(InstancePtr, XAXIVDMA_WRITE); + + if (Channel->IsValid) { + XAxiVdma_ChannelGetFrmCnt(Channel, &FrmCnt, &DlyCnt); + } + + CfgPtr->WriteFrameCount = FrmCnt; + CfgPtr->WriteDelayTimerCount = DlyCnt; + + return; +} + +/*****************************************************************************/ +/** + * Set the number of frame store buffers to use. + * + * @param InstancePtr is the XAxiVdma instance to operate on + * @param FrmStoreNum is the number of frame store buffers to use. + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return - XST_SUCCESS if operation is successful + * - XST_FAILURE if operation fails. + * - XST_NO_FEATURE if access to FrameStore register is disabled + * @note None + * + *****************************************************************************/ +int XAxiVdma_SetFrmStore(XAxiVdma *InstancePtr, u8 FrmStoreNum, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + if(FrmStoreNum > InstancePtr->MaxNumFrames) { + return XST_FAILURE; + } + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return XST_FAILURE; + } + + if(XAxiVdma_ChannelIsRunning(Channel)) { + xdbg_printf(XDBG_DEBUG_ERROR, "Cannot set frame store..." + "channel is running\r\n"); + return XST_FAILURE; + } + + if (!(Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_FRMSTORE_REG)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Frame Store Register is disabled\n\r"); + return XST_NO_FEATURE; + } + + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_FRMSTORE_OFFSET, + FrmStoreNum & XAXIVDMA_FRMSTORE_MASK); + + Channel->NumFrames = FrmStoreNum; + + XAxiVdma_ChannelInit(Channel); + + return XST_SUCCESS; + +} + +/*****************************************************************************/ +/** + * Get the number of frame store buffers to use. + * + * @param InstancePtr is the XAxiVdma instance to operate on + * @param FrmStoreNum is the number of frame store buffers to use. + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return None + * + * @note None + * + *****************************************************************************/ +void XAxiVdma_GetFrmStore(XAxiVdma *InstancePtr, u8 *FrmStoreNum, + u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return; + } + + if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_FRMSTORE_REG) { + *FrmStoreNum = (XAxiVdma_ReadReg(Channel->ChanBase, + XAXIVDMA_FRMSTORE_OFFSET)) & XAXIVDMA_FRMSTORE_MASK; + } else { + xdbg_printf(XDBG_DEBUG_ERROR, + "Frame Store Register is disabled\n\r"); + } +} + +/*****************************************************************************/ +/** + * Check for DMA Channel Errors. + * + * @param InstancePtr is the XAxiVdma instance to operate on + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return - Errors seen on the channel + * - XST_INVALID_PARAM, when channel pointer is invalid. + * - XST_DEVICE_NOT_FOUND, when the channel is not valid. + * + * @note None + * + *****************************************************************************/ +int XAxiVdma_GetDmaChannelErrors(XAxiVdma *InstancePtr, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return XST_INVALID_PARAM; + } + + if (Channel->IsValid) { + return XAxiVdma_ChannelErrors(Channel); + } + else { + return XST_DEVICE_NOT_FOUND; + } +} + +/*****************************************************************************/ +/** + * Clear DMA Channel Errors. + * + * @param InstancePtr is the XAxiVdma instance to operate on + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * @param ErrorMask is the mask of error bits to clear + * + * @return - XST_SUCCESS, when error bits are cleared. + * - XST_INVALID_PARAM, when channel pointer is invalid. + * - XST_DEVICE_NOT_FOUND, when the channel is not valid. + * + * @note None + * + *****************************************************************************/ +int XAxiVdma_ClearDmaChannelErrors(XAxiVdma *InstancePtr, u16 Direction, + u32 ErrorMask) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return XST_INVALID_PARAM; + } + + if (Channel->IsValid) { + XAxiVdma_ClearChannelErrors(Channel, ErrorMask); + return XST_SUCCESS; + } + else { + return XST_DEVICE_NOT_FOUND; + } +} diff --git a/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma.h b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma.h new file mode 100644 index 00000000..0224185c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma.h @@ -0,0 +1,589 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 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 xaxivdma.h +* +* This is the Xilinx MVI AXI Video DMA device driver. The DMA engine transfers +* frames from the AXI Bus or to the AXI Bus. It is in the chain of video +* IPs, which process video frames. +* +* It supports the following features: +* - Continuous transfers of video frames, AKA circular buffer mode +* - Continuous transfers of one specific video frame, AKA park mode +* - Optionally only transfer a certain amount of video frames +* - Optionally transfer unaligned frame buffers +* +* An AXI Video DMA engine can have one or two channels. If configured as two +* channels, then one of the channels reads data from memory, and the other +* channel writes to the memory. +* +* For a full description of AXI Video DMA features, please see the hardware +* spec. +* +* The driver composes of three parts: initialization, start a DMA transfer, and +* interrupt handling. +* +* Driver Initialization +* +* To initialize the driver, the caller needs to pass a configuration structure +* to the driver. This configuration structure contains information about the +* hardware build. +* +* A caller can manually setup the configuration structure, or call +* XAxiVdma_LoopkupConfig(). +* +* The sequence of initialization of the driver is: +* 1. XAxiVdma_LookupConfig() to get the configuration structure, or manually +* setup the structure. +* 2. XAxiVdma_CfgInitialize() to initialize the driver & device. +* 3. XAxiVdma_SetFrmStore() to set the desired frame store number which +* is optional. +* 4. If interrupt is desired: +* - Set frame counter using XAxiVdma_SetFrameCounter() +* - Set call back functions for each channel. There are two types of call +* backfunctions: general and error +* - Enable interrupts that the user cares about +* +* Start a DMA Transaction +* +* If you are using the driver API to start the transfer, then there are two +* ways to start a DMA transaction: +* +* 1. Invoke XAxiVdma_StartWriteFrame() or XAxiVdma_StartReadFrame() to start a +* DMA operation, depending on the purpose of the transfer (Read or Write). +* +* 2. Or, call the phased functions as the following: +* - Call XAxiVdma_DmaConfig() to set up a DMA operation configuration +* - Call XAxiVdma_DmaSetBufferAddr() to set up the DMA buffers +* - Call XAxiVdma_DmaStart() to kick off the DMA operation +* +* If you are writing your own functions to start the transfer, the order of +* setting up the hardware must be the following: +* +* - Do any processing or setting, but do not start the hardware, means do not +* set the RUN/STOP bit in the XAXIVDMA_CR_OFFSET register. +* - After any reset you need to do, write the head of your BD ring into the +* XAXIVDMA_CDESC_OFFSET register. +* - You can do other setup for the harware. +* - Start your hardware, by setting up the RUN/STOP bit in the +* XAXIVDMA_CR_OFFSET register. +* - You can do other setup for the hardware. +* - If you are done with all the setup, now write the tail of your BD ring to +* the XAXIVDMA_TDESC_OFFSET register to start the transfer. +* +* You can refer to XAxiVdma_ChannelStartTransfer() to see how this order is +* preserved there. The function is in xaxivdma_channel.c. +* +* Note a Read VDMA could work with one out of multiple write VDMA instances +* and vice versa. The PointNum in structure XAxiVdma_DmaSetup decides which +* VDMA instance this VDMA is working with. +* +* Interrupt Handling +* +* Each VDMA channel supports 2 kinds of interrupts: +* - General Interrupt: An interrupt other than error interrupt. +* - Error Interrupt: An error just happened. +* +* The driver does the interrupt handling, and dispatch to the user application +* through callback functions that user has registered. If there are no +* registered callback functions, then a stub callback function is called. +* +* Each channel has two interrupt callback functions. One for IOC and delay +* interrupt, or general interrupt; one for error interrupt. +* +* Reset +* +* Reset a DMA channel causes the channel enter the following state: +* +* - Interrupts are disabled +* - Coalescing threshold is one +* - Delay counter is 0 +* - RUN/STOP bit low +* - Halted bit high +* - XAXIVDMA_CDESC_OFFSET register has 0 +* - XAXIVDMA_TDESC_OFFSET register has 0 +* +* If there is an active transfer going on when reset (or stop) is issued to +* the hardware, the current transfer will gracefully finish. For a maximum +* transfer length of (0x1FFF * 0xFFFF) bytes, on a 100 MHz system, it can take +* as long as 1.34 seconds, assuming that the system responds to DMA engine's +* requests quickly. +* +* To ensure that the hardware finishes the reset, please use +* XAxiVdma_ResetNotDone() to check for completion of the reset. +* +* To start a transfer after a reset, the following actions are the minimal +* requirement before setting RUN/STOP bit high to avoid crashing the system: +* +* - XAXIVDMA_CDESC_OFFSET register has a valid BD pointer, it should be the +* head of the BD ring. +* - XAXIVDMA_TDESC_OFFSET register has a valid BD pointer, it should be the +* tail of the BD ring. +* +* If you are using the driver API to start a transfer after a reset, then it +* should be fine. +* +* Stop +* +* Stop a channel using XAxiVDma_DmaStop() is similar to a reset, except the +* registers are kept intact. +* +* To start a transfer after a stop: +* +* - If there are error bits in the status register, then a reset is necessary. +* Please refer to the Reset section for more details on how to start a +* transfer after a reset. +* - If there are no error bits in the status register, then you can call +* XAxiVdma_DmaStart() to start the transfer again. Note that the transfer +* always starts from the first video frame. +* +* Examples +* +* We provide one example on how to use the AXI VDMA with AXI Video IPs. This +* example does not work by itself. To make it work, you must have two other +* Video IPs to connect to the VDMA. One of the Video IP does the write and the +* other does the read. +* +* Cache Coherency +* +* This driver does not handle any cache coherency for the data buffers. +* The application is responsible for handling cache coherency, if the cache +* is enabled. +* +* Alignment +* +* The VDMA supports any buffer alignment when DRE is enabled in the hardware +* configuration. It only supports word-aligned buffers otherwise. Note that +* "word" is defined by C_M_AXIS_MM2S_TDATA_WIDTH and C_S_AXIS_S2MM_TDATA_WIDTH +* for the read and write channel specifically. +* +* If the horizonal frame size is not word-aligned, then DRE must be enabled +* in the hardware. Otherwise, undefined results happen. +* +* Address Translation +* +* Buffer addresses for transfers are physical addresses. If the system does not +* use MMU, then physical and virtual addresses are the same. +* +* API Change from PLB Video DMA +* +* We try to keep the API as consistent with the PLB Video DMA driver as +* possible. However, due to hardware differences, some of the PLB video DMA +* driver APIs are changed or removed. Two API functions are added to the AXI +* DMA driver. +* +* For details on the API changes, please refer to xaxivdma_porting_guide.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   08/16/10 First release
+* 2.00a jz   12/10/10 Added support for direct register access mode, v3 core
+* 2.01a jz   01/19/11 Added ability to re-assign BD addresses
+*		      Replaced include xenv.h with string.h in xaxivdma_i.h
+* 		      file.
+* 2.01a	rkv  03/28/11 Added support for frame store register and
+*                     XAxiVdma_ChannelInit API is changed.
+* 3.00a srt  08/26/11 - Added support for Flush on Frame Sync and dynamic
+*		      	programming of Line Buffer Thresholds.
+*		      - XAxiVdma_ChannelErrors API is changed to support for
+*			Flush on Frame Sync feature.
+*		      - Two flags, XST_VDMA_MISMATCH_ERROR & XAXIVDMA_MIS
+*			MATCH_ERROR are added to report error status when
+*			Flush on Frame Sync feature is enabled.
+* 4.00a srt  11/21/11 - XAxiVdma_ChannelSetBufferAddr API is changed to
+*			support 32 Frame Stores.
+*		      - XAxiVdma_ChannelConfig API is changed to support
+*			modified Park Offset Register bits.
+*		      - Added APIs:
+*			XAxiVdma_FsyncSrcSelect()
+*			XAxiVdma_GenLockSourceSelect()
+*		      - Modified structures XAxiVdma_Config and XAxiVdma to
+*		        include new parameters.
+* 4.01a srt  06/13/12 - Added APIs:
+*			XAxiVdma_GetDmaChannelErrors()
+*			XAxiVdma_ClearDmaChannelErrors()
+*			XAxiVdma_ClearChannelErrors()
+*		      - XAxiVdma_ChannelErrors API is changed to remove
+*			Mismatch error logic.
+*		      - Removed Error checking logic in the channel APIs.
+*			Provided User APIs to do this.
+*		      - Added new error bit mask XAXIVDMA_SR_ERR_SOF_LATE_MASK
+*		      - XAXIVDMA_MISMATCH_ERROR flag is deprecated.
+* 		      - Modified the logic of Error handling in interrupt
+*		        handlers.
+* 4.02a srt  10/11/12 - XAxiVdma_SetFrmStore function changed to remove
+*                       Reset logic after setting number of frame stores.
+*			(CR 678734)
+*		      - Changed Error bitmasks to support IP version 5.02a.
+*			(CR 679959)
+* 4.03a srt  01/18/13 - Updated logic of GenLockSourceSelect() & FsyncSrcSelect()
+*                       APIs for newer versions of IP (CR: 691052).
+*		      - Modified CfgInitialize() API to initialize
+*			StreamWidth parameters and added TDATA_WIDTH parameters
+*			to tcl file (CR 691866)
+*		      - Updated DDR base address for IPI designs (CR 703656).
+* 4.04a srt  03/03/13 - Support for the GenlockRepeat Control bit (Bit 15)
+*                       added in the new version of IP v5.04 (CR: 691391)
+*
+*			  - Updated driver tcl, xaxivdma_g.c and  XAxiVdma_Config
+*			structure in xaxivdma.h to import the relevant VDMA IP
+*			DEBUG_INFO_* parameters into the driver.
+*			This fixes CR# 703738.
+* 4.05a srt  05/01/3  - Merged v4.03a driver with v4.04a driver.
+*		             Driver v4.03a - Supports VDMA IPv5.04a XPS release
+*		             Driver v4.04a - Supports VDMA IPv6.00a IPI release
+*	                 The parameters C_ENABLE_DEBUG_* are only available in
+*		         VDMA IPv6.00a. These parameters should be set to '1'
+*		         for older versions of IP (XPS) and added this logic in
+*		         the driver tcl file.
+* 		      - Added unalignment checks for Hsize and Stride
+*			(CR 710279)
+* 4.06a srt  04/09/13 - Added support for the newly added S2MM_DMA_IRQ_MASK
+*                       register (CR 734741)
+* 5.0   adk  19/12/13 - Updated as per the New Tcl API's
+*
+* 
+* +******************************************************************************/ + +#ifndef XAXIVDMA_H_ /* Prevent circular inclusions */ +#define XAXIVDMA_H_ /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xaxivdma_hw.h" +#include "xaxivdma_i.h" +#include "xstatus.h" +#include "xil_assert.h" + + +/************************** Constant Definitions *****************************/ + +/** + * VDMA data transfer direction + */ +#define XAXIVDMA_WRITE 1 /**< DMA transfer into memory */ +#define XAXIVDMA_READ 2 /**< DMA transfer from memory */ + +/** + * Frame Sync Source Selection + */ +#define XAXIVDMA_CHAN_FSYNC 0 +#define XAXIVDMA_CHAN_OTHER_FSYNC 1 +#define XAXIVDMA_S2MM_TUSER_FSYNC 2 + +/** + * GenLock Source Selection + */ +#define XAXIVDMA_EXTERNAL_GENLOCK 0 +#define XAXIVDMA_INTERNAL_GENLOCK 1 + +/** + * GenLock Mode Constants + */ +#define XAXIVDMA_GENLOCK_MASTER 0 +#define XAXIVDMA_GENLOCK_SLAVE 1 +#define XAXIVDMA_DYN_GENLOCK_MASTER 2 +#define XAXIVDMA_DYN_GENLOCK_SLAVE 3 + +/** + * Interrupt type for setting up callback + */ +#define XAXIVDMA_HANDLER_GENERAL 1 /**< Non-Error Interrupt Type */ +#define XAXIVDMA_HANDLER_ERROR 2 /**< Error Interrupt Type */ + +/** + * Flag to signal that device is ready to be used + */ +#define XAXIVDMA_DEVICE_READY 0x11111111 + +/** + * Debug Configuration Parameter Constants (C_ENABLE_DEBUG_INFO_*) + */ +#define XAXIVDMA_ENABLE_DBG_THRESHOLD_REG 0x01 +#define XAXIVDMA_ENABLE_DBG_FRMSTORE_REG 0x02 +#define XAXIVDMA_ENABLE_DBG_FRM_CNTR 0x04 +#define XAXIVDMA_ENABLE_DBG_DLY_CNTR 0x08 +#define XAXIVDMA_ENABLE_DBG_ALL_FEATURES 0x0F + +/* Defined for backward compatiblity. + * This is a typical DMA Internal Error, which on detection doesnt require a + * reset (as opposed to other errors). So user on seeing this need only to + * reinitialize channels. + * + */ +#ifndef XST_VDMA_MISMATCH_ERROR +#define XST_VDMA_MISMATCH_ERROR 1430 +#endif + +/**************************** Type Definitions *******************************/ + +/*****************************************************************************/ +/** + * Callback type for general interrupts + * + * @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 called. + * @param InterruptTypes indicates the detailed type(s) of the interrupt. + * Its value equals 'OR'ing one or more XAXIVDMA_IXR_* values defined + * in xaxivdma_hw.h + *****************************************************************************/ +typedef void (*XAxiVdma_CallBack) (void *CallBackRef, u32 InterruptTypes); + +/*****************************************************************************/ +/** + * Callback type for Error interrupt. + * + * @param CallBackRef is a callback reference passed in by the upper layer + * when setting the callback function, and it is passed back to the + * upper layer when the callback is called. + * @param ErrorMask is a bit mask indicating the cause of the error. Its + * value equals 'OR'ing one or more XAXIVDMA_IXR_* values defined in + * xaxivdma_hw.h + *****************************************************************************/ +typedef void (*XAxiVdma_ErrorCallBack) (void *CallBackRef, u32 ErrorMask); + +/** + * This typedef contains the hardware configuration information for a VDMA + * device. Each VDMA device should have a configuration structure associated + * with it. + */ +typedef struct { + u16 DeviceId; /**< DeviceId is the unique ID of the device */ + u32 BaseAddress; /**< BaseAddress is the physical base address of the + * device's registers */ + u16 MaxFrameStoreNum; /**< The maximum number of Frame Stores */ + int HasMm2S; /**< Whether hw build has read channel */ + int HasMm2SDRE; /**< Read channel supports unaligned transfer */ + int Mm2SWordLen; /**< Read channel word length */ + int HasS2Mm; /**< Whether hw build has write channel */ + int HasS2MmDRE; /**< Write channel supports unaligned transfer */ + int S2MmWordLen; /**< Write channel word length */ + int HasSG; /**< Whether hardware has SG engine */ + int EnableVIDParamRead; + /**< Read Enable for video parameters in direct + * register mode */ + int UseFsync; /**< DMA operations synchronized to Frame Sync */ + int FlushonFsync; /**< VDMA Transactions are flushed & channel states + * reset on Frame Sync */ + int Mm2SBufDepth; /**< Depth of Read Channel Line Buffer FIFO */ + int S2MmBufDepth; /**< Depth of Write Channel Line Buffer FIFO */ + int Mm2SGenLock; /**< Mm2s Gen Lock Mode */ + int S2MmGenLock; /**< S2Mm Gen Lock Mode */ + int InternalGenLock; /**< Internal Gen Lock */ + int S2MmSOF; /**< S2MM Start of Flag Enable */ + int Mm2SStreamWidth; /**< MM2S TData Width */ + int S2MmStreamWidth; /**< S2MM TData Width */ + int Mm2SThresRegEn; /**< MM2S Threshold Register Enable Flag + This corresponds to C_ENABLE_DEBUG_INFO_1 + configuration parameter */ + int Mm2SFrmStoreRegEn;/**< MM2S Frame Store Register Enable Flag + This corresponds to C_ENABLE_DEBUG_INFO_5 + configuration parameter */ + int Mm2SDlyCntrEn; /**< MM2S Delay Counter (Control Reg) Enable Flag + This corresponds to C_ENABLE_DEBUG_INFO_6 + configuration parameter */ + int Mm2SFrmCntrEn; /**< MM2S Frame Counter (Control Reg) Enable Flag + This corresponds to C_ENABLE_DEBUG_INFO_7 + configuration parameter */ + int S2MmThresRegEn; /**< S2MM Threshold Register Enable Flag + This corresponds to C_ENABLE_DEBUG_INFO_9 + configuration parameter */ + int S2MmFrmStoreRegEn;/**< S2MM Frame Store Register Enable Flag + This corresponds to C_ENABLE_DEBUG_INFO_13 + configuration parameter */ + int S2MmDlyCntrEn; /**< S2MM Delay Counter (Control Reg) Enable Flag + This corresponds to C_ENABLE_DEBUG_INFO_14 + configuration parameter */ + int S2MmFrmCntrEn; /**< S2MM Frame Counter (Control Reg) Enable Flag + This corresponds to C_ENABLE_DEBUG_INFO_15 + configuration parameter */ + int EnableAllDbgFeatures;/**< Enable all Debug features + This corresponds to C_ENABLE_DEBUG_ALL + configuration parameter */ +} XAxiVdma_Config; + +/** + * The XAxiVdma_DmaSetup structure contains all the necessary information to + * start a frame write or read. + * + */ +typedef struct { + int VertSizeInput; /**< Vertical size input */ + int HoriSizeInput; /**< Horizontal size input */ + int Stride; /**< Stride */ + int FrameDelay; /**< Frame Delay */ + + int EnableCircularBuf; /**< Circular Buffer Mode? */ + int EnableSync; /**< Gen-Lock Mode? */ + int PointNum; /**< Master we synchronize with */ + int EnableFrameCounter; /**< Frame Counter Enable */ + u32 FrameStoreStartAddr[XAXIVDMA_MAX_FRAMESTORE]; + /**< Start Addresses of Frame Store Buffers. */ + int FixedFrameStoreAddr;/**< Fixed Frame Store Address index */ + int GenLockRepeat; /**< Gen-Lock Repeat? */ +} XAxiVdma_DmaSetup; + +/** + * The XAxiVdmaFrameCounter structure contains the interrupt threshold settings + * for both the transmit and the receive channel. + * + */ +typedef struct { + u8 ReadFrameCount; /**< Interrupt threshold for Receive */ + u8 ReadDelayTimerCount; /**< Delay timer threshold for receive */ + u8 WriteFrameCount; /**< Interrupt threshold for transmit */ + u8 WriteDelayTimerCount;/**< Delay timer threshold for transmit */ +} XAxiVdma_FrameCounter; + +/** + * Channel callback functions + */ +typedef struct { + XAxiVdma_CallBack CompletionCallBack; /**< Call back for completion intr */ + void *CompletionRef; /**< Call back ref */ + + XAxiVdma_ErrorCallBack ErrCallBack; /**< Call back for error intr */ + void *ErrRef; /**< Call back ref */ +} XAxiVdma_ChannelCallBack; + +/** + * The XAxiVdma driver instance data. + */ +typedef struct { + u32 BaseAddr; /**< Memory address for this device */ + int HasSG; /**< Whether hardware has SG engine */ + int IsReady; /**< Whether driver is initialized */ + + int MaxNumFrames; /**< Number of frames to work on */ + int HasMm2S; /**< Whether hw build has read channel */ + int HasMm2SDRE; /**< Whether read channel has DRE */ + int HasS2Mm; /**< Whether hw build has write channel */ + int HasS2MmDRE; /**< Whether write channel has DRE */ + int EnableVIDParamRead; /**< Read Enable for video parameters in + * direct register mode */ + int UseFsync; /**< DMA operations synchronized to + * Frame Sync */ + int InternalGenLock; /**< Internal Gen Lock */ + XAxiVdma_ChannelCallBack ReadCallBack; /**< Call back for read channel */ + XAxiVdma_ChannelCallBack WriteCallBack; /**< Call back for write channel */ + + XAxiVdma_Channel ReadChannel; /**< Channel to read from memory */ + XAxiVdma_Channel WriteChannel; /**< Channel to write to memory */ +} XAxiVdma; + + +/************************** Function Prototypes ******************************/ +/* Initialization */ +XAxiVdma_Config *XAxiVdma_LookupConfig(u16 DeviceId); + +int XAxiVdma_CfgInitialize(XAxiVdma *InstancePtr, XAxiVdma_Config *CfgPtr, + u32 EffectiveAddr); + +/* Engine and channel operations */ +void XAxiVdma_Reset(XAxiVdma *InstancePtr, u16 Direction); +int XAxiVdma_ResetNotDone(XAxiVdma *InstancePtr, u16 Direction); +int XAxiVdma_IsBusy(XAxiVdma *InstancePtr, u16 Direction); +u32 XAxiVdma_CurrFrameStore(XAxiVdma *InstancePtr, u16 Direction); +u32 XAxiVdma_GetVersion(XAxiVdma *InstancePtr); +u32 XAxiVdma_GetStatus(XAxiVdma *InstancePtr, u16 Direction); +int XAxiVdma_SetLineBufThreshold(XAxiVdma *InstancePtr, int LineBufThreshold, + u16 Direction); +int XAxiVdma_StartParking(XAxiVdma *InstancePtr, int FrameIndex, + u16 Direction); +void XAxiVdma_StopParking(XAxiVdma *InstancePtr, u16 Direction); +void XAxiVdma_StartFrmCntEnable(XAxiVdma *InstancePtr, u16 Direction); + +void XAxiVdma_IntrEnable(XAxiVdma *InstancePtr, u32 IntrType, u16 Direction); +void XAxiVdma_IntrDisable(XAxiVdma *InstancePtr, u32 IntrType ,u16 Direction); +u32 XAxiVdma_IntrGetPending(XAxiVdma *InstancePtr, u16 Direction); +void XAxiVdma_IntrClear(XAxiVdma *InstancePtr, u32 IntrType ,u16 Direction); + +int XAxiVdma_SetBdAddrs(XAxiVdma *InstancePtr, u32 BdAddrPhys, u32 BdAddrVirt, + int NumBds, u16 Direction); + +XAxiVdma_Channel *XAxiVdma_GetChannel(XAxiVdma *InstancePtr, u16 Direction); +int XAxiVdma_SetFrmStore(XAxiVdma *InstancePtr, u8 FrmStoreNum, u16 Direction); +void XAxiVdma_GetFrmStore(XAxiVdma *InstancePtr, u8 *FrmStoreNum, + u16 Direction); +int XAxiVdma_FsyncSrcSelect(XAxiVdma *InstancePtr, u32 Source, + u16 Direction); +int XAxiVdma_GenLockSourceSelect(XAxiVdma *InstancePtr, u32 Source, + u16 Direction); +int XAxiVdma_GetDmaChannelErrors(XAxiVdma *InstancePtr, u16 Direction); +int XAxiVdma_ClearDmaChannelErrors(XAxiVdma *InstancePtr, u16 Direction, + u32 ErrorMask); +int XAxiVdma_MaskS2MMErrIntr(XAxiVdma *InstancePtr, u32 ErrorMask, + u16 Direction); + +/* Transfers */ +int XAxiVdma_StartWriteFrame(XAxiVdma *InstancePtr, + XAxiVdma_DmaSetup *DmaConfigPtr); +int XAxiVdma_StartReadFrame(XAxiVdma *InstancePtr, + XAxiVdma_DmaSetup *DmaConfigPtr); + +int XAxiVdma_DmaConfig(XAxiVdma *InstancePtr, u16 Direction, + XAxiVdma_DmaSetup *DmaConfigPtr); +int XAxiVdma_DmaSetBufferAddr(XAxiVdma *InstancePtr, u16 Direction, + u32 *BufferAddrSet); +int XAxiVdma_DmaStart(XAxiVdma *InstancePtr, u16 Direction); +void XAxiVdma_DmaStop(XAxiVdma *InstancePtr, u16 Direction); +void XAxiVdma_DmaRegisterDump(XAxiVdma *InstancePtr, u16 Direction); + +int XAxiVdma_SetFrameCounter(XAxiVdma *InstancePtr, + XAxiVdma_FrameCounter *FrameCounterCfgPtr); +void XAxiVdma_GetFrameCounter(XAxiVdma *InstancePtr, + XAxiVdma_FrameCounter *FrameCounterCfgPtr); + +/* + * Interrupt related functions in xaxivdma_intr.c + */ +void XAxiVdma_ReadIntrHandler(void * InstancePtr); +void XAxiVdma_WriteIntrHandler(void * InstancePtr); +int XAxiVdma_SetCallBack(XAxiVdma * InstancePtr, u32 HandlerType, + void *CallBackFunc, void *CallBackRef, u16 Direction); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_channel.c b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_channel.c new file mode 100644 index 00000000..f53331a1 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_channel.c @@ -0,0 +1,1480 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 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 xaxivdma_channel.c +* +* Implementation of the channel related functions. These functions are used +* internally by the driver, and are declared in xaxivdma_i.h. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   08/16/10 First release
+* 2.00a jz   12/10/10 Added support for direct register access mode, v3 core
+* 2.01a jz   01/19/11 Added ability to re-assign BD addresses
+* 	rkv  03/28/11 XAxiVdma_ChannelInit API is changed.
+* 3.02a srt  08/26/11 - XAxiVdma_ChannelErrors API is changed to support for
+*			Flush on Frame Sync feature.
+*		      - Two flags, XST_VDMA_MISMATCH_ERROR & XAXIVDMA_MIS
+*			MATCH_ERROR are added to report error status when
+*			Flush on Frame Sync feature is enabled.
+* 4.00a srt  11/21/11 - XAxiVdma_ChannelSetBufferAddr API is changed to
+*			support 32 Frame Stores.
+*		      - XAxiVdma_ChannelConfig API is changed to support
+*			modified Park Offset Register bits.
+*		      - Added APIs:
+*			XAxiVdma_ChannelHiFrmAddrEnable()
+*			XAxiVdma_ChannelHiFrmAddrDisable()
+* 4.01a srt  06/13/12 - Added API:
+*			XAxiVdma_ClearChannelErrors()
+*			XAxiVdma_ChannelGetEnabledIntr()
+*		      - XAxiVdma_ChannelErrors API is changed to remove
+*			Mismatch error logic.
+*		      - Removed Error checking logic in the APIs. Provided
+*			User APIs to do this.
+* 4.04a srt  03/03/13 - Changes for IPv5.04a:
+*			Support for the GenlockRepeat Control bit (Bit 15)
+*                       (CR: 691391)
+*	     	- Support for *_ENABLE_DEBUG_INFO_* debug configuration
+*			parameters (CR: 703738)
+* 4.05a srt  04/26/13 - Added unalignment checks for Hsize and Stride
+*			(CR 710279)
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xaxivdma_hw.h" +#include "xaxivdma_i.h" +#include "xstatus.h" +#include "xaxivdma.h" + +/************************** Constant Definitions *****************************/ +/* Number of polling loops to do to check for reset completion + * + * This number is large enough to cover the maximum transfer length + * + * However, if the memory operation being throttled by the system, this number + * is not large enough + */ +#define XAXIVDMA_RESET_POLLING 1000 + + +/************************** Function Prototypes ******************************/ + +/* BD APIs, used by this file only + */ +static u32 XAxiVdma_BdRead(XAxiVdma_Bd *BdPtr, int Offset); +static void XAxiVdma_BdWrite(XAxiVdma_Bd *BdPtr, int Offset, u32 Value); +static void XAxiVdma_BdSetNextPtr(XAxiVdma_Bd *BdPtr, u32 NextPtr); +static void XAxiVdma_BdSetAddr(XAxiVdma_Bd *BdPtr, u32 Addr); +static int XAxiVdma_BdSetVsize(XAxiVdma_Bd *BdPtr, int Vsize); +static int XAxiVdma_BdSetHsize(XAxiVdma_Bd *BdPtr, int Vsize); +static int XAxiVdma_BdSetStride(XAxiVdma_Bd *BdPtr, int Stride); +static int XAxiVdma_BdSetFrmDly(XAxiVdma_Bd *BdPtr, int FrmDly); + +/*****************************************************************************/ +/* + * Translate virtual address to physical address + * + * When port this driver to other RTOS, please change this definition to + * be consistent with your target system. + * + * @param VirtAddr is the virtual address to work on + * + * @return + * The physical address of the virtual address + * + * @note + * The virtual address and the physical address are the same here. + * + *****************************************************************************/ +#define XAXIVDMA_VIRT_TO_PHYS(VirtAddr) \ + (VirtAddr) + +/*****************************************************************************/ +/** + * Set the channel to enable access to higher Frame Buffer Addresses (SG=0) + * + * @param Channel is the pointer to the channel to work on + * + * + *****************************************************************************/ +#define XAxiVdma_ChannelHiFrmAddrEnable(Channel) \ +{ \ + XAxiVdma_WriteReg(Channel->ChanBase, \ + XAXIVDMA_HI_FRMBUF_OFFSET, XAXIVDMA_REGINDEX_MASK); \ +} + +/*****************************************************************************/ +/** + * Set the channel to disable access higher Frame Buffer Addresses (SG=0) + * + * @param Channel is the pointer to the channel to work on + * + * + *****************************************************************************/ +#define XAxiVdma_ChannelHiFrmAddrDisable(Channel) \ +{ \ + XAxiVdma_WriteReg(Channel->ChanBase, \ + XAXIVDMA_HI_FRMBUF_OFFSET, (XAXIVDMA_REGINDEX_MASK >> 1)); \ +} + +/*****************************************************************************/ +/** + * Initialize a channel of a DMA engine + * + * This function initializes the BD ring for this channel + * + * @param Channel is the pointer to the DMA channel to work on + * + * @return + * None + * + *****************************************************************************/ +void XAxiVdma_ChannelInit(XAxiVdma_Channel *Channel) +{ + int i; + int NumFrames; + XAxiVdma_Bd *FirstBdPtr = &(Channel->BDs[0]); + XAxiVdma_Bd *LastBdPtr; + + /* Initialize the BD variables, so proper memory management + * can be done + */ + NumFrames = Channel->NumFrames; + Channel->IsValid = 0; + Channel->HeadBdPhysAddr = 0; + Channel->HeadBdAddr = 0; + Channel->TailBdPhysAddr = 0; + Channel->TailBdAddr = 0; + + LastBdPtr = &(Channel->BDs[NumFrames - 1]); + + /* Setup the BD ring + */ + memset((void *)FirstBdPtr, 0, NumFrames * sizeof(XAxiVdma_Bd)); + + for (i = 0; i < NumFrames; i++) { + XAxiVdma_Bd *BdPtr; + XAxiVdma_Bd *NextBdPtr; + + BdPtr = &(Channel->BDs[i]); + + /* The last BD connects to the first BD + */ + if (i == (NumFrames - 1)) { + NextBdPtr = FirstBdPtr; + } + else { + NextBdPtr = &(Channel->BDs[i + 1]); + } + + XAxiVdma_BdSetNextPtr(BdPtr, + XAXIVDMA_VIRT_TO_PHYS((u32)NextBdPtr)); + } + + Channel->AllCnt = NumFrames; + + /* Setup the BD addresses so that access the head/tail BDs fast + * + */ + Channel->HeadBdAddr = (u32)FirstBdPtr; + Channel->HeadBdPhysAddr = XAXIVDMA_VIRT_TO_PHYS((u32)FirstBdPtr); + + Channel->TailBdAddr = (u32)LastBdPtr; + Channel->TailBdPhysAddr = XAXIVDMA_VIRT_TO_PHYS((u32)LastBdPtr); + + + Channel->IsValid = 1; + + return; +} + +/*****************************************************************************/ +/** + * This function checks whether reset operation is done + * + * @param Channel is the pointer to the DMA channel to work on + * + * @return + * - 0 if reset is done + * - 1 if reset is still going + * + *****************************************************************************/ +int XAxiVdma_ChannelResetNotDone(XAxiVdma_Channel *Channel) +{ + return (XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) & + XAXIVDMA_CR_RESET_MASK); +} + +/*****************************************************************************/ +/** + * This function resets one DMA channel + * + * The registers will be default values after the reset + * + * @param Channel is the pointer to the DMA channel to work on + * + * @return + * None + * + *****************************************************************************/ +void XAxiVdma_ChannelReset(XAxiVdma_Channel *Channel) +{ + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, + XAXIVDMA_CR_RESET_MASK); + + return; +} + +/*****************************************************************************/ +/* + * Check whether a DMA channel is running + * + * @param Channel is the pointer to the channel to work on + * + * @return + * - non zero if the channel is running + * - 0 is the channel is idle + * + *****************************************************************************/ +int XAxiVdma_ChannelIsRunning(XAxiVdma_Channel *Channel) +{ + u32 Bits; + + /* If halted bit set, channel is not running + */ + Bits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET) & + XAXIVDMA_SR_HALTED_MASK; + + if (Bits) { + return 0; + } + + /* If Run/Stop bit low, then channel is not running + */ + Bits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) & + XAXIVDMA_CR_RUNSTOP_MASK; + + if (!Bits) { + return 0; + } + + return 1; +} + +/*****************************************************************************/ +/** + * Check whether a DMA channel is busy + * + * @param Channel is the pointer to the channel to work on + * + * @return + * - non zero if the channel is busy + * - 0 is the channel is idle + * + *****************************************************************************/ +int XAxiVdma_ChannelIsBusy(XAxiVdma_Channel *Channel) +{ + u32 Bits; + + /* If the channel is idle, then it is not busy + */ + Bits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET) & + XAXIVDMA_SR_IDLE_MASK; + + if (Bits) { + return 0; + } + + /* If the channel is halted, then it is not busy + */ + Bits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET) & + XAXIVDMA_SR_HALTED_MASK; + + if (Bits) { + return 0; + } + + /* Otherwise, it is busy + */ + return 1; +} + +/*****************************************************************************/ +/* + * Check DMA channel errors + * + * @param Channel is the pointer to the channel to work on + * + * @return + * Error bits of the channel, 0 means no errors + * + *****************************************************************************/ +u32 XAxiVdma_ChannelErrors(XAxiVdma_Channel *Channel) +{ + return (XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET) + & XAXIVDMA_SR_ERR_ALL_MASK); +} + +/*****************************************************************************/ +/* + * Clear DMA channel errors + * + * @param Channel is the pointer to the channel to work on + * @param ErrorMask is the mask of error bits to clear. + * + * @return + * None + * + *****************************************************************************/ +void XAxiVdma_ClearChannelErrors(XAxiVdma_Channel *Channel, u32 ErrorMask) +{ + u32 SrBits; + + /* Write on Clear bits */ + SrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET) + | ErrorMask; + + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET, + SrBits); + + return; +} + +/*****************************************************************************/ +/** + * Get the current status of a channel + * + * @param Channel is the pointer to the channel to work on + * + * @return + * The status of the channel + * + *****************************************************************************/ +u32 XAxiVdma_ChannelGetStatus(XAxiVdma_Channel *Channel) +{ + return XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET); +} + +/*****************************************************************************/ +/** + * Set the channel to run in parking mode + * + * @param Channel is the pointer to the channel to work on + * + * @return + * - XST_SUCCESS if everything is fine + * - XST_FAILURE if hardware is not running + * + *****************************************************************************/ +int XAxiVdma_ChannelStartParking(XAxiVdma_Channel *Channel) +{ + u32 CrBits; + + if (!XAxiVdma_ChannelIsRunning(Channel)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel is not running, cannot start park mode\r\n"); + + return XST_FAILURE; + } + + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) & + ~XAXIVDMA_CR_TAIL_EN_MASK; + + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, + CrBits); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Set the channel to run in circular mode, exiting parking mode + * + * @param Channel is the pointer to the channel to work on + * + * @return + * None + * + *****************************************************************************/ +void XAxiVdma_ChannelStopParking(XAxiVdma_Channel *Channel) +{ + u32 CrBits; + + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) | + XAXIVDMA_CR_TAIL_EN_MASK; + + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, + CrBits); + + return; +} + +/*****************************************************************************/ +/** + * Set the channel to run in frame count enable mode + * + * @param Channel is the pointer to the channel to work on + * + * @return + * None + * + *****************************************************************************/ +void XAxiVdma_ChannelStartFrmCntEnable(XAxiVdma_Channel *Channel) +{ + u32 CrBits; + + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) | + XAXIVDMA_CR_FRMCNT_EN_MASK; + + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, + CrBits); + + return; +} + +/*****************************************************************************/ +/** + * Setup BD addresses to a different memory region + * + * In some systems, it is convenient to put BDs into a certain region of the + * memory. This function enables that. + * + * @param Channel is the pointer to the channel to work on + * @param BdAddrPhys is the physical starting address for BDs + * @param BdAddrVirt is the Virtual starting address for BDs. For systems that + * do not use MMU, then virtual address is the same as physical address + * + * @return + * - XST_SUCCESS for a successful setup + * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used + * + * @notes + * We assume that the memory region starting from BdAddrPhys is large enough + * to hold all the BDs. + * + *****************************************************************************/ +int XAxiVdma_ChannelSetBdAddrs(XAxiVdma_Channel *Channel, u32 BdAddrPhys, + u32 BdAddrVirt) +{ + int NumFrames = Channel->AllCnt; + int i; + u32 NextPhys = BdAddrPhys; + u32 CurrVirt = BdAddrVirt; + + if (Channel->HasSG && XAxiVdma_ChannelIsBusy(Channel)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel is busy, cannot setup engine for transfer\r\n"); + + return XST_DEVICE_BUSY; + } + + memset((void *)BdAddrPhys, 0, NumFrames * sizeof(XAxiVdma_Bd)); + memset((void *)BdAddrVirt, 0, NumFrames * sizeof(XAxiVdma_Bd)); + + /* Set up the BD link list */ + for (i = 0; i < NumFrames; i++) { + XAxiVdma_Bd *BdPtr; + + BdPtr = (XAxiVdma_Bd *)CurrVirt; + + /* The last BD connects to the first BD + */ + if (i == (NumFrames - 1)) { + NextPhys = BdAddrPhys; + } + else { + NextPhys += sizeof(XAxiVdma_Bd); + } + + XAxiVdma_BdSetNextPtr(BdPtr, NextPhys); + CurrVirt += sizeof(XAxiVdma_Bd); + } + + /* Setup the BD addresses so that access the head/tail BDs fast + * + */ + Channel->HeadBdPhysAddr = BdAddrPhys; + Channel->HeadBdAddr = BdAddrVirt; + Channel->TailBdPhysAddr = BdAddrPhys + + (NumFrames - 1) * sizeof(XAxiVdma_Bd); + Channel->TailBdAddr = BdAddrVirt + + (NumFrames - 1) * sizeof(XAxiVdma_Bd); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Start a transfer + * + * This function setup the DMA engine and start the engine to do the transfer. + * + * @param Channel is the pointer to the channel to work on + * @param ChannelCfgPtr is the pointer to the setup structure + * + * @return + * - XST_SUCCESS for a successful submission + * - XST_FAILURE if channel has not being initialized + * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used + * - XST_INVAID_PARAM if parameters in config structure not valid + * + *****************************************************************************/ +int XAxiVdma_ChannelStartTransfer(XAxiVdma_Channel *Channel, + XAxiVdma_ChannelSetup *ChannelCfgPtr) +{ + int Status; + + if (!Channel->IsValid) { + xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); + + return XST_FAILURE; + } + + if (Channel->HasSG && XAxiVdma_ChannelIsBusy(Channel)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel is busy, cannot setup engine for transfer\r\n"); + + return XST_DEVICE_BUSY; + } + + Status = XAxiVdma_ChannelConfig(Channel, ChannelCfgPtr); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel config failed %d\r\n", Status); + + return Status; + } + + Status = XAxiVdma_ChannelSetBufferAddr(Channel, + ChannelCfgPtr->FrameStoreStartAddr, Channel->AllCnt); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel setup buffer addr failed %d\r\n", Status); + + return Status; + } + + Status = XAxiVdma_ChannelStart(Channel); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel start failed %d\r\n", Status); + + return Status; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Configure one DMA channel using the configuration structure + * + * Setup the control register and BDs, however, BD addresses are not set. + * + * @param Channel is the pointer to the channel to work on + * @param ChannelCfgPtr is the pointer to the setup structure + * + * @return + * - XST_SUCCESS if successful + * - XST_FAILURE if channel has not being initialized + * - XST_DEVICE_BUSY if the DMA channel is not idle + * - XST_INVALID_PARAM if fields in ChannelCfgPtr is not valid + * + *****************************************************************************/ +int XAxiVdma_ChannelConfig(XAxiVdma_Channel *Channel, + XAxiVdma_ChannelSetup *ChannelCfgPtr) +{ + u32 CrBits; + int i; + int NumBds; + int Status; + u32 WordLenBits; + + if (!Channel->IsValid) { + xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); + + return XST_FAILURE; + } + + if (Channel->HasSG && XAxiVdma_ChannelIsBusy(Channel)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel is busy, cannot config!\r\n"); + + return XST_DEVICE_BUSY; + } + + Channel->Vsize = ChannelCfgPtr->VertSizeInput; + + WordLenBits = (u32)(Channel->WordLength - 1); + + /* If hardware has no DRE, then Hsize and Stride must + * be word-aligned + */ + if (!Channel->HasDRE) { + if (ChannelCfgPtr->HoriSizeInput & WordLenBits) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Unaligned Hsize %x: without DRE\r\n", + ChannelCfgPtr->HoriSizeInput); + + return XST_INVALID_PARAM; + } + if (ChannelCfgPtr->Stride & WordLenBits) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Unaligned Stride %x: without DRE\r\n", + ChannelCfgPtr->Stride); + + return XST_INVALID_PARAM; + } + } + + Channel->Hsize = ChannelCfgPtr->HoriSizeInput; + + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, + XAXIVDMA_CR_OFFSET); + + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) & + ~(XAXIVDMA_CR_TAIL_EN_MASK | XAXIVDMA_CR_SYNC_EN_MASK | + XAXIVDMA_CR_FRMCNT_EN_MASK | XAXIVDMA_CR_RD_PTR_MASK); + + if (ChannelCfgPtr->EnableCircularBuf) { + CrBits |= XAXIVDMA_CR_TAIL_EN_MASK; + } + else { + /* Park mode */ + u32 FrmBits; + u32 RegValue; + + if ((!XAxiVdma_ChannelIsRunning(Channel)) && + Channel->HasSG) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel is not running, cannot set park mode\r\n"); + + return XST_INVALID_PARAM; + } + + if (ChannelCfgPtr->FixedFrameStoreAddr > XAXIVDMA_FRM_MAX) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Invalid frame to park on %d\r\n", + ChannelCfgPtr->FixedFrameStoreAddr); + + return XST_INVALID_PARAM; + } + + if (Channel->IsRead) { + FrmBits = ChannelCfgPtr->FixedFrameStoreAddr & + XAXIVDMA_PARKPTR_READREF_MASK; + + RegValue = XAxiVdma_ReadReg(Channel->InstanceBase, + XAXIVDMA_PARKPTR_OFFSET); + + RegValue &= ~XAXIVDMA_PARKPTR_READREF_MASK; + + RegValue |= FrmBits; + + XAxiVdma_WriteReg(Channel->InstanceBase, + XAXIVDMA_PARKPTR_OFFSET, RegValue); + } + else { + FrmBits = ChannelCfgPtr->FixedFrameStoreAddr << + XAXIVDMA_WRTREF_SHIFT; + + FrmBits &= XAXIVDMA_PARKPTR_WRTREF_MASK; + + RegValue = XAxiVdma_ReadReg(Channel->InstanceBase, + XAXIVDMA_PARKPTR_OFFSET); + + RegValue &= ~XAXIVDMA_PARKPTR_WRTREF_MASK; + + RegValue |= FrmBits; + + XAxiVdma_WriteReg(Channel->InstanceBase, + XAXIVDMA_PARKPTR_OFFSET, RegValue); + } + } + + if (ChannelCfgPtr->EnableSync) { + if (Channel->GenLock != XAXIVDMA_GENLOCK_MASTER) + CrBits |= XAXIVDMA_CR_SYNC_EN_MASK; + } + + if (ChannelCfgPtr->GenLockRepeat) { + if ((Channel->GenLock == XAXIVDMA_GENLOCK_MASTER) || + (Channel->GenLock == XAXIVDMA_DYN_GENLOCK_MASTER)) + CrBits |= XAXIVDMA_CR_GENLCK_RPT_MASK; + } + + if (ChannelCfgPtr->EnableFrameCounter) { + CrBits |= XAXIVDMA_CR_FRMCNT_EN_MASK; + } + + CrBits |= (ChannelCfgPtr->PointNum << XAXIVDMA_CR_RD_PTR_SHIFT) & + XAXIVDMA_CR_RD_PTR_MASK; + + /* Write the control register value out + */ + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, + CrBits); + + if (Channel->HasSG) { + /* Setup the information in BDs + * + * All information is available except the buffer addrs + * Buffer addrs are set through XAxiVdma_ChannelSetBufferAddr() + */ + NumBds = Channel->AllCnt; + + for (i = 0; i < NumBds; i++) { + XAxiVdma_Bd *BdPtr = (XAxiVdma_Bd *)(Channel->HeadBdAddr + + i * sizeof(XAxiVdma_Bd)); + + Status = XAxiVdma_BdSetVsize(BdPtr, + ChannelCfgPtr->VertSizeInput); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Set vertical size failed %d\r\n", Status); + + return Status; + } + + Status = XAxiVdma_BdSetHsize(BdPtr, + ChannelCfgPtr->HoriSizeInput); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Set horizontal size failed %d\r\n", Status); + + return Status; + } + + Status = XAxiVdma_BdSetStride(BdPtr, + ChannelCfgPtr->Stride); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Set stride size failed %d\r\n", Status); + + return Status; + } + + Status = XAxiVdma_BdSetFrmDly(BdPtr, + ChannelCfgPtr->FrameDelay); + if (Status != XST_SUCCESS) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Set frame delay failed %d\r\n", Status); + + return Status; + } + } + } + else { /* direct register mode */ + if ((ChannelCfgPtr->VertSizeInput > XAXIVDMA_MAX_VSIZE) || + (ChannelCfgPtr->VertSizeInput <= 0) || + (ChannelCfgPtr->HoriSizeInput > XAXIVDMA_MAX_HSIZE) || + (ChannelCfgPtr->HoriSizeInput <= 0) || + (ChannelCfgPtr->Stride > XAXIVDMA_MAX_STRIDE) || + (ChannelCfgPtr->Stride <= 0) || + (ChannelCfgPtr->FrameDelay < 0) || + (ChannelCfgPtr->FrameDelay > XAXIVDMA_FRMDLY_MAX)) { + + return XST_INVALID_PARAM; + } + + XAxiVdma_WriteReg(Channel->StartAddrBase, + XAXIVDMA_HSIZE_OFFSET, ChannelCfgPtr->HoriSizeInput); + + XAxiVdma_WriteReg(Channel->StartAddrBase, + XAXIVDMA_STRD_FRMDLY_OFFSET, + (ChannelCfgPtr->FrameDelay << XAXIVDMA_FRMDLY_SHIFT) | + ChannelCfgPtr->Stride); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Configure buffer addresses for one DMA channel + * + * The buffer addresses are physical addresses. + * Access to 32 Frame Buffer Addresses in direct mode is done through + * XAxiVdma_ChannelHiFrmAddrEnable/Disable Functions. + * 0 - Access Bank0 Registers (0x5C - 0x98) + * 1 - Access Bank1 Registers (0x5C - 0x98) + * + * @param Channel is the pointer to the channel to work on + * @param BufferAddrSet is the set of addresses for the transfers + * @param NumFrames is the number of frames to set the address + * + * @return + * - XST_SUCCESS if successful + * - XST_FAILURE if channel has not being initialized + * - XST_DEVICE_BUSY if the DMA channel is not idle, BDs are still being used + * - XST_INVAID_PARAM if buffer address not valid, for example, unaligned + * address with no DRE built in the hardware + * + *****************************************************************************/ +int XAxiVdma_ChannelSetBufferAddr(XAxiVdma_Channel *Channel, + u32 *BufferAddrSet, int NumFrames) +{ + int i; + u32 WordLenBits; + int HiFrmAddr = 0; + int FrmBound = (XAXIVDMA_MAX_FRAMESTORE)/2 - 1; + int Loop16 = 0; + + if (!Channel->IsValid) { + xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); + + return XST_FAILURE; + } + + WordLenBits = (u32)(Channel->WordLength - 1); + + /* If hardware has no DRE, then buffer addresses must + * be word-aligned + */ + for (i = 0; i < NumFrames; i++) { + if (!Channel->HasDRE) { + if (BufferAddrSet[i] & WordLenBits) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Unaligned address %d: %x without DRE\r\n", + i, BufferAddrSet[i]); + + return XST_INVALID_PARAM; + } + } + } + + for (i = 0; i < NumFrames; i++, Loop16++) { + XAxiVdma_Bd *BdPtr = (XAxiVdma_Bd *)(Channel->HeadBdAddr + + i * sizeof(XAxiVdma_Bd)); + + if (Channel->HasSG) { + XAxiVdma_BdSetAddr(BdPtr, BufferAddrSet[i]); + } + else { + if ((i > FrmBound) && !HiFrmAddr) { + XAxiVdma_ChannelHiFrmAddrEnable(Channel); + HiFrmAddr = 1; + Loop16 = 0; + } + + XAxiVdma_WriteReg(Channel->StartAddrBase, + XAXIVDMA_START_ADDR_OFFSET + + Loop16 * XAXIVDMA_START_ADDR_LEN, + BufferAddrSet[i]); + + if ((NumFrames > FrmBound) && (i == (NumFrames - 1))) + XAxiVdma_ChannelHiFrmAddrDisable(Channel); + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Start one DMA channel + * + * @param Channel is the pointer to the channel to work on + * + * @return + * - XST_SUCCESS if successful + * - XST_FAILURE if channel is not initialized + * - XST_DMA_ERROR if: + * . The DMA channel fails to stop + * . The DMA channel fails to start + * - XST_DEVICE_BUSY is the channel is doing transfers + * + *****************************************************************************/ +int XAxiVdma_ChannelStart(XAxiVdma_Channel *Channel) +{ + u32 CrBits; + + if (!Channel->IsValid) { + xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); + + return XST_FAILURE; + } + + if (Channel->HasSG && XAxiVdma_ChannelIsBusy(Channel)) { + + xdbg_printf(XDBG_DEBUG_ERROR, + "Start DMA channel while channel is busy\r\n"); + + return XST_DEVICE_BUSY; + } + + /* If channel is not running, setup the CDESC register and + * set the channel to run + */ + if (!XAxiVdma_ChannelIsRunning(Channel)) { + + if (Channel->HasSG) { + /* Set up the current bd register + * + * Can only setup current bd register when channel is halted + */ + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CDESC_OFFSET, + Channel->HeadBdPhysAddr); + } + + /* Start DMA hardware + */ + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, + XAXIVDMA_CR_OFFSET); + + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, + XAXIVDMA_CR_OFFSET) | XAXIVDMA_CR_RUNSTOP_MASK; + + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, + CrBits); + + } + + if (XAxiVdma_ChannelIsRunning(Channel)) { + + /* Start DMA transfers + * + */ + + if (Channel->HasSG) { + /* SG mode: + * Update the tail pointer so that hardware will start + * fetching BDs + */ + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_TDESC_OFFSET, + Channel->TailBdPhysAddr); + } + else { + /* Direct register mode: + * Update vsize to start the channel + */ + XAxiVdma_WriteReg(Channel->StartAddrBase, + XAXIVDMA_VSIZE_OFFSET, Channel->Vsize); + + } + + return XST_SUCCESS; + } + else { + xdbg_printf(XDBG_DEBUG_ERROR, + "Failed to start channel %x\r\n", + (unsigned int)Channel->ChanBase); + + return XST_DMA_ERROR; + } +} + +/*****************************************************************************/ +/** + * Stop one DMA channel + * + * @param Channel is the pointer to the channel to work on + * + * @return + * None + * + *****************************************************************************/ +void XAxiVdma_ChannelStop(XAxiVdma_Channel *Channel) +{ + u32 CrBits; + + if (!XAxiVdma_ChannelIsRunning(Channel)) { + return; + } + + /* Clear the RS bit in CR register + */ + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) & + (~XAXIVDMA_CR_RUNSTOP_MASK); + + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, CrBits); + + return; +} + +/*****************************************************************************/ +/** + * Dump registers from one DMA channel + * + * @param Channel is the pointer to the channel to work on + * + * @return + * None + * + *****************************************************************************/ +void XAxiVdma_ChannelRegisterDump(XAxiVdma_Channel *Channel) +{ + xil_printf("Dump register for channel %x:\r\n", Channel->ChanBase); + xil_printf("\tControl Reg: %x\r\n", + XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET)); + xil_printf("\tStatus Reg: %x\r\n", + XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET)); + xil_printf("\tCDESC Reg: %x\r\n", + XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CDESC_OFFSET)); + xil_printf("\tTDESC Reg: %x\r\n", + XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_TDESC_OFFSET)); + + return; +} + +/*****************************************************************************/ +/** + * Set the frame counter and delay counter for one channel + * + * @param Channel is the pointer to the channel to work on + * @param FrmCnt is the frame counter value to be set + * @param DlyCnt is the delay counter value to be set + * + * @return + * - XST_SUCCESS if setup finishes successfully + * - XST_FAILURE if channel is not initialized + * - XST_INVALID_PARAM if the configuration structure has invalid values + * - XST_NO_FEATURE if Frame Counter or Delay Counter is disabled + * + *****************************************************************************/ +int XAxiVdma_ChannelSetFrmCnt(XAxiVdma_Channel *Channel, u8 FrmCnt, u8 DlyCnt) +{ + u32 CrBits; + + if (!Channel->IsValid) { + xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); + + return XST_FAILURE; + } + + if (!FrmCnt) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Frame counter value must be non-zero\r\n"); + + return XST_INVALID_PARAM; + } + + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) & + ~(XAXIVDMA_DELAY_MASK | XAXIVDMA_FRMCNT_MASK); + + if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_FRM_CNTR) { + CrBits |= (FrmCnt << XAXIVDMA_FRMCNT_SHIFT); + } else { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel Frame counter is disabled\r\n"); + return XST_NO_FEATURE; + } + if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_DLY_CNTR) { + CrBits |= (DlyCnt << XAXIVDMA_DELAY_SHIFT); + } else { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel Delay counter is disabled\r\n"); + return XST_NO_FEATURE; + } + + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, + CrBits); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** + * Get the frame counter and delay counter for both channels + * + * @param Channel is the pointer to the channel to work on + * @param FrmCnt is the pointer for the returning frame counter value + * @param DlyCnt is the pointer for the returning delay counter value + * + * @return + * None + * + * @note + * If FrmCnt return as 0, then the channel is not initialized + *****************************************************************************/ +void XAxiVdma_ChannelGetFrmCnt(XAxiVdma_Channel *Channel, u8 *FrmCnt, + u8 *DlyCnt) +{ + u32 CrBits; + + if (!Channel->IsValid) { + xdbg_printf(XDBG_DEBUG_ERROR, "Channel not initialized\r\n"); + + *FrmCnt = 0; + return; + } + + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET); + + if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_FRM_CNTR) { + *FrmCnt = (CrBits & XAXIVDMA_FRMCNT_MASK) >> + XAXIVDMA_FRMCNT_SHIFT; + } else { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel Frame counter is disabled\r\n"); + } + if (Channel->DbgFeatureFlags & XAXIVDMA_ENABLE_DBG_DLY_CNTR) { + *DlyCnt = (CrBits & XAXIVDMA_DELAY_MASK) >> + XAXIVDMA_DELAY_SHIFT; + } else { + xdbg_printf(XDBG_DEBUG_ERROR, + "Channel Delay counter is disabled\r\n"); + } + + + return; +} + +/*****************************************************************************/ +/** + * Enable interrupts for a channel. Interrupts that are not specified by the + * interrupt mask are not affected. + * + * @param Channel is the pointer to the channel to work on + * @param IntrType is the interrupt mask for interrupts to be enabled + * + * @return + * None. + * + *****************************************************************************/ +void XAxiVdma_ChannelEnableIntr(XAxiVdma_Channel *Channel, u32 IntrType) +{ + u32 CrBits; + + if ((IntrType & XAXIVDMA_IXR_ALL_MASK) == 0) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Enable intr with null intr mask value %x\r\n", + (unsigned int)IntrType); + + return; + } + + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) & + ~XAXIVDMA_IXR_ALL_MASK; + + CrBits |= IntrType & XAXIVDMA_IXR_ALL_MASK; + + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, + CrBits); + + return; +} + +/*****************************************************************************/ +/** + * Disable interrupts for a channel. Interrupts that are not specified by the + * interrupt mask are not affected. + * + * @param Channel is the pointer to the channel to work on + * @param IntrType is the interrupt mask for interrupts to be disabled + * + * @return + * None. + * + *****************************************************************************/ +void XAxiVdma_ChannelDisableIntr(XAxiVdma_Channel *Channel, u32 IntrType) +{ + u32 CrBits; + u32 IrqBits; + + if ((IntrType & XAXIVDMA_IXR_ALL_MASK) == 0) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Disable intr with null intr mask value %x\r\n", + (unsigned int)IntrType); + + return; + } + + CrBits = XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET); + + IrqBits = (CrBits & XAXIVDMA_IXR_ALL_MASK) & + ~(IntrType & XAXIVDMA_IXR_ALL_MASK); + + CrBits &= ~XAXIVDMA_IXR_ALL_MASK; + + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET, + CrBits | IrqBits); + + return; +} + +/*****************************************************************************/ +/** + * Get pending interrupts of a channel. + * + * @param Channel is the pointer to the channel to work on + * + * @return + * The interrupts mask represents pending interrupts. + * + *****************************************************************************/ +u32 XAxiVdma_ChannelGetPendingIntr(XAxiVdma_Channel *Channel) +{ + return (XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET) & + XAXIVDMA_IXR_ALL_MASK); +} + +/*****************************************************************************/ +/** + * Clear interrupts of a channel. Interrupts that are not specified by the + * interrupt mask are not affected. + * + * @param Channel is the pointer to the channel to work on + * @param IntrType is the interrupt mask for interrupts to be cleared + * + * @return + * None. + * + *****************************************************************************/ +void XAxiVdma_ChannelIntrClear(XAxiVdma_Channel *Channel, u32 IntrType) +{ + + if ((IntrType & XAXIVDMA_IXR_ALL_MASK) == 0) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Clear intr with null intr mask value %x\r\n", + (unsigned int)IntrType); + + return; + } + + /* Only interrupts bits are writable in status register + */ + XAxiVdma_WriteReg(Channel->ChanBase, XAXIVDMA_SR_OFFSET, + IntrType & XAXIVDMA_IXR_ALL_MASK); + + return; +} + +/*****************************************************************************/ +/** + * Get the enabled interrupts of a channel. + * + * @param Channel is the pointer to the channel to work on + * + * @return + * The interrupts mask represents pending interrupts. + * + *****************************************************************************/ +u32 XAxiVdma_ChannelGetEnabledIntr(XAxiVdma_Channel *Channel) +{ + return (XAxiVdma_ReadReg(Channel->ChanBase, XAXIVDMA_CR_OFFSET) & + XAXIVDMA_IXR_ALL_MASK); +} + +/*********************** BD Functions ****************************************/ +/*****************************************************************************/ +/* + * Read one word from BD + * + * @param BdPtr is the BD to work on + * @param Offset is the byte offset to read from + * + * @return + * The word value + * + *****************************************************************************/ +static u32 XAxiVdma_BdRead(XAxiVdma_Bd *BdPtr, int Offset) +{ + return (*(u32 *)((u32)BdPtr + Offset)); +} + +/*****************************************************************************/ +/* + * Set one word in BD + * + * @param BdPtr is the BD to work on + * @param Offset is the byte offset to write to + * @param Value is the value to write to the BD + * + * @return + * None + * + *****************************************************************************/ +static void XAxiVdma_BdWrite(XAxiVdma_Bd *BdPtr, int Offset, u32 Value) +{ + *(u32 *)((u32)BdPtr + Offset) = Value; + + return; +} + +/*****************************************************************************/ +/* + * Set the next ptr from BD + * + * @param BdPtr is the BD to work on + * @param NextPtr is the next ptr to set in BD + * + * @return + * None + * + *****************************************************************************/ +static void XAxiVdma_BdSetNextPtr(XAxiVdma_Bd *BdPtr, u32 NextPtr) +{ + XAxiVdma_BdWrite(BdPtr, XAXIVDMA_BD_NDESC_OFFSET, NextPtr); + return; +} + +/*****************************************************************************/ +/* + * Set the start address from BD + * + * The address is physical address. + * + * @param BdPtr is the BD to work on + * @param Addr is the address to set in BD + * + * @return + * None + * + *****************************************************************************/ +static void XAxiVdma_BdSetAddr(XAxiVdma_Bd *BdPtr, u32 Addr) +{ + XAxiVdma_BdWrite(BdPtr, XAXIVDMA_BD_START_ADDR_OFFSET, Addr); + + return; +} + +/*****************************************************************************/ +/* + * Set the vertical size for a BD + * + * @param BdPtr is the BD to work on + * @param Vsize is the vertical size to set in BD + * + * @return + * - XST_SUCCESS if successful + * - XST_INVALID_PARAM if argument Vsize is invalid + * + *****************************************************************************/ +static int XAxiVdma_BdSetVsize(XAxiVdma_Bd *BdPtr, int Vsize) +{ + if ((Vsize <= 0) || (Vsize > XAXIVDMA_VSIZE_MASK)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Veritcal size %d is not valid\r\n", Vsize); + + return XST_INVALID_PARAM; + } + + XAxiVdma_BdWrite(BdPtr, XAXIVDMA_BD_VSIZE_OFFSET, Vsize); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/* + * Set the horizontal size for a BD + * + * @param BdPtr is the BD to work on + * @param Hsize is the horizontal size to set in BD + * + * @return + * - XST_SUCCESS if successful + * - XST_INVALID_PARAM if argument Hsize is invalid + * + *****************************************************************************/ +static int XAxiVdma_BdSetHsize(XAxiVdma_Bd *BdPtr, int Hsize) +{ + if ((Hsize <= 0) || (Hsize > XAXIVDMA_HSIZE_MASK)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Horizontal size %d is not valid\r\n", Hsize); + + return XST_INVALID_PARAM; + } + + XAxiVdma_BdWrite(BdPtr, XAXIVDMA_BD_HSIZE_OFFSET, Hsize); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/* + * Set the stride size for a BD + * + * @param BdPtr is the BD to work on + * @param Stride is the stride size to set in BD + * + * @return + * - XST_SUCCESS if successful + * - XST_INVALID_PARAM if argument Stride is invalid + * + *****************************************************************************/ +static int XAxiVdma_BdSetStride(XAxiVdma_Bd *BdPtr, int Stride) +{ + u32 Bits; + + if ((Stride <= 0) || (Stride > XAXIVDMA_STRIDE_MASK)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Stride size %d is not valid\r\n", Stride); + + return XST_INVALID_PARAM; + } + + Bits = XAxiVdma_BdRead(BdPtr, XAXIVDMA_BD_STRIDE_OFFSET) & + ~XAXIVDMA_STRIDE_MASK; + + XAxiVdma_BdWrite(BdPtr, XAXIVDMA_BD_STRIDE_OFFSET, Bits | Stride); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/* + * Set the frame delay for a BD + * + * @param BdPtr is the BD to work on + * @param FrmDly is the frame delay value to set in BD + * + * @return + * - XST_SUCCESS if successful + * - XST_INVALID_PARAM if argument FrmDly is invalid + * + *****************************************************************************/ +static int XAxiVdma_BdSetFrmDly(XAxiVdma_Bd *BdPtr, int FrmDly) +{ + u32 Bits; + + if ((FrmDly < 0) || (FrmDly > XAXIVDMA_FRMDLY_MAX)) { + xdbg_printf(XDBG_DEBUG_ERROR, + "FrmDly size %d is not valid\r\n", FrmDly); + + return XST_INVALID_PARAM; + } + + Bits = XAxiVdma_BdRead(BdPtr, XAXIVDMA_BD_STRIDE_OFFSET) & + ~XAXIVDMA_FRMDLY_MASK; + + XAxiVdma_BdWrite(BdPtr, XAXIVDMA_BD_STRIDE_OFFSET, + Bits | (FrmDly << XAXIVDMA_FRMDLY_SHIFT)); + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_g.c b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_g.c new file mode 100644 index 00000000..bd229d60 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_g.c @@ -0,0 +1,104 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 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 xaxivdma_g.c +* +* Provide a template for user to define their own hardware settings. +* +* If using XPS, this file will be automatically generated. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   08/16/10 First release
+* 2.00a jz   12/10/10 Added support for direct register access mode, v3 core
+* 2.01a jz   01/19/11 Added ability to re-assign BD addresses
+* 	rkv  04/07/11 added new configuration parameter for enabling read of
+*		      video parameters.
+* 3.00a srt  08/26/11 Added new parameters for Flush on Frame Sync and Line
+*		      Buffer Thresholds.
+* 4.00a srt  11/21/11 Added new parameters for Genlock Source and Fsync
+*		      Source Selection.
+* 4.03a srt  01/18/13 Added TDATA_WIDTH parameters (CR: 691866)
+* 4.04a srt	 03/03/13 Support for *_ENABLE_DEBUG_INFO_* debug configuration
+*			parameters (CR: 703738)
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xaxivdma.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +XAxiVdma_Config XAxiVdma_ConfigTable[] = +{ + { + XPAR_AXIVDMA_0_DEVICE_ID, + XPAR_AXIVDMA_0_BASEADDR, + XPAR_AXIVDMA_0_NUM_FSTORES, + XPAR_AXIVDMA_0_INCLUDE_MM2S, + XPAR_AXIVDMA_0_INCLUDE_MM2S_DRE, + XPAR_AXIVDMA_0_M_AXI_MM2S_DATA_WIDTH, + XPAR_AXIVDMA_0_INCLUDE_S2MM, + XPAR_AXIVDMA_0_INCLUDE_S2MM_DRE, + XPAR_AXIVDMA_0_M_AXI_S2MM_DATA_WIDTH, + XPAR_AXIVDMA_0_INCLUDE_SG, + XPAR_AXIVDMA_0_ENABLE_VIDPRMTR_READS, + XPAR_AXIVDMA_0_USE_FSYNC, + XPAR_AXIVDMA_0_FLUSH_ON_SYNC, + XPAR_AXIVDMA_0_MM2S_LINEBUFFER_DEPTH, + XPAR_AXIVDMA_0_S2MM_LINEBUFFER_DEPTH, + XPAR_AXIVDMA_0_MM2S_GENLOCK_MODE, + XPAR_AXIVDMA_0_S2MM_GENLOCK_MODE, + XPAR_AXIVDMA_0_INCLUDE_INTERNAL_GENLOCK, + XPAR_AXIVDMA_0_S2MM_SOF_ENABLE, + XPAR_AXIVDMA_0_M_AXIS_MM2S_TDATA_WIDTH, + XPAR_AXIVDMA_0_S_AXIS_S2MM_TDATA_WIDTH, + XPAR_AXIVDMA_0_ENABLE_DEBUG_INFO_1, + XPAR_AXIVDMA_0_ENABLE_DEBUG_INFO_5, + XPAR_AXIVDMA_0_ENABLE_DEBUG_INFO_6, + XPAR_AXIVDMA_0_ENABLE_DEBUG_INFO_7, + XPAR_AXIVDMA_0_ENABLE_DEBUG_INFO_9, + XPAR_AXIVDMA_0_ENABLE_DEBUG_INFO_13, + XPAR_AXIVDMA_0_ENABLE_DEBUG_INFO_14, + XPAR_AXIVDMA_0_ENABLE_DEBUG_INFO_15, + XPAR_AXIVDMA_0_ENABLE_DEBUG_ALL + } +}; diff --git a/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_hw.h b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_hw.h new file mode 100644 index 00000000..2e1c7140 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_hw.h @@ -0,0 +1,367 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 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 xaxivdma_hw.h + * + * Hardware definition file. It defines the register interface and Buffer + * Descriptor (BD) definitions. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a jz   07/30/10 First release
+ * 2.00a jz   12/10/10 Added support for direct register access mode, v3 core
+ * 2.01a jz   01/19/11 Added ability to re-assign BD addresses
+ * 	 rkv  03/28/11 Added support for frame store register.
+ * 3.00a srt  08/26/11 - Added support for Line Buffer Threshold Registers.
+ *		       - XAXIVDMA_MISMATCH_ERROR flag is added to support Flush
+ *		       	 on Frame Sync for Mismatch Errors.
+ * 4.00a srt  11/21/11 - XAxiVdma_ChannelSetBufferAddr API is changed to
+ *			 support 32 Frame Stores.
+ *		       - XAxiVdma_ChannelConfig API is changed to support
+ *			 modified Park Offset Register bits.
+ *		       - Added APIs:
+ *			 XAxiVdma_FsyncSrcSelect()
+ *			 XAxiVdma_GenLockSourceSelect()
+ *			 XAxiVdma_ChannelHiFrmAddrEnable()
+ *			 XAxiVdma_ChannelHiFrmAddrDisable()
+ * 4.01a srt  06/13/12 - Added new error bit mask XAXIVDMA_SR_ERR_SOF_LATE_MASK
+ *		       - XAXIVDMA_MISMATCH_ERROR flag is deprecated.
+ * 4.02a srt  10/11/12 - Changed Error bitmasks to support IP version 5.02a.
+ *			 (CR 679959)
+ * 4.04a srt  03/03/13 - Support for the GenlockRepeat Control bit (Bit 15)
+ *                       added in the new version of IP v5.04 (CR: 691391)
+ * 4.06a srt  04/09/13 - Added support for the newly added S2MM_DMA_IRQ_MASK
+ *			 register (CR 734741)
+ * 
+ * + *****************************************************************************/ + +#ifndef XAXIVDMA_HW_H_ /* prevent circular inclusions */ +#define XAXIVDMA_HW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "xil_types.h" +#include "xil_io.h" + + +/************************** Constant Definitions *****************************/ + +/** @name Buffer Descriptor Alignment + * @{ + */ +#define XAXIVDMA_BD_MINIMUM_ALIGNMENT 0x20 /**< Minimum byte alignment + requirement for descriptors */ +#define XAXIVDMA_BD_MINIMUM_ALIGNMENT_WD 0x8 /**< Minimum word alignment + requirement for descriptors */ +/** + * Maximum number of the frame store + */ +#define XAXIVDMA_MAX_FRAMESTORE 32 /**< Maximum # of the frame store */ + +/*@}*/ + +/** @name Maximum transfer length + * This is determined by hardware + * @{ + */ +#define XAXIVDMA_MAX_VSIZE 0x1FFF /* Max vertical size, 8K */ +#define XAXIVDMA_MAX_HSIZE 0xFFFF /* Max horizontal size, 64K */ +#define XAXIVDMA_MAX_STRIDE 0xFFFF /* Max stride size, 64K */ +#define XAXIVDMA_FRMDLY_MAX 0xF /**< Maximum frame delay */ +/*@}*/ + +/** + * Frame/Line Mismatch Error + * This is a typical DMA Internal Error, which on detection doesnt require + * a reset (as opposed to other errors). So a MSB bit is set to identify it, + * from other DMA Internal Errors. + * + */ +#define XAXIVDMA_MISMATCH_ERROR 0x80000010 +/* | |_ DMA Internal Error Bit. + * |_______ Set to identify Mismatch Errors. + */ + +/* Register offset definitions. Register accesses are 32-bit. + */ +/** @name Device registers + * Register sets on TX (Read) and RX (Write) channels are identical + * + * The version register is shared by both channels + * @{ + */ +#define XAXIVDMA_TX_OFFSET 0x00000000 /**< TX channel registers base */ +#define XAXIVDMA_RX_OFFSET 0x00000030 /**< RX channel registers base */ +#define XAXIVDMA_PARKPTR_OFFSET 0x00000028 /**< Park Pointer Register */ +#define XAXIVDMA_VERSION_OFFSET 0x0000002C /**< Version register */ + +/* This set of registers are applicable for both channels. Use + * XAXIVDMA_TX_OFFSET for the TX channel, and XAXIVDMA_RX_OFFSET for the + * RX channel + */ +#define XAXIVDMA_CR_OFFSET 0x00000000 /**< Channel control */ +#define XAXIVDMA_SR_OFFSET 0x00000004 /**< Status */ +#define XAXIVDMA_CDESC_OFFSET 0x00000008 /**< Current descriptor pointer */ +#define XAXIVDMA_TDESC_OFFSET 0x00000010 /**< Tail descriptor pointer */ +#define XAXIVDMA_HI_FRMBUF_OFFSET 0x00000014 /**< 32 FrameBuf Sel*/ +#define XAXIVDMA_FRMSTORE_OFFSET 0x00000018 /**< Frame Store */ +#define XAXIVDMA_BUFTHRES_OFFSET 0x0000001C /**< Line Buffer Thres */ +#define XAXIVDMA_MM2S_ADDR_OFFSET 0x00000050 /**< MM2S channel Addr */ +#define XAXIVDMA_S2MM_ADDR_OFFSET 0x000000A0 /**< S2MM channel Addr */ + +/* This register is specific to S2MM channel + */ +#define XAXIVDMA_S2MM_DMA_IRQ_MASK_OFFSET 0x0000003C /**< S2MM Err IRQ Mask*/ +/*@}*/ + +/** @name Start Addresses Register Array for a Channel + * + * Base offset is set in each channel + * This set of registers are write only, they can be read when + * C_ENABLE_VIDPRMTR_READS is 1. + * @{ + */ +#define XAXIVDMA_VSIZE_OFFSET 0x00000000 /**< Vertical size */ +#define XAXIVDMA_HSIZE_OFFSET 0x00000004 /**< Horizontal size */ +#define XAXIVDMA_STRD_FRMDLY_OFFSET 0x00000008 /**< Horizontal size */ +#define XAXIVDMA_START_ADDR_OFFSET 0x0000000C /**< Start of address */ +#define XAXIVDMA_START_ADDR_LEN 0x00000004 /**< Each entry is 4 bytes */ +/*@}*/ + +/** @name Bitmasks of the XAXIVDMA_CR_OFFSET register + * @{ + */ +#define XAXIVDMA_CR_RUNSTOP_MASK 0x00000001 /**< Start/stop DMA channel */ +#define XAXIVDMA_CR_TAIL_EN_MASK 0x00000002 /**< Tail ptr enable or Park */ +#define XAXIVDMA_CR_RESET_MASK 0x00000004 /**< Reset channel */ +#define XAXIVDMA_CR_SYNC_EN_MASK 0x00000008 /**< Gen-lock enable */ +#define XAXIVDMA_CR_FRMCNT_EN_MASK 0x00000010 /**< Frame count enable */ +#define XAXIVDMA_CR_FSYNC_SRC_MASK 0x00000060 /**< Fsync Source Select */ +#define XAXIVDMA_CR_GENLCK_SRC_MASK 0x00000080 /**< Genlock Source Select */ +#define XAXIVDMA_CR_RD_PTR_MASK 0x00000F00 /**< Read pointer number */ +#define XAXIVDMA_CR_GENLCK_RPT_MASK 0x00008000 /**< GenLock Repeat */ + +#define XAXIVDMA_CR_RD_PTR_SHIFT 8 /**< Shift for read pointer number */ +/*@}*/ + +/** @name Bitmasks of the XAXIVDMA_SR_OFFSET register + * This register reports status of a DMA channel, including + * run/stop/idle state, errors, and interrupts + * @{ + */ +#define XAXIVDMA_SR_HALTED_MASK 0x00000001 /**< DMA channel halted */ +#define XAXIVDMA_SR_IDLE_MASK 0x00000002 /**< DMA channel idle */ +#define XAXIVDMA_SR_ERR_INTERNAL_MASK 0x00000010 /**< Datamover internal err */ +#define XAXIVDMA_SR_ERR_SLAVE_MASK 0x00000020 /**< Datamover slave err */ +#define XAXIVDMA_SR_ERR_DECODE_MASK 0x00000040 /**< Datamover decode err */ +#define XAXIVDMA_SR_ERR_FSZ_LESS_MASK 0x00000080 /**< FSize Less Mismatch err */ +#define XAXIVDMA_SR_ERR_LSZ_LESS_MASK 0x00000100 /**< LSize Less Mismatch err */ +#define XAXIVDMA_SR_ERR_SG_SLV_MASK 0x00000200 /**< SG slave err */ +#define XAXIVDMA_SR_ERR_SG_DEC_MASK 0x00000400 /**< SG decode err */ +#define XAXIVDMA_SR_ERR_FSZ_MORE_MASK 0x00000800 /**< FSize More Mismatch err */ +#define XAXIVDMA_SR_ERR_ALL_MASK 0x00000FF0 /**< All errors */ + +/** @name Bitmask for interrupts + * These masks are shared by the XAXIVDMA_CR_OFFSET register and + * the XAXIVDMA_SR_OFFSET register + * @{ + */ +#define XAXIVDMA_IXR_FRMCNT_MASK 0x00001000 /**< Frame count intr */ +#define XAXIVDMA_IXR_DELAYCNT_MASK 0x00002000 /**< Delay interrupt */ +#define XAXIVDMA_IXR_ERROR_MASK 0x00004000 /**< Error interrupt */ +#define XAXIVDMA_IXR_COMPLETION_MASK 0x00003000 /**< Completion interrupts */ +#define XAXIVDMA_IXR_ALL_MASK 0x00007000 /**< All interrupts */ +/*@}*/ + +/** @name Bitmask and shift for delay and coalesce + * These masks are shared by the XAXIVDMA_CR_OFFSET register and + * the XAXIVDMA_SR_OFFSET register + * @{ + */ +#define XAXIVDMA_DELAY_MASK 0xFF000000 /**< Delay timeout counter */ +#define XAXIVDMA_FRMCNT_MASK 0x00FF0000 /**< Frame counter */ +#define XAXIVDMA_REGINDEX_MASK 0x00000001 /**< Register Index */ + +#define XAXIVDMA_DELAY_SHIFT 24 +#define XAXIVDMA_FRMCNT_SHIFT 16 +/*@}*/ + +/** @name Bitmask for the XAXIVDMA_CDESC_OFFSET register + * @{ + */ +#define XAXIVDMA_CDESC_CURBD_MASK 0xFFFFFFE0 /**< BD now working on */ +/*@}*/ + +/** @name Bitmask for XAXIVDMA_TDESC_OFFSET register + * @{ + */ +#define XAXIVDMA_TDESC_CURBD_MASK 0xFFFFFFE0 /**< BD to stop on */ +/*@}*/ + +/** @name Bitmask for XAXIVDMA_FRMSTORE_OFFSET register + * @{ + */ +#define XAXIVDMA_FRMSTORE_MASK 0x0000003F +/*@}*/ +/** @name Bitmask for XAXIVDMA_PARKPTR_OFFSET register + * @{ + */ +#define XAXIVDMA_PARKPTR_READREF_MASK 0x0000001F /**< Read frame to park on */ +#define XAXIVDMA_PARKPTR_WRTREF_MASK 0x00001F00 /**< Write frame to park on */ +#define XAXIVDMA_PARKPTR_READSTR_MASK 0x001F0000 /**< Current read frame */ +#define XAXIVDMA_PARKPTR_WRTSTR_MASK 0x1F000000 /**< Current write frame */ + +#define XAXIVDMA_READREF_SHIFT 0 +#define XAXIVDMA_WRTREF_SHIFT 8 +#define XAXIVDMA_READSTR_SHIFT 16 +#define XAXIVDMA_WRTSTR_SHIFT 24 + +#define XAXIVDMA_FRM_MAX 0xF /**< At most 16 frames */ +/*@}*/ + +/** @name Bitmask for XAXIVDMA_VERSION_OFFSET register + * @{ + */ +#define XAXIVDMA_VERSION_MAJOR_MASK 0xF0000000 /**< Major version */ +#define XAXIVDMA_VERSION_MINOR_MASK 0x0FF00000 /**< Minor version */ +#define XAXIVDMA_VERSION_REV_MASK 0x000F0000 /**< Revision letter */ + +#define XAXIVDMA_VERSION_MAJOR_SHIFT 28 +#define XAXIVDMA_VERSION_MINOR_SHIFT 20 +/*@}*/ + +/** @name Bitmask for XAXIVDMA_S2MM_IRQ_MASK_OFFSET register + * @{ + */ +#define XAXIVDMA_S2MM_IRQ_FSZLESS_SOF_ERLY_MASK 0x00000001 /**< Masks S2MM + IRQ FSize Less/SOF + Early Error */ +#define XAXIVDMA_S2MM_IRQ_LSZLESS_EOL_ERLY_MASK 0x00000002 /**< Masks S2MM + IRQ LSize Less/EOL + Early Error */ +#define XAXIVDMA_S2MM_IRQ_FSZMORE_SOF_LATE_MASK 0x00000004 /**< Masks S2MM + IRQ FSize More/SOF + Late Error */ +#define XAXIVDMA_S2MM_IRQ_LSZMORE_EOL_LATE_MASK 0x00000008 /**< Masks S2MM + IRQ LSize More/EOL + Late Error */ +#define XAXIVDMA_S2MM_IRQ_ERR_ALL_MASK 0x0000000F /**< Masks all + S2MM IRQ Errors */ +/*@}*/ + +/** @name Frame Delay shared by start address registers and BDs + * + * @{ + */ +#define XAXIVDMA_VSIZE_MASK 0x00001FFF /**< Vertical size */ +#define XAXIVDMA_HSIZE_MASK 0x0000FFFF /**< Horizontal size */ +#define XAXIVDMA_STRIDE_MASK 0x0000FFFF /**< Stride size */ +#define XAXIVDMA_FRMDLY_MASK 0x0F000000 /**< Frame delay */ + +#define XAXIVDMA_FRMDLY_SHIFT 24 /**< Shift for frame delay */ +/*@}*/ + +/* Buffer Descriptor (BD) definitions + */ + +/** @name Buffer Descriptor offsets + * + * @{ + */ +#define XAXIVDMA_BD_NDESC_OFFSET 0x00 /**< Next descriptor pointer */ +#define XAXIVDMA_BD_START_ADDR_OFFSET 0x08 /**< Start address */ +#define XAXIVDMA_BD_VSIZE_OFFSET 0x10 /**< Vertical size */ +#define XAXIVDMA_BD_HSIZE_OFFSET 0x14 /**< Horizontal size */ +#define XAXIVDMA_BD_STRIDE_OFFSET 0x18 /**< Stride size */ + +#define XAXIVDMA_BD_NUM_WORDS 7 /**< Total number of words for one BD*/ +#define XAXIVDMA_BD_HW_NUM_BYTES 28 /**< Number of bytes hw used */ +#define XAXIVDMA_BD_BYTES_TO_CLEAR 20 /**< Skip next ptr when clearing */ +/*@}*/ + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XAxiVdma_In32 Xil_In32 +#define XAxiVdma_Out32 Xil_Out32 + +/*****************************************************************************/ +/** +* +* Read the given register. +* +* @param BaseAddress is the base address of the device +* @param RegOffset is the register offset to be read +* +* @return The 32-bit value of the register +* +* @note +* C-style signature: +* u32 XAxiVdma_ReadReg(u32 BaseAddress, u32 RegOffset) +* +******************************************************************************/ +#define XAxiVdma_ReadReg(BaseAddress, RegOffset) \ + XAxiVdma_In32((BaseAddress) + (RegOffset)) + +/*****************************************************************************/ +/** +* +* Write the given register. +* +* @param BaseAddress is the base address of the device +* @param RegOffset is the register offset to be written +* @param Data is the 32-bit value to write to the register +* +* @return None. +* +* @note +* C-style signature: +* void XAxiVdma_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +******************************************************************************/ +#define XAxiVdma_WriteReg(BaseAddress, RegOffset, Data) \ + XAxiVdma_Out32((BaseAddress) + (RegOffset), (Data)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_i.h b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_i.h new file mode 100644 index 00000000..b88d6481 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_i.h @@ -0,0 +1,178 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 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 xaxivdma_i.h + * + * Internal API definitions shared by driver files. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -------------------------------------------------------
+ * 1.00a jz   08/18/10 First release
+ * 2.00a jz   12/10/10 Added support for direct register access mode, v3 core
+ * 2.01a jz   01/19/11 Added ability to re-assign BD addresses
+ *		       Replaced include xenv.h with string.h in xaxivdma_i.h
+ * 		       file.
+ *  	 rkv  03/28/11 Added support for frame store register.
+ * 3.00a srt  08/26/11 Added support for Flush on Frame Sync and dynamic
+ *		       programming of Line Buffer Thresholds.
+ * 4.00a srt  11/21/11 Added support for 32 Frame Stores and modified bit
+ *		       mask of Park Offset Register.
+ *		       Added support for GenLock & Fsync Source Selection.
+ * 4.03a srt  01/18/13 -  Added StreamWidth parameter to XAxiVdma_Channel
+ *		       structure (CR 691866).
+ * 4.04a srt  03/03/13 Support for the GenlockRepeat Control bit (Bit 15)
+ *                     added in the new version of IP v5.04 (CR: 691391)
+ *					 - Support for *_ENABLE_DEBUG_INFO_* debug configuration
+ *			           parameters (CR: 703738)
+ *
+ * 
+ * + *****************************************************************************/ + +#ifndef XAXIVDMA_I_H_ /* prevent circular inclusions */ +#define XAXIVDMA_I_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include /* memset */ +#include "xil_types.h" +#include "xdebug.h" + +/************************** Constant Definitions *****************************/ +/**************************** Type Definitions *******************************/ +/* Buffer Descriptor (BD) is only visible in this file + */ +typedef u32 XAxiVdma_Bd[XAXIVDMA_BD_MINIMUM_ALIGNMENT_WD]; + +/* The DMA channel is only visible to driver files + */ +typedef struct { + u32 ChanBase; /* Base address for this channel */ + u32 InstanceBase; /* Base address for the whole device */ + u32 StartAddrBase; /* Start address register array base */ + + int IsValid; /* Whether the channel has been initialized */ + int FlushonFsync; /* VDMA Transactions are flushed & channel states + reset on Frame Sync */ + int HasSG; /* Whether hardware has SG engine */ + int IsRead; /* Read or write channel */ + int HasDRE; /* Whether support unaligned transfer */ + int LineBufDepth; /* Depth of Channel Line Buffer FIFO */ + int LineBufThreshold; /* Threshold point at which Channel Line + * almost empty flag asserts high */ + int WordLength; /* Word length */ + int NumFrames; /* Number of frames to work on */ + + u32 HeadBdPhysAddr; /* Physical address of the first BD */ + u32 HeadBdAddr; /* Virtual address of the first BD */ + u32 TailBdPhysAddr; /* Physical address of the last BD */ + u32 TailBdAddr; /* Virtual address of the last BD */ + int Hsize; /* Horizontal size */ + int Vsize; /* Vertical size saved for no-sg mode hw start */ + + int AllCnt; /* Total number of BDs */ + + int GenLock; /* Mm2s Gen Lock Mode */ + int S2MmSOF; /* S2MM Start of Flag */ + int StreamWidth; /* Stream Width */ + XAxiVdma_Bd BDs[XAXIVDMA_MAX_FRAMESTORE] __attribute__((__aligned__(32))); + /*Statically allocated BDs */ + u32 DbgFeatureFlags; /* Debug Parameter Flags */ +}XAxiVdma_Channel; + +/* Duplicate layout of XAxiVdma_DmaSetup + * + * So to remove the dependency on xaxivdma.h + */ +typedef struct { + int VertSizeInput; /**< Vertical size input */ + int HoriSizeInput; /**< Horizontal size input */ + int Stride; /**< Stride */ + int FrameDelay; /**< Frame Delay */ + + int EnableCircularBuf; /**< Circular Buffer Mode? */ + int EnableSync; /**< Gen-Lock Mode? */ + int PointNum; /**< Master we synchronize with */ + int EnableFrameCounter; /**< Frame Counter Enable */ + u32 FrameStoreStartAddr[XAXIVDMA_MAX_FRAMESTORE]; + /**< Start Addresses of Frame Store Buffers. */ + int FixedFrameStoreAddr;/**< Fixed Frame Store Address index */ + int GenLockRepeat; /**< Gen-Lock Repeat? */ +}XAxiVdma_ChannelSetup; + +/************************** Function Prototypes ******************************/ +/* Channel API + */ +void XAxiVdma_ChannelInit(XAxiVdma_Channel *Channel); +void XAxiVdma_ChannelReset(XAxiVdma_Channel *Channel); +int XAxiVdma_ChannelResetNotDone(XAxiVdma_Channel *Channel); +int XAxiVdma_ChannelIsRunning(XAxiVdma_Channel *Channel); +int XAxiVdma_ChannelIsBusy(XAxiVdma_Channel *Channel); +u32 XAxiVdma_ChannelGetStatus(XAxiVdma_Channel *Channel); +void XAxiVdma_ChannelRegisterDump(XAxiVdma_Channel *Channel); + +int XAxiVdma_ChannelStartParking(XAxiVdma_Channel *Channel); +void XAxiVdma_ChannelStopParking(XAxiVdma_Channel *Channel); +void XAxiVdma_ChannelStartFrmCntEnable(XAxiVdma_Channel *Channel); + +void XAxiVdma_ChannelEnableIntr(XAxiVdma_Channel *Channel, u32 IntrType); +void XAxiVdma_ChannelDisableIntr(XAxiVdma_Channel *Channel, u32 IntrType); +u32 XAxiVdma_ChannelGetPendingIntr(XAxiVdma_Channel *Channel); +u32 XAxiVdma_ChannelGetEnabledIntr(XAxiVdma_Channel *Channel); +void XAxiVdma_ChannelIntrClear(XAxiVdma_Channel *Channel, u32 IntrType); +int XAxiVdma_ChannelStartTransfer(XAxiVdma_Channel *Channel, + XAxiVdma_ChannelSetup *ChannelCfgPtr); +int XAxiVdma_ChannelSetBdAddrs(XAxiVdma_Channel *Channel, u32 BdAddrPhys, + u32 BdAddrVirt); +int XAxiVdma_ChannelConfig(XAxiVdma_Channel *Channel, + XAxiVdma_ChannelSetup *ChannelCfgPtr); +int XAxiVdma_ChannelSetBufferAddr(XAxiVdma_Channel *Channel, u32 *AddrSet, + int NumFrames); +int XAxiVdma_ChannelStart(XAxiVdma_Channel *Channel); +void XAxiVdma_ChannelStop(XAxiVdma_Channel *Channel); +int XAxiVdma_ChannelSetFrmCnt(XAxiVdma_Channel *Channel, u8 FrmCnt, + u8 DlyCnt); +void XAxiVdma_ChannelGetFrmCnt(XAxiVdma_Channel *Channel, u8 *FrmCnt, + u8 *DlyCnt); +u32 XAxiVdma_ChannelErrors(XAxiVdma_Channel *Channel); +void XAxiVdma_ClearChannelErrors(XAxiVdma_Channel *Channel, u32 ErrorMask); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_intr.c b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_intr.c new file mode 100644 index 00000000..9ccea8bb --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_intr.c @@ -0,0 +1,407 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 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 xaxivdma_intr.c +* +* Implementation of interrupt related functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   08/16/10 First release
+* 2.00a jz   12/10/10 Added support for direct register access mode, v3 core
+* 2.01a jz   01/19/11 Added ability to re-assign BD addresses
+* 4.01a srt  06/13/12 Modified the logic of Error handling in interrupt
+*		      handlers.
+* 4.06a srt  04/09/13 Added API XAxiVdma_MaskS2MMErrIntr which will mask
+*		      the S2MM interrupt for the error mask provided.
+*		      (CR 734741)
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xaxivdma.h" +#include "xaxivdma_i.h" + +/*****************************************************************************/ +/** + * Enable specific interrupts for a channel + * + * Interrupts not specified by the mask will not be affected + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the DMA channel, use XAXIVDMA_READ or XAXIVDMA_WRITE + * @param IntrType is the bit mask for the interrups to be enabled + * + * @return + * None + * + * @note + * If channel is invalid, then nothing is done + *****************************************************************************/ +void XAxiVdma_IntrEnable(XAxiVdma *InstancePtr, u32 IntrType, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (Channel->IsValid) { + XAxiVdma_ChannelEnableIntr(Channel, IntrType); + } + + return; +} + +/*****************************************************************************/ +/** + * Disable specific interrupts for a channel + * + * Interrupts not specified by the mask will not be affected + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param IntrType is the bit mask for the interrups to be disabled + * @param Direction is the DMA channel, use XAXIVDMA_READ or XAXIVDMA_WRITE + * + * @return + * None + * + * @note + * If channel is invalid, then nothing is done + *****************************************************************************/ +void XAxiVdma_IntrDisable(XAxiVdma *InstancePtr, u32 IntrType, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (Channel->IsValid) { + XAxiVdma_ChannelDisableIntr(Channel, IntrType); + } + + return; +} + +/*****************************************************************************/ +/** + * Get the pending interrupts of a channel + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the DMA channel, use XAXIVDMA_READ or XAXIVDMA_WRITE + * + * @return + * The bit mask for the currently pending interrupts + * + * @note + * If Direction is invalid, return 0 + *****************************************************************************/ +u32 XAxiVdma_IntrGetPending(XAxiVdma *InstancePtr, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + xdbg_printf(XDBG_DEBUG_ERROR, + "IntrGetPending: invalid direction %d\n\r", Direction); + + return 0; + } + + if (Channel->IsValid) { + return XAxiVdma_ChannelGetPendingIntr(Channel); + } + else { + /* An invalid channel has no intr + */ + return 0; + } +} + +/*****************************************************************************/ +/** + * Clear the pending interrupts specified by the bit mask + * + * Interrupts not specified by the mask will not be affected + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param Direction is the DMA channel, use XAXIVDMA_READ or XAXIVDMA_WRITE + * @param IntrType is the bit mask for the interrups to be cleared + * + * @return + * None + * + * @note + * If channel is invalid, then nothing is done + *****************************************************************************/ +void XAxiVdma_IntrClear(XAxiVdma *InstancePtr, u32 IntrType, u16 Direction) +{ + XAxiVdma_Channel *Channel; + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (Channel->IsValid) { + XAxiVdma_ChannelIntrClear(Channel, IntrType); + } + return; +} + +/*****************************************************************************/ +/** + * Masks the S2MM error interrupt for the provided error mask value + * + * @param InstancePtr is the XAxiVdma instance to operate on + * @param ErrorMask is the mask of error bits for which S2MM error + * interrupt can be disabled. + * @param Direction is the channel to work on, use XAXIVDMA_READ/WRITE + * + * @return - XST_SUCCESS, when error bits are cleared. + * - XST_INVALID_PARAM, when channel pointer is invalid. + * - XST_DEVICE_NOT_FOUND, when the channel is not valid. + * + * @note The register S2MM_DMA_IRQ_MASK is only applicable from IPv6.01a + * which is added at offset XAXIVDMA_S2MM_DMA_IRQ_MASK_OFFSET. + * For older versions, this offset location is reserved and so + * the API does not have any effect. + * + *****************************************************************************/ +int XAxiVdma_MaskS2MMErrIntr(XAxiVdma *InstancePtr, u32 ErrorMask, + u16 Direction) +{ + XAxiVdma_Channel *Channel; + + if (Direction != XAXIVDMA_WRITE) { + return XST_INVALID_PARAM; + } + + Channel = XAxiVdma_GetChannel(InstancePtr, Direction); + + if (!Channel) { + return XST_INVALID_PARAM; + } + + if (Channel->IsValid) { + XAxiVdma_WriteReg(Channel->ChanBase, + XAXIVDMA_S2MM_DMA_IRQ_MASK_OFFSET, + ErrorMask & XAXIVDMA_S2MM_IRQ_ERR_ALL_MASK); + + return XST_SUCCESS; + } + + return XST_DEVICE_NOT_FOUND; +} + +/*****************************************************************************/ +/** + * Interrupt handler for the read channel + * + * @param InstancePtr is the pointer to the DMA engine to work on + * + * @return + * None + * + * @note + * If the channel is invalid, then no interrupt handling + *****************************************************************************/ +void XAxiVdma_ReadIntrHandler(void * InstancePtr) +{ + XAxiVdma *DmaPtr; + XAxiVdma_Channel *Channel; + XAxiVdma_ChannelCallBack *CallBack; + u32 PendingIntr; + + DmaPtr = (XAxiVdma *)InstancePtr; + + CallBack = &(DmaPtr->ReadCallBack); + + if (!CallBack->CompletionCallBack) { + + return; + } + + Channel = XAxiVdma_GetChannel(DmaPtr, XAXIVDMA_READ); + + if (!Channel->IsValid) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Read channel is invalid, no intr handling\n\r"); + + return; + } + + PendingIntr = XAxiVdma_ChannelGetPendingIntr(Channel); + PendingIntr &= XAxiVdma_ChannelGetEnabledIntr(Channel); + + XAxiVdma_ChannelIntrClear(Channel, PendingIntr); + + if (!PendingIntr || (PendingIntr & XAXIVDMA_IXR_ERROR_MASK)) { + + CallBack->ErrCallBack(CallBack->ErrRef, + PendingIntr & XAXIVDMA_IXR_ERROR_MASK); + + /* The channel's error callback should reset the channel + * There is no need to handle other interrupts + */ + return; + } + + if (PendingIntr & XAXIVDMA_IXR_COMPLETION_MASK) { + + CallBack->CompletionCallBack(CallBack->CompletionRef, + PendingIntr); + } + + return; +} + +/*****************************************************************************/ +/** + * Interrupt handler for the write channel + * + * @param InstancePtr is the pointer to the DMA engine to work on + * + * @return + * None + * + * @note + * If the channel is invalid, then no interrupt handling + *****************************************************************************/ +void XAxiVdma_WriteIntrHandler(void * InstancePtr) +{ + XAxiVdma *DmaPtr; + XAxiVdma_Channel *Channel; + XAxiVdma_ChannelCallBack *CallBack; + u32 PendingIntr; + + DmaPtr = (XAxiVdma *)InstancePtr; + + Channel = XAxiVdma_GetChannel(DmaPtr, XAXIVDMA_WRITE); + + if (!Channel->IsValid) { + xdbg_printf(XDBG_DEBUG_ERROR, + "Write channel is invalid, no intr handling\n\r"); + + return; + } + + PendingIntr = XAxiVdma_ChannelGetPendingIntr(Channel); + PendingIntr &= XAxiVdma_ChannelGetEnabledIntr(Channel); + + XAxiVdma_ChannelIntrClear(Channel, PendingIntr); + + CallBack = &(DmaPtr->WriteCallBack); + + if (!CallBack->CompletionCallBack) { + + return; + } + + if (!PendingIntr || (PendingIntr & XAXIVDMA_IXR_ERROR_MASK)) { + + CallBack->ErrCallBack(CallBack->ErrRef, + PendingIntr & XAXIVDMA_IXR_ERROR_MASK); + + /* The channel's error callback should reset the channel + * There is no need to handle other interrupts + */ + return; + } + + if (PendingIntr & XAXIVDMA_IXR_COMPLETION_MASK) { + + CallBack->CompletionCallBack(CallBack->CompletionRef, + PendingIntr); + } + + return; +} + +/*****************************************************************************/ +/** + * Set call back function and call back reference pointer for one channel + * + * @param InstancePtr is the pointer to the DMA engine to work on + * @param HandlerType is the interrupt type that this callback handles + * @param CallBackFunc is the call back function pointer + * @param CallBackRef is the call back reference pointer + * @param Direction is the DMA channel, use XAXIVDMA_READ or XAXIVDMA_WRITE + * + * @return + * - XST_SUCCESS if everything is fine + * - XST_INVALID_PARAM if the handler type or direction invalid + * + * @note + * This function overwrites the existing interrupt handler and its reference + * pointer. The function sets the handlers even if the channels are invalid. + *****************************************************************************/ +int XAxiVdma_SetCallBack(XAxiVdma * InstancePtr, u32 HandlerType, + void *CallBackFunc, void *CallBackRef, u16 Direction) +{ + XAxiVdma_ChannelCallBack *CallBack; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XAXIVDMA_DEVICE_READY); + + if ((HandlerType != XAXIVDMA_HANDLER_GENERAL) && + (HandlerType != XAXIVDMA_HANDLER_ERROR)) { + + return XST_INVALID_PARAM; + } + + if (Direction == XAXIVDMA_READ) { + CallBack = &(InstancePtr->ReadCallBack); + } + else { + CallBack = &(InstancePtr->WriteCallBack); + } + + switch (HandlerType) { + case XAXIVDMA_HANDLER_GENERAL: + CallBack->CompletionCallBack = CallBackFunc; + CallBack->CompletionRef = CallBackRef; + break; + + case XAXIVDMA_HANDLER_ERROR: + CallBack->ErrCallBack = CallBackFunc; + CallBack->ErrRef = CallBackRef; + break; + + default: + return XST_INVALID_PARAM; + } + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_porting_guide.h b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_porting_guide.h new file mode 100644 index 00000000..7ec4ef6c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_porting_guide.h @@ -0,0 +1,251 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 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 xaxivdma_porting_guide.h +* +* This is a guide on how to move from using the xvdma driver to use xaxivdma +* driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   08/16/10 First release
+* 2.00a jz   12/10/10 Added support for direct register access mode, v3 core
+* 2.01a jz   01/19/11 Added ability to re-assign BD addresses
+* 	rkv  03/28/11 Added support for frame store register.
+* 3.00a srt  08/26/11 - Added support for Flush on Frame Sync and dynamic
+*		      	programming of Line Buffer Thresholds.
+*		      - XAxiVdma_ChannelErrors API is changed to support for
+*			Flush on Frame Sync feature.
+*		      - Two flags, XST_VDMA_MISMATCH_ERROR & XAXIVDMA_MIS
+*			MATCH_ERROR are added to report error status when
+*			Flush on Frame Sync feature is enabled.
+* 4.00a srt  11/21/11 - XAxiVdma_ChannelSetBufferAddr API is changed to
+*			support 32 Frame Stores.
+*		      - XAxiVdma_ChannelConfig API is changed to support
+*			modified Park Offset Register bits.
+*		      - Added APIs:
+*			XAxiVdma_FsyncSrcSelect()
+*			XAxiVdma_GenLockSourceSelect()
+*		      - Modified structures XAxiVdma_Config and XAxiVdma to
+*		        include new parameters.
+* 4.01a srt  06/13/12 - Added APIs:
+*			XAxiVdma_GetDmaChannelErrors()
+*			XAxiVdma_ClearDmaChannelErrors()
+*			XAxiVdma_ClearChannelErrors()
+*		      - XAxiVdma_ChannelErrors API is changed to remove
+*			Mismatch error logic.
+*		      - Removed Error checking logic in the channel APIs.
+*			Provided User APIs to do this.
+*		      - Added new error bit mask XAXIVDMA_SR_ERR_SOF_LATE_MASK
+*		      - XAXIVDMA_MISMATCH_ERROR flag is deprecated.
+* 		      - Modified the logic of Error handling in interrupt
+*		        handlers.
+* 
+* +* Overview +* +* The API for xaxivdma driver is similar to xvdma driver. However, the prefix +* for functions and structures is now XAxiVdma_. Due to hardware changes, +* for AXI_VDMA core in 12.3, we have changed some API functions, removed some +* API functions and added some new API functions. +* +* From 13.1 release, the hardware, v3.00a core supports direct register access +* mode where transfer is set through direct register writes. Scatter gather is +* no longer there if the direct register access mode is selected. This change +* does not impact the driver API. +* +* For 13.2 release, the driver supports re-assigning BD addresses. This comes +* from the user that it is desirable to change the BD addresses to a memory +* region that SG hardware can access. +* +* For 13.4 release, the hardware, v5.00a core has added new features to select +* Internal GenLock and Frame Sync Sources in the control register. Due to +* hardware changes, we have added new API functions for the two new features. +* +* For 14.2 release, the hardware, v5.02a core has modified the handling of +* VDMA errors. To support this, we have changed some APIs and added some new +* APIs. +* +* API That Only Have Prefix Changes +* +* Note that API includes data structures and functions. For API functions that +* use VDMA data structures or their pointers as arguments, the structures need +* to use the new perfix as well. +* +* The following are the data structures that have prefix changed: +* +* xvdma API structures | xaxivdma API structures +*------------------------------------|------------------------------ +* XVDma | XAxiVdma +* XVDma_Config | XAxiVdma_Config +* XVDma_DmaSetup | XAxiVdma_DmaSetup +* XVDmaFrameCounter | XAxiVdma_FrameCounter +* +* The following is the list of API functions that only have the prefix changes: +* +* xvdma API functions | xaxivdma API functions +*------------------------------------|------------------------------ +* XVDma_CfgInitialize | XAxiVdma_CfgInitialize +* XVDma_StartWriteFrame | XAxiVdma_StartWriteFrame +* XVDma_StartReadFrame | XAxiVdma_StartReadFrame +* XVDma_SetFrameCounter | XAxiVdma_SetFrameCounter +* XVDma_GetFrameCounter | XAxiVdma_GetFrameCounter +* XVDma_LookupConfig | XAxiVdma_LookupConfig +* +* API Functions That Have Been Changed +* +* PLB VDMA only has one channel, while the AXI VDMA has two channels. This +* change has caused some of the API functions to take an extra argument to +* differentiate the channels. The following functions now take an extra +* argument (u16 Direction), the new argument is the last in the argument list: +* +* xvdma API functions | xaxivdma API functions +*------------------------------------|------------------------------ +* XVDma_Reset | XAxiVdma_Reset +* XVDma_IsBusy | XAxiVdma_IsBusy +* XVDma_CurrFrameStore | XAxiVdma_CurrFrameStore +* XVDma_IntrEnable | XAxiVdma_IntrEnable +* XVDma_IntrDisable | XAxiVdma_IntrDisable +* XVDma_IntrGetPending | XAxiVdma_IntrGetPending +* XVDma_IntrClear | XAxiVdma_IntrClear +* XVDma_SetCallBack | XAxiVdma_SetCallBack +* +* Note that the xvdma API functions that already have Direction as the argument +* are kept as they are, which are not necessarily having Direction as the last +* argument. +* +* Some API functions have changed return type from void to int. This is to make +* the driver more intelligent and signal the failure early on to the user. The +* following functions have change return type from void to int: +* +* xvdma API functions | xaxivdma API functions +*------------------------------------|------------------------------ +* void XVDma_DmaConfig | int XAxiVdma_DmaConfig +* void XVDma_DmaSetBufferAddr | int XAxiVdma_DmaSetBufferAddr +* void XVDma_DmaStart | int XAxiVdma_DmaStart +* +* New API Functions +* +* New core v5.02a has added new features, to support them these APIs are added +* +* int XAxiVdma_GetDmaChannelErrors(XAxiVdma *InstancePtr, u16 Direction) +* int XAxiVdma_ClearDmaChannelErrors(XAxiVdma *InstancePtr, u16 Direction, +* u32 ErrorMask) +* void XAxiVdma_ClearChannelErrors(XAxiVdma_Channel *Channel, u32 ErrorMask) +* +* +* New core v5.00a has added new features, to support them these APIs are added +* +* int XAxiVdma_FsyncSrcSelect(XAxiVdma *InstancePtr, u32 Source, +* u16 Direction) +* int XAxiVdma_GenLockSourceSelect(XAxiVdma *InstancePtr, u32 Source, +* u16 Direction) +* +* +* Due to addition of frame store register in hardware these functions are added +* +* int XAxiVdma_SetFrmStore(XAxiVdma *InstancePtr, u8 FrmStoreNum, +* u16 Direction) +* void XAxiVdma_GetFrmStore(XAxiVdma *InstancePtr, u8 *FrmStoreNum, +* u16 Direction) +* +* Due to the fact that AXI VDMA has two channels, and each channel has its own +* interrupt ID, we removed the single interrupt handler API from xvdma driver, +* and added two interrupt handlers: +* +* . void XAxiVdma_ReadIntrHandler(void *Ref) +* . void XAxiVdma_WriteIntrHandler(void *Ref) +* +* Based on customers feedback on xvdma, we added XAxiVdma_Stop to stop one +* channel: +* +* . void XAxiVdma_Stop(XAxiVdma *InstancePtr, u16 Direction) +* +* We need a function to check whether reset is done: +* +* . int XAxiVdma_ResetNotDone(XAxiVdma *InstancePtr, u16 Direction) +* +* While doing the development, it shows the need for getting the hardware +* status to provide as much information as possible for user's development. +* +* . u32 XAxiVdma_GetStatus(XAxiVdma *InstancePtr, u16 Direction) +* +* Because the hardware limitations, parking mode cannot be the initial mode to +* start the DMA engine. Entering and exiting parking mode have to be done +* after the hardware is running. Therefore, we add two API functions to enter +* and exit park mode. +* +* . void XAxiVdma_StartParking(XAxiVdma *InstancePtr, int FrameIndex, +* u16 Direction); +* . void XAxiVdma_StopParking(XAxiVdma *InstancePtr, u16 Direction); +* +* Note that configuring the hardware to be in park mode using +* XAxiVdma_DmaConfig() is fine. The advantage of using _StartParking() and +* _StopParking() is the simplicity. +* +* . void XAxiVdma_StartFrmCntEnable(XAxiVdma *InstancePtr, u16 Direction); +* +* This function is used to enable frame count enable. It is much simpler to +* enable frame count enable this way than using the full configuration +* structure. +* +* . int XAxiVdma_SetBdAddrs(XAxiVdma *InstancePtr, u32 BdAddrPhys, +* u32 BdAddrVirt, int NumBds, u16 Direction); +* +* This function provides the ability for the user application to re-assign +* the BD addresses to whereever in the memory it wants. This is to aid the +* situation that SG engine may have limited access to certain region of the +* memory, comparing to the processor's ability. The default BD addresses are +* inside the region that the processor can access. +* +* API Functions That Have Been Removed +* +* Due to hardware design change, some of the API functions are no longer +* needed: +* +* . XVDma_CmdInerfaceDisable() +* . XVDma_CmdInerfaceEnable() +* . XVDma_FullDuplexDisable() +* . XVDma_FullDuplexEnable() +* . XVDma_HoriCropDisable() +* . XVDma_HoriCropEnable() +* . XVDma_IntrEnableGlobal() +* . XVDma_IntrDisableGlobal() +* . XVDma_IntrHandler() +* +* +******************************************************************************/ diff --git a/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_sinit.c b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_sinit.c new file mode 100644 index 00000000..b596cbd4 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/src/xaxivdma_sinit.c @@ -0,0 +1,83 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 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 xaxivdma_sinit.c +* +* Look up the hardware settings using device ID. The hardware setting is inside +* the configuration table in xaxivdma_g.c, generated automatically by XPS or +* manually by user. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a jz   08/16/10 First release
+* 2.00a jz   12/10/10 Added support for direct register access mode, v3 core
+* 2.01a jz   01/19/11 Added ability to re-assign BD addresses
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xaxivdma.h" +#include "xparameters.h" + +/*****************************************************************************/ +/** + * Look up the hardware configuration for a device instance + * + * @param DeviceId is the unique device ID of the device to lookup for + * + * @return + * The configuration structure for the device. If the device ID is not found, + * a NULL pointer is returned. + * + ******************************************************************************/ +XAxiVdma_Config *XAxiVdma_LookupConfig(u16 DeviceId) +{ + extern XAxiVdma_Config XAxiVdma_ConfigTable[]; + XAxiVdma_Config *CfgPtr = NULL; + int i; + + for (i = 0; i < XPAR_XAXIVDMA_NUM_INSTANCES; i++) { + if (XAxiVdma_ConfigTable[i].DeviceId == DeviceId) { + CfgPtr = &XAxiVdma_ConfigTable[i]; + break; + } + } + + return CfgPtr; +} diff --git a/XilinxProcessorIPLib/drivers/axivdma/src/xdebug.h b/XilinxProcessorIPLib/drivers/axivdma/src/xdebug.h new file mode 100644 index 00000000..9c60cc25 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/axivdma/src/xdebug.h @@ -0,0 +1,93 @@ +/****************************************************************************** +* +* Copyright (C) 2012 - 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. +* +******************************************************************************/ +#ifndef _XDEBUG_H +#define _XDEBUG_H + +#if defined(DEBUG) && !defined(NDEBUG) + +#include + +#ifndef XDEBUG_WARNING +#define XDEBUG_WARNING +#warning DEBUG is enabled +#endif + +#define XDBG_DEBUG_ERROR 0x00000001 /* error condition messages */ +#define XDBG_DEBUG_GENERAL 0x00000002 /* general debug messages */ +#define XDBG_DEBUG_ALL 0xFFFFFFFF /* all debugging data */ + +#define XDBG_DEBUG_FIFO_REG 0x00000100 /* display register reads/writes */ +#define XDBG_DEBUG_FIFO_RX 0x00000101 /* receive debug messages */ +#define XDBG_DEBUG_FIFO_TX 0x00000102 /* transmit debug messages */ +#define XDBG_DEBUG_FIFO_ALL 0x0000010F /* all fifo debug messages */ + +#define XDBG_DEBUG_TEMAC_REG 0x00000400 /* display register reads/writes */ +#define XDBG_DEBUG_TEMAC_RX 0x00000401 /* receive debug messages */ +#define XDBG_DEBUG_TEMAC_TX 0x00000402 /* transmit debug messages */ +#define XDBG_DEBUG_TEMAC_ALL 0x0000040F /* all temac debug messages */ + +#define XDBG_DEBUG_TEMAC_ADPT_RX 0x00000800 /* receive debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_TX 0x00000801 /* transmit debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_IOCTL 0x00000802 /* ioctl debug messages */ +#define XDBG_DEBUG_TEMAC_ADPT_MISC 0x00000803 /* debug msg for other routines */ +#define XDBG_DEBUG_TEMAC_ADPT_ALL 0x0000080F /* all temac adapter debug messages */ + +#define xdbg_current_types (XDBG_DEBUG_ERROR) + +#define xdbg_stmnt(x) x + +/* In VxWorks, if _WRS_GNU_VAR_MACROS is defined, special syntax is needed for + * macros that accept variable number of arguments + */ +#if defined(XENV_VXWORKS) && defined(_WRS_GNU_VAR_MACROS) +#define xdbg_printf(type, args...) (((type) & xdbg_current_types) ? printf (## args) : 0) + +#else /* ANSI Syntax */ + +#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) + +#endif + +#else /* defined(DEBUG) && !defined(NDEBUG) */ + +#define xdbg_stmnt(x) + +/* See VxWorks comments above */ +#if defined(XENV_VXWORKS) && defined(_WRS_GNU_VAR_MACROS) +#define xdbg_printf(type, args...) +#else /* ANSI Syntax */ +#define xdbg_printf(...) +#endif + +#endif /* defined(DEBUG) && !defined(NDEBUG) */ + +#endif /* _XDEBUG_H */