1 /******************************************************************************
3 * Copyright (C) 2009 - 2016 Xilinx, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
31 ******************************************************************************/
32 /****************************************************************************/
36 * @addtogroup dmaps_v2_3
39 * This file contains the implementation of the interface functions for XDmaPs
40 * driver. Refer to the header file xdmaps.h for more detailed information.
43 * MODIFICATION HISTORY:
45 * Ver Who Date Changes
46 * ----- ------ -------- ----------------------------------------------
47 * 1.00 hbm 08/19/2010 First Release
48 * 1.00 nm 05/25/2011 Updated for minor doxygen corrections
49 * 1.02a sg 05/16/2012 Made changes for doxygen and moved some function
50 * header from the xdmaps.h file to xdmaps.c file
51 * Other cleanup for coding guidelines and CR 657109
53 * 1.03a sg 07/16/2012 changed inline to __inline for CR665681
54 * 1.04a nm 10/22/2012 Fixed CR# 681671.
55 * 1.05a nm 04/15/2013 Fixed CR# 704396. Removed warnings when compiled
56 * with -Wall and -Wextra option in bsp.
57 * 05/01/2013 Fixed CR# 700189. Changed XDmaPs_BuildDmaProg()
58 * function description.
59 * Fixed CR# 704396. Removed unused variables
60 * UseM2MByte & MemBurstLen from XDmaPs_BuildDmaProg()
62 * 1.07a asa 11/02/13. Made changes to fix compilation issues for iarcc.
63 * Removed the PDBG prints. By default they were always
64 * defined out and never used. The PDBG is non-standard for
65 * Xilinx drivers and no other driver does something similar.
66 * Since there is no easy way to fix compilation issues with
67 * the IARCC compiler around PDBG, it is better to remove it.
68 * Users can always use xil_printfs if they want to debug.
69 * 2.01 kpc 08/23/14 Fixed the IAR compiler reported errors
70 * 2.2 mus 12/08/16 Remove definition of INLINE macro to avoid re-definition,
71 * since it is being defined in xil_io.h
72 * 2.3 kpc 14/10/16 Fixed the compiler error when optimization O0 is used.
75 *****************************************************************************/
77 /***************************** Include Files ********************************/
84 #include "xil_cache.h"
86 #include "xil_printf.h"
89 /************************** Constant Definitions ****************************/
91 /* The following constant defines the amount of error that is allowed for
92 * a specified baud rate. This error is the difference between the actual
93 * baud rate that will be generated using the specified clock and the
97 /**************************** Type Definitions ******************************/
99 /***************** Macros (Inline Functions) Definitions ********************/
102 /************************** Function Prototypes *****************************/
103 static int XDmaPs_Exec_DMAKILL(u32 BaseAddr,
104 unsigned int Channel,
105 unsigned int Thread);
107 static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf);
109 static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg);
111 static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel);
112 static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool);
113 static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd,
114 unsigned CacheLength);
116 static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length);
120 /************************** Variable Definitions ****************************/
122 /****************************************************************************/
125 * Initializes a specific XDmaPs instance such that it is ready to be used.
126 * The data format of the device is setup for 8 data bits, 1 stop bit, and no
127 * parity by default. The baud rate is set to a default value specified by
128 * Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The
129 * receive FIFO threshold is set for 8 bytes. The default operating mode of the
130 * driver is polled mode.
132 * @param InstPtr is a pointer to the XDmaPs instance.
133 * @param Config is a reference to a structure containing information
134 * about a specific XDmaPs driver.
135 * @param EffectiveAddr is the device base address in the virtual memory
136 * address space. The caller is responsible for keeping the
137 * address mapping from EffectiveAddr to the device physical base
138 * address unchanged once this function is invoked. Unexpected
139 * errors may occur if the address mapping changes after this
140 * function is called. If address translation is not used, pass in
141 * the physical address instead.
145 * - XST_SUCCESS on initialization completion
149 *****************************************************************************/
150 int XDmaPs_CfgInitialize(XDmaPs *InstPtr,
151 XDmaPs_Config *Config,
154 int Status = XST_SUCCESS;
155 unsigned int CacheLength = 0;
158 XDmaPs_ChannelData *ChanData;
161 * Assert validates the input arguments
163 Xil_AssertNonvoid(InstPtr != NULL);
164 Xil_AssertNonvoid(Config != NULL);
167 * Setup the driver instance using passed in parameters
169 InstPtr->Config.DeviceId = Config->DeviceId;
170 InstPtr->Config.BaseAddress = EffectiveAddr;
172 CfgReg = XDmaPs_ReadReg(EffectiveAddr, XDMAPS_CR1_OFFSET);
173 CacheLength = CfgReg & XDMAPS_CR1_I_CACHE_LEN_MASK;
174 if (CacheLength < 2 || CacheLength > 5)
177 CacheLength = 1 << CacheLength;
179 InstPtr->CacheLength = CacheLength;
181 memset(InstPtr->Chans, 0,
182 sizeof(XDmaPs_ChannelData[XDMAPS_CHANNELS_PER_DEV]));
184 for (Channel = 0; Channel < XDMAPS_CHANNELS_PER_DEV; Channel++) {
185 ChanData = InstPtr->Chans + Channel;
186 ChanData->ChanId = Channel;
187 ChanData->DevId = Config->DeviceId;
190 InstPtr->IsReady = 1;
195 /****************************************************************************/
198 * Reset the DMA Manager.
200 * @param InstPtr is the DMA instance.
202 * @return 0 on success, -1 on time out
206 *****************************************************************************/
207 int XDmaPs_ResetManager(XDmaPs *InstPtr)
210 Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress,
216 /****************************************************************************/
219 * Reset the specified DMA Channel.
221 * @param InstPtr is the DMA instance.
222 * @param Channel is the channel to be reset.
224 * @return 0 on success, -1 on time out
228 *****************************************************************************/
229 int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel)
232 Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress,
239 /*****************************************************************************/
242 * Driver fault interrupt service routine
243 * This is the one that connects the GIC
245 * @param InstPtr is the DMA instance.
251 ******************************************************************************/
252 void XDmaPs_FaultISR(XDmaPs *InstPtr)
256 u32 Fsm; /* Fault status DMA manager register value */
257 u32 Fsc; /* Fault status DMA channel register value */
258 u32 FaultType; /* Fault type DMA manager register value */
260 u32 BaseAddr = InstPtr->Config.BaseAddress;
262 u32 Pc; /* DMA Pc or channel Pc */
263 XDmaPs_ChannelData *ChanData;
270 Fsm = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSM_OFFSET) & 0x01;
271 Fsc = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSC_OFFSET) & 0xFF;
274 DevId = InstPtr->Config.DeviceId;
278 * if DMA manager is fault
280 FaultType = XDmaPs_ReadReg(BaseAddr, XDMAPS_FTM_OFFSET);
281 Pc = XDmaPs_ReadReg(BaseAddr, XDMAPS_DPC_OFFSET);
283 xil_printf("PL330 device %d fault with type: %x at Pc %x\n",
287 /* kill the DMA manager thread */
288 /* Should we disable interrupt?*/
289 XDmaPs_Exec_DMAKILL(BaseAddr, 0, 0);
293 * check which channel faults and kill the channel thread
296 Chan < XDMAPS_CHANNELS_PER_DEV;
298 if (Fsc & (0x01 << Chan)) {
300 XDmaPs_ReadReg(BaseAddr,
301 XDmaPs_FTCn_OFFSET(Chan));
302 Pc = XDmaPs_ReadReg(BaseAddr,
303 XDmaPs_CPCn_OFFSET(Chan));
305 /* kill the channel thread */
306 /* Should we disable interrupt? */
307 XDmaPs_Exec_DMAKILL(BaseAddr, Chan, 1);
310 * get the fault type and fault Pc and invoke the
313 ChanData = InstPtr->Chans + Chan;
315 DmaCmd = ChanData->DmaCmdToHw;
317 /* Should we check DmaCmd is not null */
318 DmaCmd->DmaStatus = -1;
319 DmaCmd->ChanFaultType = FaultType;
320 DmaCmd->ChanFaultPCAddr = Pc;
321 ChanData->DmaCmdFromHw = DmaCmd;
322 ChanData->DmaCmdToHw = NULL;
324 if (!ChanData->HoldDmaProg) {
325 DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg;
327 XDmaPs_BufPool_Free(ChanData->ProgBufPool,
329 DmaCmd->GeneratedDmaProg = NULL;
332 if (InstPtr->FaultHandler)
333 InstPtr->FaultHandler(Chan,
342 /*****************************************************************************/
345 * Set the done handler for a channel.
347 * @param InstPtr is the DMA instance.
348 * @param Channel is the channel number.
349 * @param DoneHandler is the done interrupt handler.
350 * @param CallbackRef is the callback reference data.
356 ******************************************************************************/
357 int XDmaPs_SetDoneHandler(XDmaPs *InstPtr,
359 XDmaPsDoneHandler DoneHandler,
362 XDmaPs_ChannelData *ChanData;
364 Xil_AssertNonvoid(InstPtr != NULL);
366 if (Channel >= XDMAPS_CHANNELS_PER_DEV)
370 ChanData = InstPtr->Chans + Channel;
372 ChanData->DoneHandler = DoneHandler;
373 ChanData->DoneRef = CallbackRef;
378 /*****************************************************************************/
381 * Set the fault handler for a channel.
383 * @param InstPtr is the DMA instance.
384 * @param FaultHandler is the fault interrupt handler.
385 * @param CallbackRef is the callback reference data.
391 ******************************************************************************/
392 int XDmaPs_SetFaultHandler(XDmaPs *InstPtr,
393 XDmaPsFaultHandler FaultHandler,
396 Xil_AssertNonvoid(InstPtr != NULL);
398 InstPtr->FaultHandler = FaultHandler;
399 InstPtr->FaultRef = CallbackRef;
406 /****************************************************************************/
408 * Construction function for DMAEND instruction. This function fills the program
409 * buffer with the constructed instruction.
411 * @param DmaProg the DMA program buffer, it's the starting address for
412 * the instruction being constructed
414 * @return The number of bytes for this instruction which is 1.
418 *****************************************************************************/
419 static INLINE int XDmaPs_Instr_DMAEND(char *DmaProg)
431 static INLINE void XDmaPs_Memcpy4(char *Dst, char *Src)
434 *(Dst + 1) = *(Src + 1);
435 *(Dst + 2) = *(Src + 2);
436 *(Dst + 3) = *(Src + 3);
439 /****************************************************************************/
442 * Construction function for DMAGO instruction. This function fills the program
443 * buffer with the constructed instruction.
445 * @param DmaProg is the DMA program buffer, it's the starting address
446 * for the instruction being constructed
447 * @param Cn is the Channel number, 0 - 7
448 * @param Imm is 32-bit immediate number written to the Channel Program
450 * @param Ns is Non-secure flag. If Ns is 1, the DMA channel operates in
451 * the Non-secure state. If Ns is 0, the execution depends on the
452 * security state of the DMA manager:
453 * DMA manager is in the Secure state, DMA channel operates in the
455 * DMA manager is in the Non-secure state, DMAC aborts.
457 * @return The number of bytes for this instruction which is 6.
461 *****************************************************************************/
462 static INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn,
463 u32 Imm, unsigned int Ns)
467 * 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
468 * 0 0 0 0 0 |cn[2:0]| 1 0 1 0 0 0 ns 0
473 *DmaProg = 0xA0 | ((Ns << 1) & 0x02);
475 *(DmaProg + 1) = (u8)(Cn & 0x07);
477 // *((u32 *)(DmaProg + 2)) = Imm;
478 XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm);
484 /****************************************************************************/
487 * Construction function for DMALD instruction. This function fills the program
488 * buffer with the constructed instruction.
490 * @param DmaProg the DMA program buffer, it's the starting address for the
491 * instruction being constructed
493 * @return The number of bytes for this instruction which is 1.
497 *****************************************************************************/
498 static INLINE int XDmaPs_Instr_DMALD(char *DmaProg)
505 * Note: this driver doesn't support conditional load or store,
506 * so the bs bit is 0 and x bit is 0.
512 /****************************************************************************/
515 * Construction function for DMALP instruction. This function fills the program
516 * buffer with the constructed instruction.
518 * @param DmaProg is the DMA program buffer, it's the starting address
519 * for the instruction being constructed
520 * @param Lc is the Loop counter register, can either be 0 or 1.
521 * @param LoopIterations: the number of interations, LoopInterations - 1
522 * will be encoded in the DMALP instruction.
524 * @return The number of bytes for this instruction which is 2.
528 *****************************************************************************/
529 static INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc,
530 unsigned LoopIterations)
534 * 15 ... 8 7 6 5 4 3 2 1 0
535 * | iter[7:0] |0 0 1 0 0 0 lc 0
537 *DmaProg = (u8)(0x20 | ((Lc & 1) << 1));
538 *(DmaProg + 1) = (u8)(LoopIterations - 1);
542 /****************************************************************************/
545 * Construction function for DMALPEND instruction. This function fills the
546 * program buffer with the constructed instruction.
548 * @param DmaProg is the DMA program buffer, it's the starting address
549 * for the instruction being constructed
550 * @param BodyStart is the starting address of the loop body. It is used
551 * to calculate the bytes of backward jump.
552 * @param Lc is the Loop counter register, can either be 0 or 1.
554 * @return The number of bytes for this instruction which is 2.
558 *****************************************************************************/
559 static INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc)
563 * 15 ... 8 7 6 5 4 3 2 1 0
564 * | backward_jump[7:0] |0 0 1 nf 1 lc bs x
567 * nf is for loop forever. The driver does not support loop forever,
569 * The driver does not support conditional LPEND, so bs is 0, x is 0.
571 *DmaProg = 0x38 | ((Lc & 1) << 2);
572 *(DmaProg + 1) = (u8)(DmaProg - BodyStart);
578 * Register number for the DMAMOV instruction
580 #define XDMAPS_MOV_SAR 0x0
581 #define XDMAPS_MOV_CCR 0x1
582 #define XDMAPS_MOV_DAR 0x2
584 /****************************************************************************/
587 * Construction function for DMAMOV instruction. This function fills the
588 * program buffer with the constructed instruction.
590 * @param DmaProg is the DMA program buffer, it's the starting address
591 * for the instruction being constructed
592 * @param Rd is the register id, 0 for SAR, 1 for CCR, and 2 for DAR
593 * @param Imm is the 32-bit immediate number
595 * @return The number of bytes for this instruction which is 6.
599 *****************************************************************************/
600 static INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm)
604 * 15 4 3 2 1 10 ... 8 7 6 5 4 3 2 1 0
605 * 0 0 0 0 0 |rd[2:0]|1 0 1 1 1 1 0 0
610 * rd: b000 for SAR, b001 CCR, b010 DAR
613 *(DmaProg + 1) = Rd & 0x7;
614 // *((u32 *)(DmaProg + 2)) = Imm;
615 XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm);
620 /****************************************************************************/
623 * Construction function for DMANOP instruction. This function fills the
624 * program buffer with the constructed instruction.
626 * @param DmaProg is the DMA program buffer, it's the starting address
627 * for the instruction being constructed
628 * @return The number of bytes for this instruction which is 1.
632 *****************************************************************************/
633 static INLINE int XDmaPs_Instr_DMANOP(char *DmaProg)
644 /****************************************************************************/
647 * Construction function for DMARMB instruction. This function fills the
648 * program buffer with the constructed instruction.
650 * @param DmaProg is the DMA program buffer, it's the starting address
651 * for the instruction being constructed
653 * @return The number of bytes for this instruction which is 1.
657 *****************************************************************************/
658 static INLINE int XDmaPs_Instr_DMARMB(char *DmaProg)
669 /****************************************************************************/
672 * Construction function for DMASEV instruction. This function fills the
673 * program buffer with the constructed instruction.
675 * @param DmaProg is the DMA program buffer, it's the starting address
676 * for the instruction being constructed
677 * @param EventNumber is the Event number to signal.
679 * @return The number of bytes for this instruction which is 2.
683 *****************************************************************************/
684 static INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber)
688 * 15 4 3 2 1 10 9 8 7 6 5 4 3 2 1 0
689 * |event[4:0]| 0 0 0 0 0 1 1 0 1 0 0
692 *(DmaProg + 1) = (u8)(EventNumber << 3);
698 /****************************************************************************/
701 * Construction function for DMAST instruction. This function fills the
702 * program buffer with the constructed instruction.
704 * @param DmaProg is the DMA program buffer, it's the starting address
705 * for the instruction being constructed
707 * @return The number of bytes for this instruction which is 1.
711 *****************************************************************************/
712 static INLINE int XDmaPs_Instr_DMAST(char *DmaProg)
719 * Note: this driver doesn't support conditional load or store,
720 * so the bs bit is 0 and x bit is 0.
727 /****************************************************************************/
730 * Construction function for DMAWMB instruction. This function fills the
731 * program buffer with the constructed instruction.
733 * @param DmaProg is the DMA program buffer, it's the starting address
734 * for the instruction being constructed
736 * @return The number of bytes for this instruction which is 1.
740 *****************************************************************************/
741 static INLINE int XDmaPs_Instr_DMAWMB(char *DmaProg)
752 /****************************************************************************/
755 * Conversion function from the endian swap size to the bit encoding of the CCR
757 * @param EndianSwapSize is the endian swap size, in terms of bits, it
758 * could be 8, 16, 32, 64, or 128(We are using DMA assembly syntax)
760 * @return The endian swap size bit encoding for the CCR.
764 *****************************************************************************/
765 static INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize)
767 switch (EndianSwapSize) {
785 /****************************************************************************/
788 * Conversion function from the burst size to the bit encoding of the CCR
790 * @param BurstSize is the burst size. It's the data width.
791 * In terms of bytes, it could be 1, 2, 4, 8, 16, 32, 64, or 128.
792 * It must be no larger than the bus width.
793 * (We are using DMA assembly syntax.)
797 *****************************************************************************/
798 static INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize)
823 /****************************************************************************/
826 * Conversion function from PL330 bus transfer descriptors to CCR value. All the
827 * values passed to the functions are in terms of assembly languages, not in
828 * terms of the register bit encoding.
830 * @param ChanCtrl is the Instance of XDmaPs_ChanCtrl.
832 * @return The 32-bit CCR value.
836 *****************************************************************************/
837 u32 XDmaPs_ToCCRValue(XDmaPs_ChanCtrl *ChanCtrl)
840 * Channel Control Register encoding
841 * [31:28] - endian_swap_size
842 * [27:25] - dst_cache_ctrl
843 * [24:22] - dst_prot_ctrl
844 * [21:18] - dst_burst_len
845 * [17:15] - dst_burst_size
847 * [13:11] - src_cache_ctrl
848 * [10:8] - src_prot_ctrl
849 * [7:4] - src_burst_len
850 * [3:1] - src_burst_size
855 XDmaPs_ToEndianSwapSizeBits(ChanCtrl->EndianSwapSize);
857 unsigned dst_burst_size =
858 XDmaPs_ToBurstSizeBits(ChanCtrl->DstBurstSize);
859 unsigned dst_burst_len = (ChanCtrl->DstBurstLen - 1) & 0x0F;
860 unsigned dst_cache_ctrl = (ChanCtrl->DstCacheCtrl & 0x03)
861 | ((ChanCtrl->DstCacheCtrl & 0x08) >> 1);
862 unsigned dst_prot_ctrl = ChanCtrl->DstProtCtrl & 0x07;
863 unsigned dst_inc_bit = ChanCtrl->DstInc & 1;
865 unsigned src_burst_size =
866 XDmaPs_ToBurstSizeBits(ChanCtrl->SrcBurstSize);
867 unsigned src_burst_len = (ChanCtrl->SrcBurstLen - 1) & 0x0F;
868 unsigned src_cache_ctrl = (ChanCtrl->SrcCacheCtrl & 0x03)
869 | ((ChanCtrl->SrcCacheCtrl & 0x08) >> 1);
870 unsigned src_prot_ctrl = ChanCtrl->SrcProtCtrl & 0x07;
871 unsigned src_inc_bit = ChanCtrl->SrcInc & 1;
873 u32 ccr_value = (es << 28)
874 | (dst_cache_ctrl << 25)
875 | (dst_prot_ctrl << 22)
876 | (dst_burst_len << 18)
877 | (dst_burst_size << 15)
878 | (dst_inc_bit << 14)
879 | (src_cache_ctrl << 11)
880 | (src_prot_ctrl << 8)
881 | (src_burst_len << 4)
882 | (src_burst_size << 1)
888 /****************************************************************************/
890 * Construct a loop with only DMALD and DMAST as the body using loop counter 0.
891 * The function also makes sure the loop body and the lpend is in the same
894 * @param DmaProgStart is the very start address of the DMA program.
895 * This is used to calculate whether the loop is in a cache line.
896 * @param CacheLength is the icache line length, in terms of bytes.
897 * If it's zero, the performance enhancement feature will be
899 * @param DmaProgLoopStart The starting address of the loop (DMALP).
900 * @param LoopCount The inner loop count. Loop count - 1 will be used to
901 * initialize the loop counter.
903 * @return The number of bytes the loop has.
907 *****************************************************************************/
908 int XDmaPs_ConstructSingleLoop(char *DmaProgStart,
910 char *DmaProgLoopStart,
913 int CacheStartOffset;
916 char *DmaProgBuf = DmaProgLoopStart;
918 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCount);
920 if (CacheLength > 0) {
922 * the CacheLength > 0 switch is ued to turn on/off nop
925 CacheStartOffset = DmaProgBuf - DmaProgStart;
926 CacheEndOffset = CacheStartOffset + 3;
929 * check whether the body and lpend fit in one cache line
931 if (CacheStartOffset / CacheLength
932 != CacheEndOffset / CacheLength) {
933 /* insert the nops */
934 NumNops = CacheLength
935 - CacheStartOffset % CacheLength;
938 XDmaPs_Instr_DMANOP(DmaProgBuf);
943 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
944 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
945 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
948 return DmaProgBuf - DmaProgLoopStart;
951 /****************************************************************************/
953 * Construct a nested loop with only DMALD and DMAST in the inner loop body.
954 * It uses loop counter 1 for the outer loop and loop counter 0 for the
957 * @param DmaProgStart is the very start address of the DMA program.
958 * This is used to calculate whether the loop is in a cache line.
959 * @param CacheLength is the icache line length, in terms of bytes.
960 * If it's zero, the performance enhancement feature will be
962 * @param DmaProgLoopStart The starting address of the loop (DMALP).
963 * @param LoopCountOuter The outer loop count. Loop count - 1 will be
964 * used to initialize the loop counter.
965 * @param LoopCountInner The inner loop count. Loop count - 1 will be
966 * used to initialize the loop counter.
968 * @return The number byes the nested loop program has.
972 *****************************************************************************/
973 int XDmaPs_ConstructNestedLoop(char *DmaProgStart,
975 char *DmaProgLoopStart,
976 unsigned int LoopCountOuter,
977 unsigned int LoopCountInner)
979 int CacheStartOffset;
982 char *InnerLoopStart;
983 char *DmaProgBuf = DmaProgLoopStart;
985 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 1, LoopCountOuter);
986 InnerLoopStart = DmaProgBuf;
988 if (CacheLength > 0) {
990 * the CacheLength > 0 switch is ued to turn on/off nop
993 if (CacheLength < 8) {
995 * if the cache line is too small to fit both loops
996 * just align the inner loop
999 XDmaPs_ConstructSingleLoop(DmaProgStart,
1003 /* outer loop end */
1005 XDmaPs_Instr_DMALPEND(DmaProgBuf,
1010 * the nested loop is constructed for
1011 * smaller cache line
1013 return DmaProgBuf - DmaProgLoopStart;
1017 * Now let's handle the case where a cache line can
1018 * fit the nested loops.
1020 CacheStartOffset = DmaProgBuf - DmaProgStart;
1021 CacheEndOffset = CacheStartOffset + 7;
1024 * check whether the body and lpend fit in one cache line
1026 if (CacheStartOffset / CacheLength
1027 != CacheEndOffset / CacheLength) {
1028 /* insert the nops */
1029 NumNops = CacheLength
1030 - CacheStartOffset % CacheLength;
1033 XDmaPs_Instr_DMANOP(DmaProgBuf);
1038 /* insert the inner DMALP */
1039 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCountInner);
1041 /* DMALD and DMAST instructions */
1042 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
1043 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
1045 /* inner DMALPEND */
1046 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
1048 /* outer DMALPEND */
1049 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
1052 /* return the number of bytes */
1053 return DmaProgBuf - DmaProgLoopStart;
1057 * [31:28] endian_swap_size b0000
1058 * [27:25] dst_cache_ctrl b000
1059 * [24:22] dst_prot_ctrl b000
1060 * [21:18] dst_burst_len b0000
1061 * [17:15] dst_burst_size b000
1063 * [27:25] src_cache_ctrl b000
1064 * [24:22] src_prot_ctrl b000
1065 * [21:18] src_burst_len b0000
1066 * [17:15] src_burst_size b000
1069 #define XDMAPS_CCR_SINGLE_BYTE (0x0)
1070 #define XDMAPS_CCR_M2M_SINGLE_BYTE ((0x1 << 14) | 0x1)
1073 /****************************************************************************/
1076 * Construct the DMA program based on the descriptions of the DMA transfer.
1077 * The function handles memory to memory DMA transfers.
1078 * It also handles unalgined head and small amount of residue tail.
1080 * @param Channel DMA channel number
1081 * @param Cmd is the DMA command.
1082 * @param CacheLength is the icache line length, in terms of bytes.
1083 * If it's zero, the performance enhancement feature will be
1086 * @returns The number of bytes for the program.
1090 *****************************************************************************/
1091 static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd,
1092 unsigned CacheLength)
1097 char *DmaProgBuf = (char *)Cmd->GeneratedDmaProg;
1098 unsigned DevChan = Channel;
1099 unsigned long DmaLength = Cmd->BD.Length;
1100 u32 SrcAddr = Cmd->BD.SrcAddr;
1102 unsigned SrcInc = Cmd->ChanCtrl.SrcInc;
1103 u32 DstAddr = Cmd->BD.DstAddr;
1104 unsigned DstInc = Cmd->ChanCtrl.DstInc;
1106 char *DmaProgStart = DmaProgBuf;
1108 unsigned int BurstBytes;
1109 unsigned int LoopCount;
1110 unsigned int LoopCount1 = 0;
1111 unsigned int LoopResidue = 0;
1112 unsigned int TailBytes;
1113 unsigned int TailWords;
1116 unsigned int Unaligned;
1117 unsigned int UnalignedCount;
1118 unsigned int MemBurstSize = 1;
1121 unsigned int SrcUnaligned = 0;
1122 unsigned int DstUnaligned = 0;
1124 XDmaPs_ChanCtrl *ChanCtrl;
1125 XDmaPs_ChanCtrl WordChanCtrl;
1126 static XDmaPs_ChanCtrl Mem2MemByteCC;
1128 Mem2MemByteCC.EndianSwapSize = 0;
1129 Mem2MemByteCC.DstCacheCtrl = 0;
1130 Mem2MemByteCC.DstProtCtrl = 0;
1131 Mem2MemByteCC.DstBurstLen = 1;
1132 Mem2MemByteCC.DstBurstSize = 1;
1133 Mem2MemByteCC.DstInc = 1;
1134 Mem2MemByteCC.SrcCacheCtrl = 0;
1135 Mem2MemByteCC.SrcProtCtrl = 0;
1136 Mem2MemByteCC.SrcBurstLen = 1;
1137 Mem2MemByteCC.SrcBurstSize = 1;
1138 Mem2MemByteCC.SrcInc = 1;
1140 ChanCtrl = &Cmd->ChanCtrl;
1142 /* insert DMAMOV for SAR and DAR */
1143 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1146 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1151 if (ChanCtrl->SrcInc)
1152 SrcUnaligned = SrcAddr % ChanCtrl->SrcBurstSize;
1154 if (ChanCtrl->DstInc)
1155 DstUnaligned = DstAddr % ChanCtrl->DstBurstSize;
1157 if ((SrcUnaligned && DstInc) || (DstUnaligned && SrcInc)) {
1158 ChanCtrl = &Mem2MemByteCC;
1161 if (ChanCtrl->SrcInc) {
1162 MemBurstSize = ChanCtrl->SrcBurstSize;
1165 } else if (ChanCtrl->DstInc) {
1166 MemBurstSize = ChanCtrl->DstBurstSize;
1170 /* check whether the head is aligned or not */
1171 Unaligned = MemAddr % MemBurstSize;
1174 /* if head is unaligned, transfer head in bytes */
1175 UnalignedCount = MemBurstSize - Unaligned;
1176 CCRValue = XDMAPS_CCR_SINGLE_BYTE
1178 | ((DstInc & 1) << 14);
1180 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1184 for (Index = 0; Index < UnalignedCount; Index++) {
1185 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
1186 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
1189 DmaLength -= UnalignedCount;
1192 /* now the burst transfer part */
1193 CCRValue = XDmaPs_ToCCRValue(ChanCtrl);
1194 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1198 BurstBytes = ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen;
1200 LoopCount = DmaLength / BurstBytes;
1201 TailBytes = DmaLength % BurstBytes;
1204 * the loop count register is 8-bit wide, so if we need
1205 * a larger loop, we need to have nested loops
1207 if (LoopCount > 256) {
1208 LoopCount1 = LoopCount / 256;
1209 if (LoopCount1 > 256) {
1210 xil_printf("DMA operation cannot fit in a 2-level "
1211 "loop for channel %d, please reduce the "
1212 "DMA length or increase the burst size or "
1217 LoopResidue = LoopCount % 256;
1221 XDmaPs_ConstructNestedLoop(DmaProgStart,
1228 XDmaPs_ConstructSingleLoop(DmaProgStart,
1233 /* there will be some that cannot be covered by
1236 LoopCount = LoopResidue;
1239 if (LoopCount > 0) {
1240 DmaProgBuf += XDmaPs_ConstructSingleLoop(DmaProgStart,
1247 /* handle the tail */
1248 TailWords = TailBytes / MemBurstSize;
1249 TailBytes = TailBytes % MemBurstSize;
1252 WordChanCtrl = *ChanCtrl;
1254 * if we can transfer the tail in words, we will
1255 * transfer words as much as possible
1257 WordChanCtrl.SrcBurstSize = MemBurstSize;
1258 WordChanCtrl.SrcBurstLen = 1;
1259 WordChanCtrl.DstBurstSize = MemBurstSize;
1260 WordChanCtrl.DstBurstLen = 1;
1264 * the burst length is 1
1266 CCRValue = XDmaPs_ToCCRValue(&WordChanCtrl);
1269 XDmaPs_Instr_DMAMOV(DmaProgBuf,
1273 XDmaPs_ConstructSingleLoop(DmaProgStart,
1282 * for the rest, we'll tranfer in bytes
1285 * So far just to be safe, the tail bytes
1286 * are transfered in a loop. We can optimize a little
1287 * to perform a burst.
1289 CCRValue = XDMAPS_CCR_SINGLE_BYTE
1291 | ((DstInc & 1) << 14);
1294 XDmaPs_Instr_DMAMOV(DmaProgBuf,
1299 XDmaPs_ConstructSingleLoop(DmaProgStart,
1307 DmaProgBuf += XDmaPs_Instr_DMASEV(DmaProgBuf, DevChan);
1308 DmaProgBuf += XDmaPs_Instr_DMAEND(DmaProgBuf);
1310 DmaProgBytes = DmaProgBuf - DmaProgStart;
1312 Xil_DCacheFlushRange((u32)DmaProgStart, DmaProgBytes);
1314 return DmaProgBytes;
1319 /****************************************************************************/
1322 * Generate a DMA program based for the DMA command, the buffer will be pointed
1323 * by the GeneratedDmaProg field of the command.
1325 * @param InstPtr is then DMA instance.
1326 * @param Channel is the DMA channel number.
1327 * @param Cmd is the DMA command.
1329 * @return - XST_SUCCESS on success.
1330 * - XST_FAILURE if it fails
1334 *****************************************************************************/
1335 int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd)
1339 XDmaPs_ChannelData *ChanData;
1340 XDmaPs_ChanCtrl *ChanCtrl;
1342 Xil_AssertNonvoid(InstPtr != NULL);
1343 Xil_AssertNonvoid(Cmd != NULL);
1346 if (Channel > XDMAPS_CHANNELS_PER_DEV)
1349 ChanData = InstPtr->Chans + Channel;
1350 ChanCtrl = &Cmd->ChanCtrl;
1352 if (ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen
1353 != ChanCtrl->DstBurstSize * ChanCtrl->DstBurstLen) {
1359 * unaligned fixed address is not supported
1361 if (!ChanCtrl->SrcInc && Cmd->BD.SrcAddr % ChanCtrl->SrcBurstSize) {
1365 if (!ChanCtrl->DstInc && Cmd->BD.DstAddr % ChanCtrl->DstBurstSize) {
1369 Buf = XDmaPs_BufPool_Allocate(ChanData->ProgBufPool);
1374 Cmd->GeneratedDmaProg = Buf;
1375 ProgLen = XDmaPs_BuildDmaProg(Channel, Cmd,
1376 InstPtr->CacheLength);
1377 Cmd->GeneratedDmaProgLength = ProgLen;
1381 XDmaPs_Print_DmaProg(Cmd);
1385 /* something wrong, release the buffer */
1386 XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf);
1387 Cmd->GeneratedDmaProgLength = 0;
1388 Cmd->GeneratedDmaProg = NULL;
1396 /****************************************************************************/
1398 * Free the DMA program buffer that is pointed by the GeneratedDmaProg field
1401 * @param InstPtr is then DMA instance.
1402 * @param Channel is the DMA channel number.
1403 * @param Cmd is the DMA command.
1405 * @return XST_SUCCESS on success.
1406 * XST_FAILURE if there is any error.
1410 ****************************************************************************/
1411 int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd)
1415 XDmaPs_ChannelData *ChanData;
1417 Xil_AssertNonvoid(InstPtr != NULL);
1418 Xil_AssertNonvoid(Cmd != NULL);
1420 if (Channel > XDMAPS_CHANNELS_PER_DEV)
1423 Buf = (void *)Cmd->GeneratedDmaProg;
1424 ChanData = InstPtr->Chans + Channel;
1427 XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf);
1428 Cmd->GeneratedDmaProg = 0;
1429 Cmd->GeneratedDmaProgLength = 0;
1436 /****************************************************************************/
1439 * Start a DMA command. The command can only be invoked when the channel
1440 * is idle. The driver takes the command, generates DMA program if needed,
1441 * then pass the program to DMAC to execute.
1443 * @param InstPtr is then DMA instance.
1444 * @param Channel is the DMA channel number.
1445 * @param Cmd is the DMA command.
1446 * @param HoldDmaProg is tag indicating whether the driver can release
1447 * the allocated DMA buffer or not. If a user wants to examine the
1448 * generated DMA program, the flag should be set to 1. After the
1449 * DMA program is finished, a user needs to explicity free the
1453 * - XST_SUCCESS on success
1454 * - XST_DEVICE_BUSY if DMA is busy
1455 * - XST_FAILURE on other failures
1459 ****************************************************************************/
1460 int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel,
1468 Xil_AssertNonvoid(InstPtr != NULL);
1469 Xil_AssertNonvoid(Cmd != NULL);
1472 Cmd->DmaStatus = XST_FAILURE;
1474 if (XDmaPs_IsActive(InstPtr, Channel))
1475 return XST_DEVICE_BUSY;
1477 if (!Cmd->UserDmaProg && !Cmd->GeneratedDmaProg) {
1478 Status = XDmaPs_GenDmaProg(InstPtr, Channel, Cmd);
1483 InstPtr->Chans[Channel].HoldDmaProg = HoldDmaProg;
1485 if (Cmd->UserDmaProg)
1486 DmaProg = (u32)Cmd->UserDmaProg;
1487 else if (Cmd->GeneratedDmaProg)
1488 DmaProg = (u32)Cmd->GeneratedDmaProg;
1491 /* enable the interrupt */
1492 Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1493 XDMAPS_INTEN_OFFSET);
1494 Inten |= 0x01 << Channel; /* set the correpsonding bit */
1495 XDmaPs_WriteReg(InstPtr->Config.BaseAddress,
1496 XDMAPS_INTEN_OFFSET,
1498 Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1499 XDMAPS_INTEN_OFFSET);
1501 InstPtr->Chans[Channel].DmaCmdToHw = Cmd;
1503 if (Cmd->ChanCtrl.SrcInc) {
1504 Xil_DCacheFlushRange(Cmd->BD.SrcAddr, Cmd->BD.Length);
1506 if (Cmd->ChanCtrl.DstInc) {
1507 Xil_DCacheInvalidateRange(Cmd->BD.DstAddr,
1511 Status = XDmaPs_Exec_DMAGO(InstPtr->Config.BaseAddress,
1515 InstPtr->Chans[Channel].DmaCmdToHw = NULL;
1516 Status = XST_FAILURE;
1522 /****************************************************************************/
1525 * Checks whether the DMA channel is active or idle.
1527 * @param InstPtr is the DMA instance.
1528 * @param Channel is the DMA channel number.
1530 * @return 0: if the channel is idle
1535 *****************************************************************************/
1536 int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel)
1538 Xil_AssertNonvoid(InstPtr != NULL);
1540 /* Need to assert Channel is in range */
1541 if (Channel > XDMAPS_CHANNELS_PER_DEV)
1544 return InstPtr->Chans[Channel].DmaCmdToHw != NULL;
1549 /****************************************************************************/
1552 * Allocate a buffer of the DMA program buffer from the pool.
1554 * @param Pool the DMA program pool.
1556 * @return The allocated buffer, NULL if there is any error.
1560 *****************************************************************************/
1561 static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool)
1565 Xil_AssertNonvoid(Pool != NULL);
1567 for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) {
1568 if (!Pool[Index].Allocated) {
1569 Pool[Index].Allocated = 1;
1570 return Pool[Index].Buf;
1578 /*****************************************************************************/
1581 * Driver done interrupt service routine for channel 0. We need this done ISR
1582 * mainly because the driver needs to release the DMA program buffer.
1583 * This is the one that connects the GIC
1585 * @param InstPtr is the DMA instance.
1591 ******************************************************************************/
1592 void XDmaPs_DoneISR_0(XDmaPs *InstPtr)
1594 XDmaPs_DoneISR_n(InstPtr, 0);
1597 /*****************************************************************************/
1600 * Driver done interrupt service routine for channel 1. We need this done ISR
1601 * mainly because the driver needs to release the DMA program buffer.
1602 * This is the one that connects the GIC
1604 * @param InstPtr is the DMA instance.
1610 ******************************************************************************/
1611 void XDmaPs_DoneISR_1(XDmaPs *InstPtr)
1613 XDmaPs_DoneISR_n(InstPtr, 1);
1616 /*****************************************************************************/
1619 * Driver done interrupt service routine for channel 2. We need this done ISR
1620 * mainly because the driver needs to release the DMA program buffer.
1621 * This is the one that connects the GIC
1623 * @param InstPtr is the DMA instance.
1629 ******************************************************************************/
1630 void XDmaPs_DoneISR_2(XDmaPs *InstPtr)
1632 XDmaPs_DoneISR_n(InstPtr, 2);
1635 /*****************************************************************************/
1638 * Driver done interrupt service routine for channel 3. We need this done ISR
1639 * mainly because the driver needs to release the DMA program buffer.
1640 * This is the one that connects the GIC
1642 * @param InstPtr is the DMA instance.
1648 ******************************************************************************/
1649 void XDmaPs_DoneISR_3(XDmaPs *InstPtr)
1651 XDmaPs_DoneISR_n(InstPtr, 3);
1654 /*****************************************************************************/
1657 * Driver done interrupt service routine for channel 4. We need this done ISR
1658 * mainly because the driver needs to release the DMA program buffer.
1659 * This is the one that connects the GIC
1661 * @param InstPtr is the DMA instance.
1667 ******************************************************************************/
1668 void XDmaPs_DoneISR_4(XDmaPs *InstPtr)
1670 XDmaPs_DoneISR_n(InstPtr, 4);
1673 /*****************************************************************************/
1676 * Driver done interrupt service routine for channel 5. We need this done ISR
1677 * mainly because the driver needs to release the DMA program buffer.
1678 * This is the one that connects the GIC
1680 * @param InstPtr is the DMA instance.
1686 ******************************************************************************/
1687 void XDmaPs_DoneISR_5(XDmaPs *InstPtr)
1689 XDmaPs_DoneISR_n(InstPtr, 5);
1692 /*****************************************************************************/
1695 * Driver done interrupt service routine for channel 6. We need this done ISR
1696 * mainly because the driver needs to release the DMA program buffer.
1697 * This is the one that connects the GIC
1699 * @param InstPtr is the DMA instance.
1705 ******************************************************************************/
1706 void XDmaPs_DoneISR_6(XDmaPs *InstPtr)
1708 XDmaPs_DoneISR_n(InstPtr, 6);
1711 /*****************************************************************************/
1714 * Driver done interrupt service routine for channel 7. We need this done ISR
1715 * mainly because the driver needs to release the DMA program buffer.
1716 * This is the one that connects the GIC
1718 * @param InstPtr is the DMA instance.
1724 ******************************************************************************/
1725 void XDmaPs_DoneISR_7(XDmaPs *InstPtr)
1727 XDmaPs_DoneISR_n(InstPtr, 7);
1730 #ifndef XDMAPS_MAX_WAIT
1731 #define XDMAPS_MAX_WAIT 4000
1734 /****************************************************************************/
1736 * Use the debug registers to kill the DMA thread.
1738 * @param BaseAddr is DMA device base address.
1739 * @param Channel is the DMA channel number.
1740 * @param Thread is Debug thread encoding.
1741 * 0: DMA manager thread, 1: DMA channel.
1743 * @return 0 on success, -1 on time out
1747 *****************************************************************************/
1748 static int XDmaPs_Exec_DMAKILL(u32 BaseAddr,
1749 unsigned int Channel,
1750 unsigned int Thread)
1755 DbgInst0 = XDmaPs_DBGINST0(0, 0x01, Channel, Thread);
1757 /* wait while debug status is busy */
1759 while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET)
1760 & XDMAPS_DBGSTATUS_BUSY)
1761 && (WaitCount < XDMAPS_MAX_WAIT))
1764 if (WaitCount >= XDMAPS_MAX_WAIT) {
1766 xil_printf("PL330 device at %x debug status busy time out\n",
1772 /* write debug instruction 0 */
1773 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0);
1775 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, 0);
1778 /* run the command in DbgInst0 and DbgInst1 */
1779 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0);
1784 /****************************************************************************/
1788 * Free a buffer of the DMA program buffer.
1789 * @param Pool the DMA program pool.
1790 * @param Buf the DMA program buffer to be release.
1796 *****************************************************************************/
1797 static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf)
1800 Xil_AssertVoid(Pool != NULL);
1802 for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) {
1803 if (Pool[Index].Buf == Buf) {
1804 if (Pool[Index].Allocated) {
1805 Pool[Index].Allocated = 0;
1811 /*****************************************************************************/
1813 * XDmaPs_Exec_DMAGO - Execute the DMAGO to start a channel.
1815 * @param BaseAddr PL330 device base address
1816 * @param Channel Channel number for the device
1817 * @param DmaProg DMA program starting address, this should be DMA address
1819 * @return 0 on success, -1 on time out
1823 ****************************************************************************/
1824 static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg)
1832 XDmaPs_Instr_DMAGO(DmaGoProg, Channel, DmaProg, 0);
1834 DbgInst0 = XDmaPs_DBGINST0(*(DmaGoProg + 1), *DmaGoProg, 0, 0);
1835 DbgInst1 = (u32)DmaProg;
1837 /* wait while debug status is busy */
1839 while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET)
1840 & XDMAPS_DBGSTATUS_BUSY)
1841 && (WaitCount < XDMAPS_MAX_WAIT)) {
1846 if (WaitCount >= XDMAPS_MAX_WAIT) {
1847 xil_printf("PL330 device at %x debug status busy time out\r\n",
1852 /* write debug instruction 0 */
1853 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0);
1854 /* write debug instruction 1 */
1855 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, DbgInst1);
1858 /* wait while the DMA Manager is busy */
1860 while ((XDmaPs_ReadReg(BaseAddr,
1861 XDMAPS_DS_OFFSET) & XDMAPS_DS_DMA_STATUS)
1862 != XDMAPS_DS_DMA_STATUS_STOPPED
1863 && WaitCount <= XDMAPS_MAX_WAIT) {
1867 if (WaitCount >= XDMAPS_MAX_WAIT) {
1868 xil_printf("PL330 device at %x debug status busy time out\r\n",
1873 /* run the command in DbgInst0 and DbgInst1 */
1874 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0);
1880 /****************************************************************************/
1883 * It's the generic Done ISR.
1884 * @param InstPtr is the DMA instance.
1885 * @param Channel is the DMA channel numer.
1891 *****************************************************************************/
1892 static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel)
1896 XDmaPs_ChannelData *ChanData;
1900 ChanData = InstPtr->Chans + Channel;
1902 /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1903 XDMAPS_INTSTATUS_OFFSET);*/
1905 /* clear the interrupt status */
1906 XDmaPs_WriteReg(InstPtr->Config.BaseAddress,
1907 XDMAPS_INTCLR_OFFSET,
1908 1 << ChanData->ChanId);
1910 /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1911 XDMAPS_INTSTATUS_OFFSET);*/
1914 DmaCmd = ChanData->DmaCmdToHw;
1916 if (!ChanData->HoldDmaProg) {
1917 DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg;
1919 XDmaPs_BufPool_Free(ChanData->ProgBufPool,
1921 DmaCmd->GeneratedDmaProg = NULL;
1924 DmaCmd->DmaStatus = 0;
1925 ChanData->DmaCmdToHw = NULL;
1926 ChanData->DmaCmdFromHw = DmaCmd;
1928 if (ChanData->DoneHandler)
1929 ChanData->DoneHandler(Channel, DmaCmd,
1936 /****************************************************************************/
1938 * Prints the content of the buffer in bytes
1939 * @param Buf is the buffer.
1940 * @param Length is the length of the DMA program.
1945 ****************************************************************************/
1946 static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length)
1949 for (Index = 0; Index < Length; Index++)
1950 xil_printf("[%x] %x\r\n", Index, Buf[Index]);
1953 /****************************************************************************/
1955 * Print the Dma Prog Contents.
1957 * @param Cmd is the command buffer.
1963 *****************************************************************************/
1964 void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd)
1966 if (Cmd->GeneratedDmaProg && Cmd->GeneratedDmaProgLength) {
1967 xil_printf("Generated DMA program (%d):\r\n",
1968 Cmd->GeneratedDmaProgLength);
1969 XDmaPs_Print_DmaProgBuf((char *)Cmd->GeneratedDmaProg,
1970 Cmd->GeneratedDmaProgLength);
1973 if (Cmd->UserDmaProg && Cmd->UserDmaProgLength) {
1974 xil_printf("User defined DMA program (%d):\r\n",
1975 Cmd->UserDmaProgLength);
1976 XDmaPs_Print_DmaProgBuf((char *)Cmd->UserDmaProg,
1977 Cmd->UserDmaProgLength);