1 /******************************************************************************
3 * Copyright (C) 2009 - 2015 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_1
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
72 *****************************************************************************/
74 /***************************** Include Files ********************************/
81 #include "xil_cache.h"
83 #include "xil_printf.h"
86 /************************** Constant Definitions ****************************/
88 /* The following constant defines the amount of error that is allowed for
89 * a specified baud rate. This error is the difference between the actual
90 * baud rate that will be generated using the specified clock and the
94 /**************************** Type Definitions ******************************/
99 #define INLINE __inline
101 /***************** Macros (Inline Functions) Definitions ********************/
104 /************************** Function Prototypes *****************************/
105 static int XDmaPs_Exec_DMAKILL(u32 BaseAddr,
106 unsigned int Channel,
107 unsigned int Thread);
109 static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf);
111 static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg);
113 static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel);
114 static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool);
115 static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd,
116 unsigned CacheLength);
118 static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length);
122 /************************** Variable Definitions ****************************/
124 /****************************************************************************/
127 * Initializes a specific XDmaPs instance such that it is ready to be used.
128 * The data format of the device is setup for 8 data bits, 1 stop bit, and no
129 * parity by default. The baud rate is set to a default value specified by
130 * Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The
131 * receive FIFO threshold is set for 8 bytes. The default operating mode of the
132 * driver is polled mode.
134 * @param InstPtr is a pointer to the XDmaPs instance.
135 * @param Config is a reference to a structure containing information
136 * about a specific XDmaPs driver.
137 * @param EffectiveAddr is the device base address in the virtual memory
138 * address space. The caller is responsible for keeping the
139 * address mapping from EffectiveAddr to the device physical base
140 * address unchanged once this function is invoked. Unexpected
141 * errors may occur if the address mapping changes after this
142 * function is called. If address translation is not used, pass in
143 * the physical address instead.
147 * - XST_SUCCESS on initialization completion
151 *****************************************************************************/
152 int XDmaPs_CfgInitialize(XDmaPs *InstPtr,
153 XDmaPs_Config *Config,
156 int Status = XST_SUCCESS;
157 unsigned int CacheLength = 0;
160 XDmaPs_ChannelData *ChanData;
163 * Assert validates the input arguments
165 Xil_AssertNonvoid(InstPtr != NULL);
166 Xil_AssertNonvoid(Config != NULL);
169 * Setup the driver instance using passed in parameters
171 InstPtr->Config.DeviceId = Config->DeviceId;
172 InstPtr->Config.BaseAddress = EffectiveAddr;
174 CfgReg = XDmaPs_ReadReg(EffectiveAddr, XDMAPS_CR1_OFFSET);
175 CacheLength = CfgReg & XDMAPS_CR1_I_CACHE_LEN_MASK;
176 if (CacheLength < 2 || CacheLength > 5)
179 CacheLength = 1 << CacheLength;
181 InstPtr->CacheLength = CacheLength;
183 memset(InstPtr->Chans, 0,
184 sizeof(XDmaPs_ChannelData[XDMAPS_CHANNELS_PER_DEV]));
186 for (Channel = 0; Channel < XDMAPS_CHANNELS_PER_DEV; Channel++) {
187 ChanData = InstPtr->Chans + Channel;
188 ChanData->ChanId = Channel;
189 ChanData->DevId = Config->DeviceId;
192 InstPtr->IsReady = 1;
197 /****************************************************************************/
200 * Reset the DMA Manager.
202 * @param InstPtr is the DMA instance.
204 * @return 0 on success, -1 on time out
208 *****************************************************************************/
209 int XDmaPs_ResetManager(XDmaPs *InstPtr)
212 Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress,
218 /****************************************************************************/
221 * Reset the specified DMA Channel.
223 * @param InstPtr is the DMA instance.
224 * @param Channel is the channel to be reset.
226 * @return 0 on success, -1 on time out
230 *****************************************************************************/
231 int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel)
234 Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress,
241 /*****************************************************************************/
244 * Driver fault interrupt service routine
245 * This is the one that connects the GIC
247 * @param InstPtr is the DMA instance.
253 ******************************************************************************/
254 void XDmaPs_FaultISR(XDmaPs *InstPtr)
258 u32 Fsm; /* Fault status DMA manager register value */
259 u32 Fsc; /* Fault status DMA channel register value */
260 u32 FaultType; /* Fault type DMA manager register value */
262 u32 BaseAddr = InstPtr->Config.BaseAddress;
264 u32 Pc; /* DMA Pc or channel Pc */
265 XDmaPs_ChannelData *ChanData;
272 Fsm = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSM_OFFSET) & 0x01;
273 Fsc = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSC_OFFSET) & 0xFF;
276 DevId = InstPtr->Config.DeviceId;
280 * if DMA manager is fault
282 FaultType = XDmaPs_ReadReg(BaseAddr, XDMAPS_FTM_OFFSET);
283 Pc = XDmaPs_ReadReg(BaseAddr, XDMAPS_DPC_OFFSET);
285 xil_printf("PL330 device %d fault with type: %x at Pc %x\n",
289 /* kill the DMA manager thread */
290 /* Should we disable interrupt?*/
291 XDmaPs_Exec_DMAKILL(BaseAddr, 0, 0);
295 * check which channel faults and kill the channel thread
298 Chan < XDMAPS_CHANNELS_PER_DEV;
300 if (Fsc & (0x01 << Chan)) {
302 XDmaPs_ReadReg(BaseAddr,
303 XDmaPs_FTCn_OFFSET(Chan));
304 Pc = XDmaPs_ReadReg(BaseAddr,
305 XDmaPs_CPCn_OFFSET(Chan));
307 /* kill the channel thread */
308 /* Should we disable interrupt? */
309 XDmaPs_Exec_DMAKILL(BaseAddr, Chan, 1);
312 * get the fault type and fault Pc and invoke the
315 ChanData = InstPtr->Chans + Chan;
317 DmaCmd = ChanData->DmaCmdToHw;
319 /* Should we check DmaCmd is not null */
320 DmaCmd->DmaStatus = -1;
321 DmaCmd->ChanFaultType = FaultType;
322 DmaCmd->ChanFaultPCAddr = Pc;
323 ChanData->DmaCmdFromHw = DmaCmd;
324 ChanData->DmaCmdToHw = NULL;
326 if (!ChanData->HoldDmaProg) {
327 DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg;
329 XDmaPs_BufPool_Free(ChanData->ProgBufPool,
331 DmaCmd->GeneratedDmaProg = NULL;
334 if (InstPtr->FaultHandler)
335 InstPtr->FaultHandler(Chan,
344 /*****************************************************************************/
347 * Set the done handler for a channel.
349 * @param InstPtr is the DMA instance.
350 * @param Channel is the channel number.
351 * @param DoneHandler is the done interrupt handler.
352 * @param CallbackRef is the callback reference data.
358 ******************************************************************************/
359 int XDmaPs_SetDoneHandler(XDmaPs *InstPtr,
361 XDmaPsDoneHandler DoneHandler,
364 XDmaPs_ChannelData *ChanData;
366 Xil_AssertNonvoid(InstPtr != NULL);
368 if (Channel >= XDMAPS_CHANNELS_PER_DEV)
372 ChanData = InstPtr->Chans + Channel;
374 ChanData->DoneHandler = DoneHandler;
375 ChanData->DoneRef = CallbackRef;
380 /*****************************************************************************/
383 * Set the fault handler for a channel.
385 * @param InstPtr is the DMA instance.
386 * @param FaultHandler is the fault interrupt handler.
387 * @param CallbackRef is the callback reference data.
393 ******************************************************************************/
394 int XDmaPs_SetFaultHandler(XDmaPs *InstPtr,
395 XDmaPsFaultHandler FaultHandler,
398 Xil_AssertNonvoid(InstPtr != NULL);
400 InstPtr->FaultHandler = FaultHandler;
401 InstPtr->FaultRef = CallbackRef;
408 /****************************************************************************/
410 * Construction function for DMAEND instruction. This function fills the program
411 * buffer with the constructed instruction.
413 * @param DmaProg the DMA program buffer, it's the starting address for
414 * the instruction being constructed
416 * @return The number of bytes for this instruction which is 1.
420 *****************************************************************************/
421 INLINE int XDmaPs_Instr_DMAEND(char *DmaProg)
433 INLINE void XDmaPs_Memcpy4(char *Dst, char *Src)
436 *(Dst + 1) = *(Src + 1);
437 *(Dst + 2) = *(Src + 2);
438 *(Dst + 3) = *(Src + 3);
441 /****************************************************************************/
444 * Construction function for DMAGO instruction. This function fills the program
445 * buffer with the constructed instruction.
447 * @param DmaProg is the DMA program buffer, it's the starting address
448 * for the instruction being constructed
449 * @param Cn is the Channel number, 0 - 7
450 * @param Imm is 32-bit immediate number written to the Channel Program
452 * @param Ns is Non-secure flag. If Ns is 1, the DMA channel operates in
453 * the Non-secure state. If Ns is 0, the execution depends on the
454 * security state of the DMA manager:
455 * DMA manager is in the Secure state, DMA channel operates in the
457 * DMA manager is in the Non-secure state, DMAC aborts.
459 * @return The number of bytes for this instruction which is 6.
463 *****************************************************************************/
464 INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn,
465 u32 Imm, unsigned int Ns)
469 * 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
470 * 0 0 0 0 0 |cn[2:0]| 1 0 1 0 0 0 ns 0
475 *DmaProg = 0xA0 | ((Ns << 1) & 0x02);
477 *(DmaProg + 1) = (u8)(Cn & 0x07);
479 // *((u32 *)(DmaProg + 2)) = Imm;
480 XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm);
486 /****************************************************************************/
489 * Construction function for DMALD instruction. This function fills the program
490 * buffer with the constructed instruction.
492 * @param DmaProg the DMA program buffer, it's the starting address for the
493 * instruction being constructed
495 * @return The number of bytes for this instruction which is 1.
499 *****************************************************************************/
500 INLINE int XDmaPs_Instr_DMALD(char *DmaProg)
507 * Note: this driver doesn't support conditional load or store,
508 * so the bs bit is 0 and x bit is 0.
514 /****************************************************************************/
517 * Construction function for DMALP instruction. This function fills the program
518 * buffer with the constructed instruction.
520 * @param DmaProg is the DMA program buffer, it's the starting address
521 * for the instruction being constructed
522 * @param Lc is the Loop counter register, can either be 0 or 1.
523 * @param LoopIterations: the number of interations, LoopInterations - 1
524 * will be encoded in the DMALP instruction.
526 * @return The number of bytes for this instruction which is 2.
530 *****************************************************************************/
531 INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc,
532 unsigned LoopIterations)
536 * 15 ... 8 7 6 5 4 3 2 1 0
537 * | iter[7:0] |0 0 1 0 0 0 lc 0
539 *DmaProg = (u8)(0x20 | ((Lc & 1) << 1));
540 *(DmaProg + 1) = (u8)(LoopIterations - 1);
544 /****************************************************************************/
547 * Construction function for DMALPEND instruction. This function fills the
548 * program buffer with the constructed instruction.
550 * @param DmaProg is the DMA program buffer, it's the starting address
551 * for the instruction being constructed
552 * @param BodyStart is the starting address of the loop body. It is used
553 * to calculate the bytes of backward jump.
554 * @param Lc is the Loop counter register, can either be 0 or 1.
556 * @return The number of bytes for this instruction which is 2.
560 *****************************************************************************/
561 INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc)
565 * 15 ... 8 7 6 5 4 3 2 1 0
566 * | backward_jump[7:0] |0 0 1 nf 1 lc bs x
569 * nf is for loop forever. The driver does not support loop forever,
571 * The driver does not support conditional LPEND, so bs is 0, x is 0.
573 *DmaProg = 0x38 | ((Lc & 1) << 2);
574 *(DmaProg + 1) = (u8)(DmaProg - BodyStart);
580 * Register number for the DMAMOV instruction
582 #define XDMAPS_MOV_SAR 0x0
583 #define XDMAPS_MOV_CCR 0x1
584 #define XDMAPS_MOV_DAR 0x2
586 /****************************************************************************/
589 * Construction function for DMAMOV instruction. This function fills the
590 * program buffer with the constructed instruction.
592 * @param DmaProg is the DMA program buffer, it's the starting address
593 * for the instruction being constructed
594 * @param Rd is the register id, 0 for SAR, 1 for CCR, and 2 for DAR
595 * @param Imm is the 32-bit immediate number
597 * @return The number of bytes for this instruction which is 6.
601 *****************************************************************************/
602 INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm)
606 * 15 4 3 2 1 10 ... 8 7 6 5 4 3 2 1 0
607 * 0 0 0 0 0 |rd[2:0]|1 0 1 1 1 1 0 0
612 * rd: b000 for SAR, b001 CCR, b010 DAR
615 *(DmaProg + 1) = Rd & 0x7;
616 // *((u32 *)(DmaProg + 2)) = Imm;
617 XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm);
622 /****************************************************************************/
625 * Construction function for DMANOP instruction. This function fills the
626 * program buffer with the constructed instruction.
628 * @param DmaProg is the DMA program buffer, it's the starting address
629 * for the instruction being constructed
630 * @return The number of bytes for this instruction which is 1.
634 *****************************************************************************/
635 INLINE int XDmaPs_Instr_DMANOP(char *DmaProg)
646 /****************************************************************************/
649 * Construction function for DMARMB instruction. This function fills the
650 * program buffer with the constructed instruction.
652 * @param DmaProg is the DMA program buffer, it's the starting address
653 * for the instruction being constructed
655 * @return The number of bytes for this instruction which is 1.
659 *****************************************************************************/
660 INLINE int XDmaPs_Instr_DMARMB(char *DmaProg)
671 /****************************************************************************/
674 * Construction function for DMASEV instruction. This function fills the
675 * program buffer with the constructed instruction.
677 * @param DmaProg is the DMA program buffer, it's the starting address
678 * for the instruction being constructed
679 * @param EventNumber is the Event number to signal.
681 * @return The number of bytes for this instruction which is 2.
685 *****************************************************************************/
686 INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber)
690 * 15 4 3 2 1 10 9 8 7 6 5 4 3 2 1 0
691 * |event[4:0]| 0 0 0 0 0 1 1 0 1 0 0
694 *(DmaProg + 1) = (u8)(EventNumber << 3);
700 /****************************************************************************/
703 * Construction function for DMAST instruction. This function fills the
704 * program buffer with the constructed instruction.
706 * @param DmaProg is the DMA program buffer, it's the starting address
707 * for the instruction being constructed
709 * @return The number of bytes for this instruction which is 1.
713 *****************************************************************************/
714 INLINE int XDmaPs_Instr_DMAST(char *DmaProg)
721 * Note: this driver doesn't support conditional load or store,
722 * so the bs bit is 0 and x bit is 0.
729 /****************************************************************************/
732 * Construction function for DMAWMB instruction. This function fills the
733 * program buffer with the constructed instruction.
735 * @param DmaProg is the DMA program buffer, it's the starting address
736 * for the instruction being constructed
738 * @return The number of bytes for this instruction which is 1.
742 *****************************************************************************/
743 INLINE int XDmaPs_Instr_DMAWMB(char *DmaProg)
754 /****************************************************************************/
757 * Conversion function from the endian swap size to the bit encoding of the CCR
759 * @param EndianSwapSize is the endian swap size, in terms of bits, it
760 * could be 8, 16, 32, 64, or 128(We are using DMA assembly syntax)
762 * @return The endian swap size bit encoding for the CCR.
766 *****************************************************************************/
767 INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize)
769 switch (EndianSwapSize) {
787 /****************************************************************************/
790 * Conversion function from the burst size to the bit encoding of the CCR
792 * @param BurstSize is the burst size. It's the data width.
793 * In terms of bytes, it could be 1, 2, 4, 8, 16, 32, 64, or 128.
794 * It must be no larger than the bus width.
795 * (We are using DMA assembly syntax.)
799 *****************************************************************************/
800 INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize)
825 /****************************************************************************/
828 * Conversion function from PL330 bus transfer descriptors to CCR value. All the
829 * values passed to the functions are in terms of assembly languages, not in
830 * terms of the register bit encoding.
832 * @param ChanCtrl is the Instance of XDmaPs_ChanCtrl.
834 * @return The 32-bit CCR value.
838 *****************************************************************************/
839 u32 XDmaPs_ToCCRValue(XDmaPs_ChanCtrl *ChanCtrl)
842 * Channel Control Register encoding
843 * [31:28] - endian_swap_size
844 * [27:25] - dst_cache_ctrl
845 * [24:22] - dst_prot_ctrl
846 * [21:18] - dst_burst_len
847 * [17:15] - dst_burst_size
849 * [13:11] - src_cache_ctrl
850 * [10:8] - src_prot_ctrl
851 * [7:4] - src_burst_len
852 * [3:1] - src_burst_size
857 XDmaPs_ToEndianSwapSizeBits(ChanCtrl->EndianSwapSize);
859 unsigned dst_burst_size =
860 XDmaPs_ToBurstSizeBits(ChanCtrl->DstBurstSize);
861 unsigned dst_burst_len = (ChanCtrl->DstBurstLen - 1) & 0x0F;
862 unsigned dst_cache_ctrl = (ChanCtrl->DstCacheCtrl & 0x03)
863 | ((ChanCtrl->DstCacheCtrl & 0x08) >> 1);
864 unsigned dst_prot_ctrl = ChanCtrl->DstProtCtrl & 0x07;
865 unsigned dst_inc_bit = ChanCtrl->DstInc & 1;
867 unsigned src_burst_size =
868 XDmaPs_ToBurstSizeBits(ChanCtrl->SrcBurstSize);
869 unsigned src_burst_len = (ChanCtrl->SrcBurstLen - 1) & 0x0F;
870 unsigned src_cache_ctrl = (ChanCtrl->SrcCacheCtrl & 0x03)
871 | ((ChanCtrl->SrcCacheCtrl & 0x08) >> 1);
872 unsigned src_prot_ctrl = ChanCtrl->SrcProtCtrl & 0x07;
873 unsigned src_inc_bit = ChanCtrl->SrcInc & 1;
875 u32 ccr_value = (es << 28)
876 | (dst_cache_ctrl << 25)
877 | (dst_prot_ctrl << 22)
878 | (dst_burst_len << 18)
879 | (dst_burst_size << 15)
880 | (dst_inc_bit << 14)
881 | (src_cache_ctrl << 11)
882 | (src_prot_ctrl << 8)
883 | (src_burst_len << 4)
884 | (src_burst_size << 1)
890 /****************************************************************************/
892 * Construct a loop with only DMALD and DMAST as the body using loop counter 0.
893 * The function also makes sure the loop body and the lpend is in the same
896 * @param DmaProgStart is the very start address of the DMA program.
897 * This is used to calculate whether the loop is in a cache line.
898 * @param CacheLength is the icache line length, in terms of bytes.
899 * If it's zero, the performance enhancement feature will be
901 * @param DmaProgLoopStart The starting address of the loop (DMALP).
902 * @param LoopCount The inner loop count. Loop count - 1 will be used to
903 * initialize the loop counter.
905 * @return The number of bytes the loop has.
909 *****************************************************************************/
910 int XDmaPs_ConstructSingleLoop(char *DmaProgStart,
912 char *DmaProgLoopStart,
915 int CacheStartOffset;
918 char *DmaProgBuf = DmaProgLoopStart;
920 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCount);
922 if (CacheLength > 0) {
924 * the CacheLength > 0 switch is ued to turn on/off nop
927 CacheStartOffset = DmaProgBuf - DmaProgStart;
928 CacheEndOffset = CacheStartOffset + 3;
931 * check whether the body and lpend fit in one cache line
933 if (CacheStartOffset / CacheLength
934 != CacheEndOffset / CacheLength) {
935 /* insert the nops */
936 NumNops = CacheLength
937 - CacheStartOffset % CacheLength;
940 XDmaPs_Instr_DMANOP(DmaProgBuf);
945 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
946 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
947 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
950 return DmaProgBuf - DmaProgLoopStart;
953 /****************************************************************************/
955 * Construct a nested loop with only DMALD and DMAST in the inner loop body.
956 * It uses loop counter 1 for the outer loop and loop counter 0 for the
959 * @param DmaProgStart is the very start address of the DMA program.
960 * This is used to calculate whether the loop is in a cache line.
961 * @param CacheLength is the icache line length, in terms of bytes.
962 * If it's zero, the performance enhancement feature will be
964 * @param DmaProgLoopStart The starting address of the loop (DMALP).
965 * @param LoopCountOuter The outer loop count. Loop count - 1 will be
966 * used to initialize the loop counter.
967 * @param LoopCountInner The inner loop count. Loop count - 1 will be
968 * used to initialize the loop counter.
970 * @return The number byes the nested loop program has.
974 *****************************************************************************/
975 int XDmaPs_ConstructNestedLoop(char *DmaProgStart,
977 char *DmaProgLoopStart,
978 unsigned int LoopCountOuter,
979 unsigned int LoopCountInner)
981 int CacheStartOffset;
984 char *InnerLoopStart;
985 char *DmaProgBuf = DmaProgLoopStart;
987 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 1, LoopCountOuter);
988 InnerLoopStart = DmaProgBuf;
990 if (CacheLength > 0) {
992 * the CacheLength > 0 switch is ued to turn on/off nop
995 if (CacheLength < 8) {
997 * if the cache line is too small to fit both loops
998 * just align the inner loop
1001 XDmaPs_ConstructSingleLoop(DmaProgStart,
1005 /* outer loop end */
1007 XDmaPs_Instr_DMALPEND(DmaProgBuf,
1012 * the nested loop is constructed for
1013 * smaller cache line
1015 return DmaProgBuf - DmaProgLoopStart;
1019 * Now let's handle the case where a cache line can
1020 * fit the nested loops.
1022 CacheStartOffset = DmaProgBuf - DmaProgStart;
1023 CacheEndOffset = CacheStartOffset + 7;
1026 * check whether the body and lpend fit in one cache line
1028 if (CacheStartOffset / CacheLength
1029 != CacheEndOffset / CacheLength) {
1030 /* insert the nops */
1031 NumNops = CacheLength
1032 - CacheStartOffset % CacheLength;
1035 XDmaPs_Instr_DMANOP(DmaProgBuf);
1040 /* insert the inner DMALP */
1041 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCountInner);
1043 /* DMALD and DMAST instructions */
1044 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
1045 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
1047 /* inner DMALPEND */
1048 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
1050 /* outer DMALPEND */
1051 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
1054 /* return the number of bytes */
1055 return DmaProgBuf - DmaProgLoopStart;
1059 * [31:28] endian_swap_size b0000
1060 * [27:25] dst_cache_ctrl b000
1061 * [24:22] dst_prot_ctrl b000
1062 * [21:18] dst_burst_len b0000
1063 * [17:15] dst_burst_size b000
1065 * [27:25] src_cache_ctrl b000
1066 * [24:22] src_prot_ctrl b000
1067 * [21:18] src_burst_len b0000
1068 * [17:15] src_burst_size b000
1071 #define XDMAPS_CCR_SINGLE_BYTE (0x0)
1072 #define XDMAPS_CCR_M2M_SINGLE_BYTE ((0x1 << 14) | 0x1)
1075 /****************************************************************************/
1078 * Construct the DMA program based on the descriptions of the DMA transfer.
1079 * The function handles memory to memory DMA transfers.
1080 * It also handles unalgined head and small amount of residue tail.
1082 * @param Channel DMA channel number
1083 * @param Cmd is the DMA command.
1084 * @param CacheLength is the icache line length, in terms of bytes.
1085 * If it's zero, the performance enhancement feature will be
1088 * @returns The number of bytes for the program.
1092 *****************************************************************************/
1093 static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd,
1094 unsigned CacheLength)
1099 char *DmaProgBuf = (char *)Cmd->GeneratedDmaProg;
1100 unsigned DevChan = Channel;
1101 unsigned long DmaLength = Cmd->BD.Length;
1102 u32 SrcAddr = Cmd->BD.SrcAddr;
1104 unsigned SrcInc = Cmd->ChanCtrl.SrcInc;
1105 u32 DstAddr = Cmd->BD.DstAddr;
1106 unsigned DstInc = Cmd->ChanCtrl.DstInc;
1108 char *DmaProgStart = DmaProgBuf;
1110 unsigned int BurstBytes;
1111 unsigned int LoopCount;
1112 unsigned int LoopCount1 = 0;
1113 unsigned int LoopResidue = 0;
1114 unsigned int TailBytes;
1115 unsigned int TailWords;
1118 unsigned int Unaligned;
1119 unsigned int UnalignedCount;
1120 unsigned int MemBurstSize = 1;
1123 unsigned int SrcUnaligned = 0;
1124 unsigned int DstUnaligned = 0;
1126 XDmaPs_ChanCtrl *ChanCtrl;
1127 XDmaPs_ChanCtrl WordChanCtrl;
1128 static XDmaPs_ChanCtrl Mem2MemByteCC;
1130 Mem2MemByteCC.EndianSwapSize = 0;
1131 Mem2MemByteCC.DstCacheCtrl = 0;
1132 Mem2MemByteCC.DstProtCtrl = 0;
1133 Mem2MemByteCC.DstBurstLen = 1;
1134 Mem2MemByteCC.DstBurstSize = 1;
1135 Mem2MemByteCC.DstInc = 1;
1136 Mem2MemByteCC.SrcCacheCtrl = 0;
1137 Mem2MemByteCC.SrcProtCtrl = 0;
1138 Mem2MemByteCC.SrcBurstLen = 1;
1139 Mem2MemByteCC.SrcBurstSize = 1;
1140 Mem2MemByteCC.SrcInc = 1;
1142 ChanCtrl = &Cmd->ChanCtrl;
1144 /* insert DMAMOV for SAR and DAR */
1145 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1148 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1153 if (ChanCtrl->SrcInc)
1154 SrcUnaligned = SrcAddr % ChanCtrl->SrcBurstSize;
1156 if (ChanCtrl->DstInc)
1157 DstUnaligned = DstAddr % ChanCtrl->DstBurstSize;
1159 if ((SrcUnaligned && DstInc) || (DstUnaligned && SrcInc)) {
1160 ChanCtrl = &Mem2MemByteCC;
1163 if (ChanCtrl->SrcInc) {
1164 MemBurstSize = ChanCtrl->SrcBurstSize;
1167 } else if (ChanCtrl->DstInc) {
1168 MemBurstSize = ChanCtrl->DstBurstSize;
1172 /* check whether the head is aligned or not */
1173 Unaligned = MemAddr % MemBurstSize;
1176 /* if head is unaligned, transfer head in bytes */
1177 UnalignedCount = MemBurstSize - Unaligned;
1178 CCRValue = XDMAPS_CCR_SINGLE_BYTE
1180 | ((DstInc & 1) << 14);
1182 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1186 for (Index = 0; Index < UnalignedCount; Index++) {
1187 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
1188 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
1191 DmaLength -= UnalignedCount;
1194 /* now the burst transfer part */
1195 CCRValue = XDmaPs_ToCCRValue(ChanCtrl);
1196 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1200 BurstBytes = ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen;
1202 LoopCount = DmaLength / BurstBytes;
1203 TailBytes = DmaLength % BurstBytes;
1206 * the loop count register is 8-bit wide, so if we need
1207 * a larger loop, we need to have nested loops
1209 if (LoopCount > 256) {
1210 LoopCount1 = LoopCount / 256;
1211 if (LoopCount1 > 256) {
1212 xil_printf("DMA operation cannot fit in a 2-level "
1213 "loop for channel %d, please reduce the "
1214 "DMA length or increase the burst size or "
1219 LoopResidue = LoopCount % 256;
1223 XDmaPs_ConstructNestedLoop(DmaProgStart,
1230 XDmaPs_ConstructSingleLoop(DmaProgStart,
1235 /* there will be some that cannot be covered by
1238 LoopCount = LoopResidue;
1241 if (LoopCount > 0) {
1242 DmaProgBuf += XDmaPs_ConstructSingleLoop(DmaProgStart,
1249 /* handle the tail */
1250 TailWords = TailBytes / MemBurstSize;
1251 TailBytes = TailBytes % MemBurstSize;
1254 WordChanCtrl = *ChanCtrl;
1256 * if we can transfer the tail in words, we will
1257 * transfer words as much as possible
1259 WordChanCtrl.SrcBurstSize = MemBurstSize;
1260 WordChanCtrl.SrcBurstLen = 1;
1261 WordChanCtrl.DstBurstSize = MemBurstSize;
1262 WordChanCtrl.DstBurstLen = 1;
1266 * the burst length is 1
1268 CCRValue = XDmaPs_ToCCRValue(&WordChanCtrl);
1271 XDmaPs_Instr_DMAMOV(DmaProgBuf,
1275 XDmaPs_ConstructSingleLoop(DmaProgStart,
1284 * for the rest, we'll tranfer in bytes
1287 * So far just to be safe, the tail bytes
1288 * are transfered in a loop. We can optimize a little
1289 * to perform a burst.
1291 CCRValue = XDMAPS_CCR_SINGLE_BYTE
1293 | ((DstInc & 1) << 14);
1296 XDmaPs_Instr_DMAMOV(DmaProgBuf,
1301 XDmaPs_ConstructSingleLoop(DmaProgStart,
1309 DmaProgBuf += XDmaPs_Instr_DMASEV(DmaProgBuf, DevChan);
1310 DmaProgBuf += XDmaPs_Instr_DMAEND(DmaProgBuf);
1312 DmaProgBytes = DmaProgBuf - DmaProgStart;
1314 Xil_DCacheFlushRange((u32)DmaProgStart, DmaProgBytes);
1316 return DmaProgBytes;
1321 /****************************************************************************/
1324 * Generate a DMA program based for the DMA command, the buffer will be pointed
1325 * by the GeneratedDmaProg field of the command.
1327 * @param InstPtr is then DMA instance.
1328 * @param Channel is the DMA channel number.
1329 * @param Cmd is the DMA command.
1331 * @return - XST_SUCCESS on success.
1332 * - XST_FAILURE if it fails
1336 *****************************************************************************/
1337 int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd)
1341 XDmaPs_ChannelData *ChanData;
1342 XDmaPs_ChanCtrl *ChanCtrl;
1344 Xil_AssertNonvoid(InstPtr != NULL);
1345 Xil_AssertNonvoid(Cmd != NULL);
1348 if (Channel > XDMAPS_CHANNELS_PER_DEV)
1351 ChanData = InstPtr->Chans + Channel;
1352 ChanCtrl = &Cmd->ChanCtrl;
1354 if (ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen
1355 != ChanCtrl->DstBurstSize * ChanCtrl->DstBurstLen) {
1361 * unaligned fixed address is not supported
1363 if (!ChanCtrl->SrcInc && Cmd->BD.SrcAddr % ChanCtrl->SrcBurstSize) {
1367 if (!ChanCtrl->DstInc && Cmd->BD.DstAddr % ChanCtrl->DstBurstSize) {
1371 Buf = XDmaPs_BufPool_Allocate(ChanData->ProgBufPool);
1376 Cmd->GeneratedDmaProg = Buf;
1377 ProgLen = XDmaPs_BuildDmaProg(Channel, Cmd,
1378 InstPtr->CacheLength);
1379 Cmd->GeneratedDmaProgLength = ProgLen;
1383 XDmaPs_Print_DmaProg(Cmd);
1387 /* something wrong, release the buffer */
1388 XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf);
1389 Cmd->GeneratedDmaProgLength = 0;
1390 Cmd->GeneratedDmaProg = NULL;
1398 /****************************************************************************/
1400 * Free the DMA program buffer that is pointed by the GeneratedDmaProg field
1403 * @param InstPtr is then DMA instance.
1404 * @param Channel is the DMA channel number.
1405 * @param Cmd is the DMA command.
1407 * @return XST_SUCCESS on success.
1408 * XST_FAILURE if there is any error.
1412 ****************************************************************************/
1413 int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd)
1417 XDmaPs_ChannelData *ChanData;
1419 Xil_AssertNonvoid(InstPtr != NULL);
1420 Xil_AssertNonvoid(Cmd != NULL);
1422 if (Channel > XDMAPS_CHANNELS_PER_DEV)
1425 Buf = (void *)Cmd->GeneratedDmaProg;
1426 ChanData = InstPtr->Chans + Channel;
1429 XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf);
1430 Cmd->GeneratedDmaProg = 0;
1431 Cmd->GeneratedDmaProgLength = 0;
1438 /****************************************************************************/
1441 * Start a DMA command. The command can only be invoked when the channel
1442 * is idle. The driver takes the command, generates DMA program if needed,
1443 * then pass the program to DMAC to execute.
1445 * @param InstPtr is then DMA instance.
1446 * @param Channel is the DMA channel number.
1447 * @param Cmd is the DMA command.
1448 * @param HoldDmaProg is tag indicating whether the driver can release
1449 * the allocated DMA buffer or not. If a user wants to examine the
1450 * generated DMA program, the flag should be set to 1. After the
1451 * DMA program is finished, a user needs to explicity free the
1455 * - XST_SUCCESS on success
1456 * - XST_DEVICE_BUSY if DMA is busy
1457 * - XST_FAILURE on other failures
1461 ****************************************************************************/
1462 int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel,
1470 Xil_AssertNonvoid(InstPtr != NULL);
1471 Xil_AssertNonvoid(Cmd != NULL);
1474 Cmd->DmaStatus = XST_FAILURE;
1476 if (XDmaPs_IsActive(InstPtr, Channel))
1477 return XST_DEVICE_BUSY;
1479 if (!Cmd->UserDmaProg && !Cmd->GeneratedDmaProg) {
1480 Status = XDmaPs_GenDmaProg(InstPtr, Channel, Cmd);
1485 InstPtr->Chans[Channel].HoldDmaProg = HoldDmaProg;
1487 if (Cmd->UserDmaProg)
1488 DmaProg = (u32)Cmd->UserDmaProg;
1489 else if (Cmd->GeneratedDmaProg)
1490 DmaProg = (u32)Cmd->GeneratedDmaProg;
1493 /* enable the interrupt */
1494 Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1495 XDMAPS_INTEN_OFFSET);
1496 Inten |= 0x01 << Channel; /* set the correpsonding bit */
1497 XDmaPs_WriteReg(InstPtr->Config.BaseAddress,
1498 XDMAPS_INTEN_OFFSET,
1500 Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1501 XDMAPS_INTEN_OFFSET);
1503 InstPtr->Chans[Channel].DmaCmdToHw = Cmd;
1505 if (Cmd->ChanCtrl.SrcInc) {
1506 Xil_DCacheFlushRange(Cmd->BD.SrcAddr, Cmd->BD.Length);
1508 if (Cmd->ChanCtrl.DstInc) {
1509 Xil_DCacheInvalidateRange(Cmd->BD.DstAddr,
1513 Status = XDmaPs_Exec_DMAGO(InstPtr->Config.BaseAddress,
1517 InstPtr->Chans[Channel].DmaCmdToHw = NULL;
1518 Status = XST_FAILURE;
1524 /****************************************************************************/
1527 * Checks whether the DMA channel is active or idle.
1529 * @param InstPtr is the DMA instance.
1530 * @param Channel is the DMA channel number.
1532 * @return 0: if the channel is idle
1537 *****************************************************************************/
1538 int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel)
1540 Xil_AssertNonvoid(InstPtr != NULL);
1542 /* Need to assert Channel is in range */
1543 if (Channel > XDMAPS_CHANNELS_PER_DEV)
1546 return InstPtr->Chans[Channel].DmaCmdToHw != NULL;
1551 /****************************************************************************/
1554 * Allocate a buffer of the DMA program buffer from the pool.
1556 * @param Pool the DMA program pool.
1558 * @return The allocated buffer, NULL if there is any error.
1562 *****************************************************************************/
1563 static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool)
1567 Xil_AssertNonvoid(Pool != NULL);
1569 for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) {
1570 if (!Pool[Index].Allocated) {
1571 Pool[Index].Allocated = 1;
1572 return Pool[Index].Buf;
1580 /*****************************************************************************/
1583 * Driver done interrupt service routine for channel 0. We need this done ISR
1584 * mainly because the driver needs to release the DMA program buffer.
1585 * This is the one that connects the GIC
1587 * @param InstPtr is the DMA instance.
1593 ******************************************************************************/
1594 void XDmaPs_DoneISR_0(XDmaPs *InstPtr)
1596 XDmaPs_DoneISR_n(InstPtr, 0);
1599 /*****************************************************************************/
1602 * Driver done interrupt service routine for channel 1. We need this done ISR
1603 * mainly because the driver needs to release the DMA program buffer.
1604 * This is the one that connects the GIC
1606 * @param InstPtr is the DMA instance.
1612 ******************************************************************************/
1613 void XDmaPs_DoneISR_1(XDmaPs *InstPtr)
1615 XDmaPs_DoneISR_n(InstPtr, 1);
1618 /*****************************************************************************/
1621 * Driver done interrupt service routine for channel 2. We need this done ISR
1622 * mainly because the driver needs to release the DMA program buffer.
1623 * This is the one that connects the GIC
1625 * @param InstPtr is the DMA instance.
1631 ******************************************************************************/
1632 void XDmaPs_DoneISR_2(XDmaPs *InstPtr)
1634 XDmaPs_DoneISR_n(InstPtr, 2);
1637 /*****************************************************************************/
1640 * Driver done interrupt service routine for channel 3. We need this done ISR
1641 * mainly because the driver needs to release the DMA program buffer.
1642 * This is the one that connects the GIC
1644 * @param InstPtr is the DMA instance.
1650 ******************************************************************************/
1651 void XDmaPs_DoneISR_3(XDmaPs *InstPtr)
1653 XDmaPs_DoneISR_n(InstPtr, 3);
1656 /*****************************************************************************/
1659 * Driver done interrupt service routine for channel 4. We need this done ISR
1660 * mainly because the driver needs to release the DMA program buffer.
1661 * This is the one that connects the GIC
1663 * @param InstPtr is the DMA instance.
1669 ******************************************************************************/
1670 void XDmaPs_DoneISR_4(XDmaPs *InstPtr)
1672 XDmaPs_DoneISR_n(InstPtr, 4);
1675 /*****************************************************************************/
1678 * Driver done interrupt service routine for channel 5. We need this done ISR
1679 * mainly because the driver needs to release the DMA program buffer.
1680 * This is the one that connects the GIC
1682 * @param InstPtr is the DMA instance.
1688 ******************************************************************************/
1689 void XDmaPs_DoneISR_5(XDmaPs *InstPtr)
1691 XDmaPs_DoneISR_n(InstPtr, 5);
1694 /*****************************************************************************/
1697 * Driver done interrupt service routine for channel 6. We need this done ISR
1698 * mainly because the driver needs to release the DMA program buffer.
1699 * This is the one that connects the GIC
1701 * @param InstPtr is the DMA instance.
1707 ******************************************************************************/
1708 void XDmaPs_DoneISR_6(XDmaPs *InstPtr)
1710 XDmaPs_DoneISR_n(InstPtr, 6);
1713 /*****************************************************************************/
1716 * Driver done interrupt service routine for channel 7. We need this done ISR
1717 * mainly because the driver needs to release the DMA program buffer.
1718 * This is the one that connects the GIC
1720 * @param InstPtr is the DMA instance.
1726 ******************************************************************************/
1727 void XDmaPs_DoneISR_7(XDmaPs *InstPtr)
1729 XDmaPs_DoneISR_n(InstPtr, 7);
1732 #ifndef XDMAPS_MAX_WAIT
1733 #define XDMAPS_MAX_WAIT 4000
1736 /****************************************************************************/
1738 * Use the debug registers to kill the DMA thread.
1740 * @param BaseAddr is DMA device base address.
1741 * @param Channel is the DMA channel number.
1742 * @param Thread is Debug thread encoding.
1743 * 0: DMA manager thread, 1: DMA channel.
1745 * @return 0 on success, -1 on time out
1749 *****************************************************************************/
1750 static int XDmaPs_Exec_DMAKILL(u32 BaseAddr,
1751 unsigned int Channel,
1752 unsigned int Thread)
1757 DbgInst0 = XDmaPs_DBGINST0(0, 0x01, Channel, Thread);
1759 /* wait while debug status is busy */
1761 while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET)
1762 & XDMAPS_DBGSTATUS_BUSY)
1763 && (WaitCount < XDMAPS_MAX_WAIT))
1766 if (WaitCount >= XDMAPS_MAX_WAIT) {
1768 xil_printf("PL330 device at %x debug status busy time out\n",
1774 /* write debug instruction 0 */
1775 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0);
1777 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, 0);
1780 /* run the command in DbgInst0 and DbgInst1 */
1781 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0);
1786 /****************************************************************************/
1790 * Free a buffer of the DMA program buffer.
1791 * @param Pool the DMA program pool.
1792 * @param Buf the DMA program buffer to be release.
1798 *****************************************************************************/
1799 static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf)
1802 Xil_AssertVoid(Pool != NULL);
1804 for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) {
1805 if (Pool[Index].Buf == Buf) {
1806 if (Pool[Index].Allocated) {
1807 Pool[Index].Allocated = 0;
1813 /*****************************************************************************/
1815 * XDmaPs_Exec_DMAGO - Execute the DMAGO to start a channel.
1817 * @param BaseAddr PL330 device base address
1818 * @param Channel Channel number for the device
1819 * @param DmaProg DMA program starting address, this should be DMA address
1821 * @return 0 on success, -1 on time out
1825 ****************************************************************************/
1826 static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg)
1834 XDmaPs_Instr_DMAGO(DmaGoProg, Channel, DmaProg, 0);
1836 DbgInst0 = XDmaPs_DBGINST0(*(DmaGoProg + 1), *DmaGoProg, 0, 0);
1837 DbgInst1 = (u32)DmaProg;
1839 /* wait while debug status is busy */
1841 while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET)
1842 & XDMAPS_DBGSTATUS_BUSY)
1843 && (WaitCount < XDMAPS_MAX_WAIT)) {
1848 if (WaitCount >= XDMAPS_MAX_WAIT) {
1849 xil_printf("PL330 device at %x debug status busy time out\r\n",
1854 /* write debug instruction 0 */
1855 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0);
1856 /* write debug instruction 1 */
1857 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, DbgInst1);
1860 /* wait while the DMA Manager is busy */
1862 while ((XDmaPs_ReadReg(BaseAddr,
1863 XDMAPS_DS_OFFSET) & XDMAPS_DS_DMA_STATUS)
1864 != XDMAPS_DS_DMA_STATUS_STOPPED
1865 && WaitCount <= XDMAPS_MAX_WAIT) {
1869 if (WaitCount >= XDMAPS_MAX_WAIT) {
1870 xil_printf("PL330 device at %x debug status busy time out\r\n",
1875 /* run the command in DbgInst0 and DbgInst1 */
1876 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0);
1882 /****************************************************************************/
1885 * It's the generic Done ISR.
1886 * @param InstPtr is the DMA instance.
1887 * @param Channel is the DMA channel numer.
1893 *****************************************************************************/
1894 static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel)
1898 XDmaPs_ChannelData *ChanData;
1902 ChanData = InstPtr->Chans + Channel;
1904 /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1905 XDMAPS_INTSTATUS_OFFSET);*/
1907 /* clear the interrupt status */
1908 XDmaPs_WriteReg(InstPtr->Config.BaseAddress,
1909 XDMAPS_INTCLR_OFFSET,
1910 1 << ChanData->ChanId);
1912 /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1913 XDMAPS_INTSTATUS_OFFSET);*/
1916 DmaCmd = ChanData->DmaCmdToHw;
1918 if (!ChanData->HoldDmaProg) {
1919 DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg;
1921 XDmaPs_BufPool_Free(ChanData->ProgBufPool,
1923 DmaCmd->GeneratedDmaProg = NULL;
1926 DmaCmd->DmaStatus = 0;
1927 ChanData->DmaCmdToHw = NULL;
1928 ChanData->DmaCmdFromHw = DmaCmd;
1930 if (ChanData->DoneHandler)
1931 ChanData->DoneHandler(Channel, DmaCmd,
1938 /****************************************************************************/
1940 * Prints the content of the buffer in bytes
1941 * @param Buf is the buffer.
1942 * @param Length is the length of the DMA program.
1947 ****************************************************************************/
1948 static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length)
1951 for (Index = 0; Index < Length; Index++)
1952 xil_printf("[%x] %x\r\n", Index, Buf[Index]);
1955 /****************************************************************************/
1957 * Print the Dma Prog Contents.
1959 * @param Cmd is the command buffer.
1965 *****************************************************************************/
1966 void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd)
1968 if (Cmd->GeneratedDmaProg && Cmd->GeneratedDmaProgLength) {
1969 xil_printf("Generated DMA program (%d):\r\n",
1970 Cmd->GeneratedDmaProgLength);
1971 XDmaPs_Print_DmaProgBuf((char *)Cmd->GeneratedDmaProg,
1972 Cmd->GeneratedDmaProgLength);
1975 if (Cmd->UserDmaProg && Cmd->UserDmaProgLength) {
1976 xil_printf("User defined DMA program (%d):\r\n",
1977 Cmd->UserDmaProgLength);
1978 XDmaPs_Print_DmaProgBuf((char *)Cmd->UserDmaProg,
1979 Cmd->UserDmaProgLength);