1 /*****************************************************************************
3 * (c) Copyright 2009-2013 Xilinx, Inc. All rights reserved.
5 * This file contains confidential and proprietary information of Xilinx, Inc.
6 * and is protected under U.S. and international copyright and other
7 * intellectual property laws.
10 * This disclaimer is not a license and does not grant any rights to the
11 * materials distributed herewith. Except as otherwise provided in a valid
12 * license issued to you by Xilinx, and to the maximum extent permitted by
13 * applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL
14 * FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,
15 * IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
16 * MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE;
17 * and (2) Xilinx shall not be liable (whether in contract or tort, including
18 * negligence, or under any other theory of liability) for any loss or damage
19 * of any kind or nature related to, arising under or in connection with these
20 * materials, including for any direct, or any indirect, special, incidental,
21 * or consequential loss or damage (including loss of data, profits, goodwill,
22 * or any type of loss or damage suffered as a result of any action brought by
23 * a third party) even if such damage or loss was reasonably foreseeable or
24 * Xilinx had been advised of the possibility of the same.
26 * CRITICAL APPLICATIONS
27 * Xilinx products are not designed or intended to be fail-safe, or for use in
28 * any application requiring fail-safe performance, such as life-support or
29 * safety devices or systems, Class III medical devices, nuclear facilities,
30 * applications related to the deployment of airbags, or any other applications
31 * that could lead to death, personal injury, or severe property or
32 * environmental damage (individually and collectively, "Critical
33 * Applications"). Customer assumes the sole risk and liability of any use of
34 * Xilinx products in Critical Applications, subject only to applicable laws
35 * and regulations governing limitations on product liability.
37 * THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE
40 *****************************************************************************/
41 /****************************************************************************/
46 * This file contains the implementation of the interface functions for XDmaPs
47 * driver. Refer to the header file xdmaps.h for more detailed information.
50 * MODIFICATION HISTORY:
52 * Ver Who Date Changes
53 * ----- ------ -------- ----------------------------------------------
54 * 1.00 hbm 08/19/2010 First Release
55 * 1.00 nm 05/25/2011 Updated for minor doxygen corrections
56 * 1.02a sg 05/16/2012 Made changes for doxygen and moved some function
57 * header from the xdmaps.h file to xdmaps.c file
58 * Other cleanup for coding guidelines and CR 657109
60 * 1.03a sg 07/16/2012 changed inline to __inline for CR665681
61 * 1.04a nm 10/22/2012 Fixed CR# 681671.
62 * 1.05a nm 04/15/2013 Fixed CR# 704396. Removed warnings when compiled
63 * with -Wall and -Wextra option in bsp.
64 * 05/01/2013 Fixed CR# 700189. Changed XDmaPs_BuildDmaProg()
65 * function description.
66 * Fixed CR# 704396. Removed unused variables
67 * UseM2MByte & MemBurstLen from XDmaPs_BuildDmaProg()
69 * 1.07a asa 11/02/13. Made changes to fix compilation issues for iarcc.
70 * Removed the PDBG prints. By default they were always
71 * defined out and never used. The PDBG is non-standard for
72 * Xilinx drivers and no other driver does something similar.
73 * Since there is no easy way to fix compilation issues with
74 * the IARCC compiler around PDBG, it is better to remove it.
75 * Users can always use xil_printfs if they want to debug.
78 *****************************************************************************/
80 /***************************** Include Files ********************************/
87 #include "xil_cache.h"
89 #include "xil_printf.h"
92 /************************** Constant Definitions ****************************/
94 /* The following constant defines the amount of error that is allowed for
95 * a specified baud rate. This error is the difference between the actual
96 * baud rate that will be generated using the specified clock and the
100 /**************************** Type Definitions ******************************/
102 /***************** Macros (Inline Functions) Definitions ********************/
105 /************************** Function Prototypes *****************************/
106 static int XDmaPs_Exec_DMAKILL(u32 BaseAddr,
107 unsigned int Channel,
108 unsigned int Thread);
110 static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf);
112 static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg);
114 static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel);
115 static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool);
116 static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd,
117 unsigned CacheLength);
119 static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length);
123 /************************** Variable Definitions ****************************/
125 /****************************************************************************/
128 * Initializes a specific XDmaPs instance such that it is ready to be used.
129 * The data format of the device is setup for 8 data bits, 1 stop bit, and no
130 * parity by default. The baud rate is set to a default value specified by
131 * Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The
132 * receive FIFO threshold is set for 8 bytes. The default operating mode of the
133 * driver is polled mode.
135 * @param InstPtr is a pointer to the XDmaPs instance.
136 * @param Config is a reference to a structure containing information
137 * about a specific XDmaPs driver.
138 * @param EffectiveAddr is the device base address in the virtual memory
139 * address space. The caller is responsible for keeping the
140 * address mapping from EffectiveAddr to the device physical base
141 * address unchanged once this function is invoked. Unexpected
142 * errors may occur if the address mapping changes after this
143 * function is called. If address translation is not used, pass in
144 * the physical address instead.
148 * - XST_SUCCESS on initialization completion
152 *****************************************************************************/
153 int XDmaPs_CfgInitialize(XDmaPs *InstPtr,
154 XDmaPs_Config *Config,
157 int Status = XST_SUCCESS;
158 unsigned int CacheLength = 0;
161 XDmaPs_ChannelData *ChanData;
164 * Assert validates the input arguments
166 Xil_AssertNonvoid(InstPtr != NULL);
167 Xil_AssertNonvoid(Config != NULL);
170 * Setup the driver instance using passed in parameters
172 InstPtr->Config.DeviceId = Config->DeviceId;
173 InstPtr->Config.BaseAddress = EffectiveAddr;
175 CfgReg = XDmaPs_ReadReg(EffectiveAddr, XDMAPS_CR1_OFFSET);
176 CacheLength = CfgReg & XDMAPS_CR1_I_CACHE_LEN_MASK;
177 if (CacheLength < 2 || CacheLength > 5)
180 CacheLength = 1 << CacheLength;
182 InstPtr->CacheLength = CacheLength;
184 memset(InstPtr->Chans, 0,
185 sizeof(XDmaPs_ChannelData[XDMAPS_CHANNELS_PER_DEV]));
187 for (Channel = 0; Channel < XDMAPS_CHANNELS_PER_DEV; Channel++) {
188 ChanData = InstPtr->Chans + Channel;
189 ChanData->ChanId = Channel;
190 ChanData->DevId = Config->DeviceId;
193 InstPtr->IsReady = 1;
198 /****************************************************************************/
201 * Reset the DMA Manager.
203 * @param InstPtr is the DMA instance.
205 * @return 0 on success, -1 on time out
209 *****************************************************************************/
210 int XDmaPs_ResetManager(XDmaPs *InstPtr)
213 Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress,
219 /****************************************************************************/
222 * Reset the specified DMA Channel.
224 * @param InstPtr is the DMA instance.
225 * @param Channel is the channel to be reset.
227 * @return 0 on success, -1 on time out
231 *****************************************************************************/
232 int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel)
235 Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress,
242 /*****************************************************************************/
245 * Driver fault interrupt service routine
246 * This is the one that connects the GIC
248 * @param InstPtr is the DMA instance.
254 ******************************************************************************/
255 void XDmaPs_FaultISR(XDmaPs *InstPtr)
259 u32 Fsm; /* Fault status DMA manager register value */
260 u32 Fsc; /* Fault status DMA channel register value */
261 u32 FaultType; /* Fault type DMA manager register value */
263 u32 BaseAddr = InstPtr->Config.BaseAddress;
265 u32 Pc; /* DMA Pc or channel Pc */
266 XDmaPs_ChannelData *ChanData;
273 Fsm = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSM_OFFSET) & 0x01;
274 Fsc = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSC_OFFSET) & 0xFF;
277 DevId = InstPtr->Config.DeviceId;
281 * if DMA manager is fault
283 FaultType = XDmaPs_ReadReg(BaseAddr, XDMAPS_FTM_OFFSET);
284 Pc = XDmaPs_ReadReg(BaseAddr, XDMAPS_DPC_OFFSET);
286 xil_printf("PL330 device %d fault with type: %x at Pc %x\n",
290 /* kill the DMA manager thread */
291 /* Should we disable interrupt?*/
292 XDmaPs_Exec_DMAKILL(BaseAddr, 0, 0);
296 * check which channel faults and kill the channel thread
299 Chan < XDMAPS_CHANNELS_PER_DEV;
301 if (Fsc & (0x01 << Chan)) {
303 XDmaPs_ReadReg(BaseAddr,
304 XDmaPs_FTCn_OFFSET(Chan));
305 Pc = XDmaPs_ReadReg(BaseAddr,
306 XDmaPs_CPCn_OFFSET(Chan));
308 /* kill the channel thread */
309 /* Should we disable interrupt? */
310 XDmaPs_Exec_DMAKILL(BaseAddr, Chan, 1);
313 * get the fault type and fault Pc and invoke the
316 ChanData = InstPtr->Chans + Chan;
318 DmaCmd = ChanData->DmaCmdToHw;
320 /* Should we check DmaCmd is not null */
321 DmaCmd->DmaStatus = -1;
322 DmaCmd->ChanFaultType = FaultType;
323 DmaCmd->ChanFaultPCAddr = Pc;
324 ChanData->DmaCmdFromHw = DmaCmd;
325 ChanData->DmaCmdToHw = NULL;
327 if (!ChanData->HoldDmaProg) {
328 DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg;
330 XDmaPs_BufPool_Free(ChanData->ProgBufPool,
332 DmaCmd->GeneratedDmaProg = NULL;
335 if (InstPtr->FaultHandler)
336 InstPtr->FaultHandler(Chan,
345 /*****************************************************************************/
348 * Set the done handler for a channel.
350 * @param InstPtr is the DMA instance.
351 * @param Channel is the channel number.
352 * @param DoneHandler is the done interrupt handler.
353 * @param CallbackRef is the callback reference data.
359 ******************************************************************************/
360 int XDmaPs_SetDoneHandler(XDmaPs *InstPtr,
362 XDmaPsDoneHandler DoneHandler,
365 XDmaPs_ChannelData *ChanData;
367 Xil_AssertNonvoid(InstPtr != NULL);
369 if (Channel >= XDMAPS_CHANNELS_PER_DEV)
373 ChanData = InstPtr->Chans + Channel;
375 ChanData->DoneHandler = DoneHandler;
376 ChanData->DoneRef = CallbackRef;
381 /*****************************************************************************/
384 * Set the fault handler for a channel.
386 * @param InstPtr is the DMA instance.
387 * @param FaultHandler is the fault interrupt handler.
388 * @param CallbackRef is the callback reference data.
394 ******************************************************************************/
395 int XDmaPs_SetFaultHandler(XDmaPs *InstPtr,
396 XDmaPsFaultHandler FaultHandler,
399 Xil_AssertNonvoid(InstPtr != NULL);
401 InstPtr->FaultHandler = FaultHandler;
402 InstPtr->FaultRef = CallbackRef;
409 /****************************************************************************/
411 * Construction function for DMAEND instruction. This function fills the program
412 * buffer with the constructed instruction.
414 * @param DmaProg the DMA program buffer, it's the starting address for
415 * the instruction being constructed
417 * @return The number of bytes for this instruction which is 1.
421 *****************************************************************************/
422 __inline int XDmaPs_Instr_DMAEND(char *DmaProg)
434 __inline void XDmaPs_Memcpy4(char *Dst, char *Src)
437 *(Dst + 1) = *(Src + 1);
438 *(Dst + 2) = *(Src + 2);
439 *(Dst + 3) = *(Src + 3);
442 /****************************************************************************/
445 * Construction function for DMAGO instruction. This function fills the program
446 * buffer with the constructed instruction.
448 * @param DmaProg is the DMA program buffer, it's the starting address
449 * for the instruction being constructed
450 * @param Cn is the Channel number, 0 - 7
451 * @param Imm is 32-bit immediate number written to the Channel Program
453 * @param Ns is Non-secure flag. If Ns is 1, the DMA channel operates in
454 * the Non-secure state. If Ns is 0, the execution depends on the
455 * security state of the DMA manager:
456 * DMA manager is in the Secure state, DMA channel operates in the
458 * DMA manager is in the Non-secure state, DMAC aborts.
460 * @return The number of bytes for this instruction which is 6.
464 *****************************************************************************/
465 __inline int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn,
466 u32 Imm, unsigned int Ns)
470 * 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
471 * 0 0 0 0 0 |cn[2:0]| 1 0 1 0 0 0 ns 0
476 *DmaProg = 0xA0 | ((Ns << 1) & 0x02);
478 *(DmaProg + 1) = (u8)(Cn & 0x07);
480 // *((u32 *)(DmaProg + 2)) = Imm;
481 XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm);
487 /****************************************************************************/
490 * Construction function for DMALD instruction. This function fills the program
491 * buffer with the constructed instruction.
493 * @param DmaProg the DMA program buffer, it's the starting address for the
494 * instruction being constructed
496 * @return The number of bytes for this instruction which is 1.
500 *****************************************************************************/
501 __inline int XDmaPs_Instr_DMALD(char *DmaProg)
508 * Note: this driver doesn't support conditional load or store,
509 * so the bs bit is 0 and x bit is 0.
515 /****************************************************************************/
518 * Construction function for DMALP instruction. This function fills the program
519 * buffer with the constructed instruction.
521 * @param DmaProg is the DMA program buffer, it's the starting address
522 * for the instruction being constructed
523 * @param Lc is the Loop counter register, can either be 0 or 1.
524 * @param LoopIterations: the number of interations, LoopInterations - 1
525 * will be encoded in the DMALP instruction.
527 * @return The number of bytes for this instruction which is 2.
531 *****************************************************************************/
532 __inline int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc,
533 unsigned LoopIterations)
537 * 15 ... 8 7 6 5 4 3 2 1 0
538 * | iter[7:0] |0 0 1 0 0 0 lc 0
540 *DmaProg = (u8)(0x20 | ((Lc & 1) << 1));
541 *(DmaProg + 1) = (u8)(LoopIterations - 1);
545 /****************************************************************************/
548 * Construction function for DMALPEND instruction. This function fills the
549 * program buffer with the constructed instruction.
551 * @param DmaProg is the DMA program buffer, it's the starting address
552 * for the instruction being constructed
553 * @param BodyStart is the starting address of the loop body. It is used
554 * to calculate the bytes of backward jump.
555 * @param Lc is the Loop counter register, can either be 0 or 1.
557 * @return The number of bytes for this instruction which is 2.
561 *****************************************************************************/
562 __inline int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc)
566 * 15 ... 8 7 6 5 4 3 2 1 0
567 * | backward_jump[7:0] |0 0 1 nf 1 lc bs x
570 * nf is for loop forever. The driver does not support loop forever,
572 * The driver does not support conditional LPEND, so bs is 0, x is 0.
574 *DmaProg = 0x38 | ((Lc & 1) << 2);
575 *(DmaProg + 1) = (u8)(DmaProg - BodyStart);
581 * Register number for the DMAMOV instruction
583 #define XDMAPS_MOV_SAR 0x0
584 #define XDMAPS_MOV_CCR 0x1
585 #define XDMAPS_MOV_DAR 0x2
587 /****************************************************************************/
590 * Construction function for DMAMOV instruction. This function fills the
591 * program buffer with the constructed instruction.
593 * @param DmaProg is the DMA program buffer, it's the starting address
594 * for the instruction being constructed
595 * @param Rd is the register id, 0 for SAR, 1 for CCR, and 2 for DAR
596 * @param Imm is the 32-bit immediate number
598 * @return The number of bytes for this instruction which is 6.
602 *****************************************************************************/
603 __inline int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm)
607 * 15 4 3 2 1 10 ... 8 7 6 5 4 3 2 1 0
608 * 0 0 0 0 0 |rd[2:0]|1 0 1 1 1 1 0 0
613 * rd: b000 for SAR, b001 CCR, b010 DAR
616 *(DmaProg + 1) = Rd & 0x7;
617 // *((u32 *)(DmaProg + 2)) = Imm;
618 XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm);
623 /****************************************************************************/
626 * Construction function for DMANOP instruction. This function fills the
627 * program buffer with the constructed instruction.
629 * @param DmaProg is the DMA program buffer, it's the starting address
630 * for the instruction being constructed
631 * @return The number of bytes for this instruction which is 1.
635 *****************************************************************************/
636 __inline int XDmaPs_Instr_DMANOP(char *DmaProg)
647 /****************************************************************************/
650 * Construction function for DMARMB instruction. This function fills the
651 * program buffer with the constructed instruction.
653 * @param DmaProg is the DMA program buffer, it's the starting address
654 * for the instruction being constructed
656 * @return The number of bytes for this instruction which is 1.
660 *****************************************************************************/
661 __inline int XDmaPs_Instr_DMARMB(char *DmaProg)
672 /****************************************************************************/
675 * Construction function for DMASEV instruction. This function fills the
676 * program buffer with the constructed instruction.
678 * @param DmaProg is the DMA program buffer, it's the starting address
679 * for the instruction being constructed
680 * @param EventNumber is the Event number to signal.
682 * @return The number of bytes for this instruction which is 2.
686 *****************************************************************************/
687 __inline int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber)
691 * 15 4 3 2 1 10 9 8 7 6 5 4 3 2 1 0
692 * |event[4:0]| 0 0 0 0 0 1 1 0 1 0 0
695 *(DmaProg + 1) = (u8)(EventNumber << 3);
701 /****************************************************************************/
704 * Construction function for DMAST instruction. This function fills the
705 * program buffer with the constructed instruction.
707 * @param DmaProg is the DMA program buffer, it's the starting address
708 * for the instruction being constructed
710 * @return The number of bytes for this instruction which is 1.
714 *****************************************************************************/
715 __inline int XDmaPs_Instr_DMAST(char *DmaProg)
722 * Note: this driver doesn't support conditional load or store,
723 * so the bs bit is 0 and x bit is 0.
730 /****************************************************************************/
733 * Construction function for DMAWMB instruction. This function fills the
734 * program buffer with the constructed instruction.
736 * @param DmaProg is the DMA program buffer, it's the starting address
737 * for the instruction being constructed
739 * @return The number of bytes for this instruction which is 1.
743 *****************************************************************************/
744 __inline int XDmaPs_Instr_DMAWMB(char *DmaProg)
755 /****************************************************************************/
758 * Conversion function from the endian swap size to the bit encoding of the CCR
760 * @param EndianSwapSize is the endian swap size, in terms of bits, it
761 * could be 8, 16, 32, 64, or 128(We are using DMA assembly syntax)
763 * @return The endian swap size bit encoding for the CCR.
767 *****************************************************************************/
768 __inline unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize)
770 switch (EndianSwapSize) {
788 /****************************************************************************/
791 * Conversion function from the burst size to the bit encoding of the CCR
793 * @param BurstSize is the burst size. It's the data width.
794 * In terms of bytes, it could be 1, 2, 4, 8, 16, 32, 64, or 128.
795 * It must be no larger than the bus width.
796 * (We are using DMA assembly syntax.)
800 *****************************************************************************/
801 __inline unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize)
826 /****************************************************************************/
829 * Conversion function from PL330 bus transfer descriptors to CCR value. All the
830 * values passed to the functions are in terms of assembly languages, not in
831 * terms of the register bit encoding.
833 * @param ChanCtrl is the Instance of XDmaPs_ChanCtrl.
835 * @return The 32-bit CCR value.
839 *****************************************************************************/
840 u32 XDmaPs_ToCCRValue(XDmaPs_ChanCtrl *ChanCtrl)
843 * Channel Control Register encoding
844 * [31:28] - endian_swap_size
845 * [27:25] - dst_cache_ctrl
846 * [24:22] - dst_prot_ctrl
847 * [21:18] - dst_burst_len
848 * [17:15] - dst_burst_size
850 * [13:11] - src_cache_ctrl
851 * [10:8] - src_prot_ctrl
852 * [7:4] - src_burst_len
853 * [3:1] - src_burst_size
858 XDmaPs_ToEndianSwapSizeBits(ChanCtrl->EndianSwapSize);
860 unsigned dst_burst_size =
861 XDmaPs_ToBurstSizeBits(ChanCtrl->DstBurstSize);
862 unsigned dst_burst_len = (ChanCtrl->DstBurstLen - 1) & 0x0F;
863 unsigned dst_cache_ctrl = (ChanCtrl->DstCacheCtrl & 0x03)
864 | ((ChanCtrl->DstCacheCtrl & 0x08) >> 1);
865 unsigned dst_prot_ctrl = ChanCtrl->DstProtCtrl & 0x07;
866 unsigned dst_inc_bit = ChanCtrl->DstInc & 1;
868 unsigned src_burst_size =
869 XDmaPs_ToBurstSizeBits(ChanCtrl->SrcBurstSize);
870 unsigned src_burst_len = (ChanCtrl->SrcBurstLen - 1) & 0x0F;
871 unsigned src_cache_ctrl = (ChanCtrl->SrcCacheCtrl & 0x03)
872 | ((ChanCtrl->SrcCacheCtrl & 0x08) >> 1);
873 unsigned src_prot_ctrl = ChanCtrl->SrcProtCtrl & 0x07;
874 unsigned src_inc_bit = ChanCtrl->SrcInc & 1;
876 u32 ccr_value = (es << 28)
877 | (dst_cache_ctrl << 25)
878 | (dst_prot_ctrl << 22)
879 | (dst_burst_len << 18)
880 | (dst_burst_size << 15)
881 | (dst_inc_bit << 14)
882 | (src_cache_ctrl << 11)
883 | (src_prot_ctrl << 8)
884 | (src_burst_len << 4)
885 | (src_burst_size << 1)
891 /****************************************************************************/
893 * Construct a loop with only DMALD and DMAST as the body using loop counter 0.
894 * The function also makes sure the loop body and the lpend is in the same
897 * @param DmaProgStart is the very start address of the DMA program.
898 * This is used to calculate whether the loop is in a cache line.
899 * @param CacheLength is the icache line length, in terms of bytes.
900 * If it's zero, the performance enhancement feature will be
902 * @param DmaProgLoopStart The starting address of the loop (DMALP).
903 * @param LoopCount The inner loop count. Loop count - 1 will be used to
904 * initialize the loop counter.
906 * @return The number of bytes the loop has.
910 *****************************************************************************/
911 int XDmaPs_ConstructSingleLoop(char *DmaProgStart,
913 char *DmaProgLoopStart,
916 int CacheStartOffset;
919 char *DmaProgBuf = DmaProgLoopStart;
921 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCount);
923 if (CacheLength > 0) {
925 * the CacheLength > 0 switch is ued to turn on/off nop
928 CacheStartOffset = DmaProgBuf - DmaProgStart;
929 CacheEndOffset = CacheStartOffset + 3;
932 * check whether the body and lpend fit in one cache line
934 if (CacheStartOffset / CacheLength
935 != CacheEndOffset / CacheLength) {
936 /* insert the nops */
937 NumNops = CacheLength
938 - CacheStartOffset % CacheLength;
941 XDmaPs_Instr_DMANOP(DmaProgBuf);
946 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
947 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
948 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
951 return DmaProgBuf - DmaProgLoopStart;
954 /****************************************************************************/
956 * Construct a nested loop with only DMALD and DMAST in the inner loop body.
957 * It uses loop counter 1 for the outer loop and loop counter 0 for the
960 * @param DmaProgStart is the very start address of the DMA program.
961 * This is used to calculate whether the loop is in a cache line.
962 * @param CacheLength is the icache line length, in terms of bytes.
963 * If it's zero, the performance enhancement feature will be
965 * @param DmaProgLoopStart The starting address of the loop (DMALP).
966 * @param LoopCountOuter The outer loop count. Loop count - 1 will be
967 * used to initialize the loop counter.
968 * @param LoopCountInner The inner loop count. Loop count - 1 will be
969 * used to initialize the loop counter.
971 * @return The number byes the nested loop program has.
975 *****************************************************************************/
976 int XDmaPs_ConstructNestedLoop(char *DmaProgStart,
978 char *DmaProgLoopStart,
979 unsigned int LoopCountOuter,
980 unsigned int LoopCountInner)
982 int CacheStartOffset;
985 char *InnerLoopStart;
986 char *DmaProgBuf = DmaProgLoopStart;
988 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 1, LoopCountOuter);
989 InnerLoopStart = DmaProgBuf;
991 if (CacheLength > 0) {
993 * the CacheLength > 0 switch is ued to turn on/off nop
996 if (CacheLength < 8) {
998 * if the cache line is too small to fit both loops
999 * just align the inner loop
1002 XDmaPs_ConstructSingleLoop(DmaProgStart,
1006 /* outer loop end */
1008 XDmaPs_Instr_DMALPEND(DmaProgBuf,
1013 * the nested loop is constructed for
1014 * smaller cache line
1016 return DmaProgBuf - DmaProgLoopStart;
1020 * Now let's handle the case where a cache line can
1021 * fit the nested loops.
1023 CacheStartOffset = DmaProgBuf - DmaProgStart;
1024 CacheEndOffset = CacheStartOffset + 7;
1027 * check whether the body and lpend fit in one cache line
1029 if (CacheStartOffset / CacheLength
1030 != CacheEndOffset / CacheLength) {
1031 /* insert the nops */
1032 NumNops = CacheLength
1033 - CacheStartOffset % CacheLength;
1036 XDmaPs_Instr_DMANOP(DmaProgBuf);
1041 /* insert the inner DMALP */
1042 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCountInner);
1044 /* DMALD and DMAST instructions */
1045 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
1046 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
1048 /* inner DMALPEND */
1049 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
1051 /* outer DMALPEND */
1052 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
1055 /* return the number of bytes */
1056 return DmaProgBuf - DmaProgLoopStart;
1060 * [31:28] endian_swap_size b0000
1061 * [27:25] dst_cache_ctrl b000
1062 * [24:22] dst_prot_ctrl b000
1063 * [21:18] dst_burst_len b0000
1064 * [17:15] dst_burst_size b000
1066 * [27:25] src_cache_ctrl b000
1067 * [24:22] src_prot_ctrl b000
1068 * [21:18] src_burst_len b0000
1069 * [17:15] src_burst_size b000
1072 #define XDMAPS_CCR_SINGLE_BYTE (0x0)
1073 #define XDMAPS_CCR_M2M_SINGLE_BYTE ((0x1 << 14) | 0x1)
1076 /****************************************************************************/
1079 * Construct the DMA program based on the descriptions of the DMA transfer.
1080 * The function handles memory to memory DMA transfers.
1081 * It also handles unalgined head and small amount of residue tail.
1083 * @param Channel DMA channel number
1084 * @param Cmd is the DMA command.
1085 * @param CacheLength is the icache line length, in terms of bytes.
1086 * If it's zero, the performance enhancement feature will be
1089 * @returns The number of bytes for the program.
1093 *****************************************************************************/
1094 static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd,
1095 unsigned CacheLength)
1100 char *DmaProgBuf = (char *)Cmd->GeneratedDmaProg;
1101 unsigned DevChan = Channel;
1102 unsigned long DmaLength = Cmd->BD.Length;
1103 u32 SrcAddr = Cmd->BD.SrcAddr;
1105 unsigned SrcInc = Cmd->ChanCtrl.SrcInc;
1106 u32 DstAddr = Cmd->BD.DstAddr;
1107 unsigned DstInc = Cmd->ChanCtrl.DstInc;
1109 char *DmaProgStart = DmaProgBuf;
1111 unsigned int BurstBytes;
1112 unsigned int LoopCount;
1113 unsigned int LoopCount1 = 0;
1114 unsigned int LoopResidue = 0;
1115 unsigned int TailBytes;
1116 unsigned int TailWords;
1119 unsigned int Unaligned;
1120 unsigned int UnalignedCount;
1121 unsigned int MemBurstSize = 1;
1124 unsigned int SrcUnaligned = 0;
1125 unsigned int DstUnaligned = 0;
1127 XDmaPs_ChanCtrl *ChanCtrl;
1128 XDmaPs_ChanCtrl WordChanCtrl;
1129 static XDmaPs_ChanCtrl Mem2MemByteCC;
1131 Mem2MemByteCC.EndianSwapSize = 0;
1132 Mem2MemByteCC.DstCacheCtrl = 0;
1133 Mem2MemByteCC.DstProtCtrl = 0;
1134 Mem2MemByteCC.DstBurstLen = 1;
1135 Mem2MemByteCC.DstBurstSize = 1;
1136 Mem2MemByteCC.DstInc = 1;
1137 Mem2MemByteCC.SrcCacheCtrl = 0;
1138 Mem2MemByteCC.SrcProtCtrl = 0;
1139 Mem2MemByteCC.SrcBurstLen = 1;
1140 Mem2MemByteCC.SrcBurstSize = 1;
1141 Mem2MemByteCC.SrcInc = 1;
1143 ChanCtrl = &Cmd->ChanCtrl;
1145 /* insert DMAMOV for SAR and DAR */
1146 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1149 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1154 if (ChanCtrl->SrcInc)
1155 SrcUnaligned = SrcAddr % ChanCtrl->SrcBurstSize;
1157 if (ChanCtrl->DstInc)
1158 DstUnaligned = DstAddr % ChanCtrl->DstBurstSize;
1160 if ((SrcUnaligned && DstInc) || (DstUnaligned && SrcInc)) {
1161 ChanCtrl = &Mem2MemByteCC;
1164 if (ChanCtrl->SrcInc) {
1165 MemBurstSize = ChanCtrl->SrcBurstSize;
1168 } else if (ChanCtrl->DstInc) {
1169 MemBurstSize = ChanCtrl->DstBurstSize;
1173 /* check whether the head is aligned or not */
1174 Unaligned = MemAddr % MemBurstSize;
1177 /* if head is unaligned, transfer head in bytes */
1178 UnalignedCount = MemBurstSize - Unaligned;
1179 CCRValue = XDMAPS_CCR_SINGLE_BYTE
1181 | ((DstInc & 1) << 14);
1183 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1187 for (Index = 0; Index < UnalignedCount; Index++) {
1188 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
1189 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
1192 DmaLength -= UnalignedCount;
1195 /* now the burst transfer part */
1196 CCRValue = XDmaPs_ToCCRValue(ChanCtrl);
1197 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1201 BurstBytes = ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen;
1203 LoopCount = DmaLength / BurstBytes;
1204 TailBytes = DmaLength % BurstBytes;
1207 * the loop count register is 8-bit wide, so if we need
1208 * a larger loop, we need to have nested loops
1210 if (LoopCount > 256) {
1211 LoopCount1 = LoopCount / 256;
1212 if (LoopCount1 > 256) {
1213 xil_printf("DMA operation cannot fit in a 2-level "
1214 "loop for channel %d, please reduce the "
1215 "DMA length or increase the burst size or "
1220 LoopResidue = LoopCount % 256;
1224 XDmaPs_ConstructNestedLoop(DmaProgStart,
1231 XDmaPs_ConstructSingleLoop(DmaProgStart,
1236 /* there will be some that cannot be covered by
1239 LoopCount = LoopResidue;
1242 if (LoopCount > 0) {
1243 DmaProgBuf += XDmaPs_ConstructSingleLoop(DmaProgStart,
1250 /* handle the tail */
1251 TailWords = TailBytes / MemBurstSize;
1252 TailBytes = TailBytes % MemBurstSize;
1255 WordChanCtrl = *ChanCtrl;
1257 * if we can transfer the tail in words, we will
1258 * transfer words as much as possible
1260 WordChanCtrl.SrcBurstSize = MemBurstSize;
1261 WordChanCtrl.SrcBurstLen = 1;
1262 WordChanCtrl.DstBurstSize = MemBurstSize;
1263 WordChanCtrl.DstBurstLen = 1;
1267 * the burst length is 1
1269 CCRValue = XDmaPs_ToCCRValue(&WordChanCtrl);
1272 XDmaPs_Instr_DMAMOV(DmaProgBuf,
1276 XDmaPs_ConstructSingleLoop(DmaProgStart,
1285 * for the rest, we'll tranfer in bytes
1288 * So far just to be safe, the tail bytes
1289 * are transfered in a loop. We can optimize a little
1290 * to perform a burst.
1292 CCRValue = XDMAPS_CCR_SINGLE_BYTE
1294 | ((DstInc & 1) << 14);
1297 XDmaPs_Instr_DMAMOV(DmaProgBuf,
1302 XDmaPs_ConstructSingleLoop(DmaProgStart,
1310 DmaProgBuf += XDmaPs_Instr_DMASEV(DmaProgBuf, DevChan);
1311 DmaProgBuf += XDmaPs_Instr_DMAEND(DmaProgBuf);
1313 DmaProgBytes = DmaProgBuf - DmaProgStart;
1315 Xil_DCacheFlushRange((u32)DmaProgStart, DmaProgBytes);
1317 return DmaProgBytes;
1322 /****************************************************************************/
1325 * Generate a DMA program based for the DMA command, the buffer will be pointed
1326 * by the GeneratedDmaProg field of the command.
1328 * @param InstPtr is then DMA instance.
1329 * @param Channel is the DMA channel number.
1330 * @param Cmd is the DMA command.
1332 * @return - XST_SUCCESS on success.
1333 * - XST_FAILURE if it fails
1337 *****************************************************************************/
1338 int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd)
1342 XDmaPs_ChannelData *ChanData;
1343 XDmaPs_ChanCtrl *ChanCtrl;
1345 Xil_AssertNonvoid(InstPtr != NULL);
1346 Xil_AssertNonvoid(Cmd != NULL);
1349 if (Channel > XDMAPS_CHANNELS_PER_DEV)
1352 ChanData = InstPtr->Chans + Channel;
1353 ChanCtrl = &Cmd->ChanCtrl;
1355 if (ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen
1356 != ChanCtrl->DstBurstSize * ChanCtrl->DstBurstLen) {
1357 xil_printf("source burst_size * burst_len does not match "
1358 "that of destination\r\n");
1364 * unaligned fixed address is not supported
1366 if (!ChanCtrl->SrcInc && Cmd->BD.SrcAddr % ChanCtrl->SrcBurstSize) {
1367 xil_printf("source address is fixed but is unaligned\r\n");
1371 if (!ChanCtrl->DstInc && Cmd->BD.DstAddr % ChanCtrl->DstBurstSize) {
1372 xil_printf("destination address is fixed but is "
1377 Buf = XDmaPs_BufPool_Allocate(ChanData->ProgBufPool);
1379 xil_printf("failed to allocate program buffer\r\n");
1383 Cmd->GeneratedDmaProg = Buf;
1384 ProgLen = XDmaPs_BuildDmaProg(Channel, Cmd,
1385 InstPtr->CacheLength);
1386 Cmd->GeneratedDmaProgLength = ProgLen;
1390 XDmaPs_Print_DmaProg(Cmd);
1394 /* something wrong, release the buffer */
1395 XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf);
1396 Cmd->GeneratedDmaProgLength = 0;
1397 Cmd->GeneratedDmaProg = NULL;
1405 /****************************************************************************/
1407 * Free the DMA program buffer that is pointed by the GeneratedDmaProg field
1410 * @param InstPtr is then DMA instance.
1411 * @param Channel is the DMA channel number.
1412 * @param Cmd is the DMA command.
1414 * @return XST_SUCCESS on success.
1415 * XST_FAILURE if there is any error.
1419 ****************************************************************************/
1420 int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd)
1424 XDmaPs_ChannelData *ChanData;
1426 Xil_AssertNonvoid(InstPtr != NULL);
1427 Xil_AssertNonvoid(Cmd != NULL);
1429 if (Channel > XDMAPS_CHANNELS_PER_DEV)
1432 Buf = (void *)Cmd->GeneratedDmaProg;
1433 ChanData = InstPtr->Chans + Channel;
1436 XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf);
1437 Cmd->GeneratedDmaProg = 0;
1438 Cmd->GeneratedDmaProgLength = 0;
1445 /****************************************************************************/
1448 * Start a DMA command. The command can only be invoked when the channel
1449 * is idle. The driver takes the command, generates DMA program if needed,
1450 * then pass the program to DMAC to execute.
1452 * @param InstPtr is then DMA instance.
1453 * @param Channel is the DMA channel number.
1454 * @param Cmd is the DMA command.
1455 * @param HoldDmaProg is tag indicating whether the driver can release
1456 * the allocated DMA buffer or not. If a user wants to examine the
1457 * generated DMA program, the flag should be set to 1. After the
1458 * DMA program is finished, a user needs to explicity free the
1462 * - XST_SUCCESS on success
1463 * - XST_DEVICE_BUSY if DMA is busy
1464 * - XST_FAILURE on other failures
1468 ****************************************************************************/
1469 int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel,
1477 Xil_AssertNonvoid(InstPtr != NULL);
1478 Xil_AssertNonvoid(Cmd != NULL);
1481 Cmd->DmaStatus = XST_FAILURE;
1483 if (XDmaPs_IsActive(InstPtr, Channel))
1484 return XST_DEVICE_BUSY;
1486 if (!Cmd->UserDmaProg && !Cmd->GeneratedDmaProg) {
1487 Status = XDmaPs_GenDmaProg(InstPtr, Channel, Cmd);
1492 InstPtr->Chans[Channel].HoldDmaProg = HoldDmaProg;
1494 if (Cmd->UserDmaProg)
1495 DmaProg = (u32)Cmd->UserDmaProg;
1496 else if (Cmd->GeneratedDmaProg)
1497 DmaProg = (u32)Cmd->GeneratedDmaProg;
1500 /* enable the interrupt */
1501 Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1502 XDMAPS_INTEN_OFFSET);
1503 Inten |= 0x01 << Channel; /* set the correpsonding bit */
1504 XDmaPs_WriteReg(InstPtr->Config.BaseAddress,
1505 XDMAPS_INTEN_OFFSET,
1507 Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1508 XDMAPS_INTEN_OFFSET);
1510 InstPtr->Chans[Channel].DmaCmdToHw = Cmd;
1512 if (Cmd->ChanCtrl.SrcInc) {
1513 Xil_DCacheFlushRange(Cmd->BD.SrcAddr, Cmd->BD.Length);
1515 if (Cmd->ChanCtrl.DstInc) {
1516 Xil_DCacheInvalidateRange(Cmd->BD.DstAddr,
1520 Status = XDmaPs_Exec_DMAGO(InstPtr->Config.BaseAddress,
1524 InstPtr->Chans[Channel].DmaCmdToHw = NULL;
1525 Status = XST_FAILURE;
1531 /****************************************************************************/
1534 * Checks whether the DMA channel is active or idle.
1536 * @param InstPtr is the DMA instance.
1537 * @param Channel is the DMA channel number.
1539 * @return 0: if the channel is idle
1544 *****************************************************************************/
1545 int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel)
1547 Xil_AssertNonvoid(InstPtr != NULL);
1549 /* Need to assert Channel is in range */
1550 if (Channel > XDMAPS_CHANNELS_PER_DEV)
1553 return InstPtr->Chans[Channel].DmaCmdToHw != NULL;
1558 /****************************************************************************/
1561 * Allocate a buffer of the DMA program buffer from the pool.
1563 * @param Pool the DMA program pool.
1565 * @return The allocated buffer, NULL if there is any error.
1569 *****************************************************************************/
1570 static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool)
1574 Xil_AssertNonvoid(Pool != NULL);
1576 for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) {
1577 if (!Pool[Index].Allocated) {
1578 Pool[Index].Allocated = 1;
1579 return Pool[Index].Buf;
1587 /*****************************************************************************/
1590 * Driver done interrupt service routine for channel 0. We need this done ISR
1591 * mainly because the driver needs to release the DMA program buffer.
1592 * This is the one that connects the GIC
1594 * @param InstPtr is the DMA instance.
1600 ******************************************************************************/
1601 void XDmaPs_DoneISR_0(XDmaPs *InstPtr)
1603 XDmaPs_DoneISR_n(InstPtr, 0);
1606 /*****************************************************************************/
1609 * Driver done interrupt service routine for channel 1. We need this done ISR
1610 * mainly because the driver needs to release the DMA program buffer.
1611 * This is the one that connects the GIC
1613 * @param InstPtr is the DMA instance.
1619 ******************************************************************************/
1620 void XDmaPs_DoneISR_1(XDmaPs *InstPtr)
1622 XDmaPs_DoneISR_n(InstPtr, 1);
1625 /*****************************************************************************/
1628 * Driver done interrupt service routine for channel 2. We need this done ISR
1629 * mainly because the driver needs to release the DMA program buffer.
1630 * This is the one that connects the GIC
1632 * @param InstPtr is the DMA instance.
1638 ******************************************************************************/
1639 void XDmaPs_DoneISR_2(XDmaPs *InstPtr)
1641 XDmaPs_DoneISR_n(InstPtr, 2);
1644 /*****************************************************************************/
1647 * Driver done interrupt service routine for channel 3. We need this done ISR
1648 * mainly because the driver needs to release the DMA program buffer.
1649 * This is the one that connects the GIC
1651 * @param InstPtr is the DMA instance.
1657 ******************************************************************************/
1658 void XDmaPs_DoneISR_3(XDmaPs *InstPtr)
1660 XDmaPs_DoneISR_n(InstPtr, 3);
1663 /*****************************************************************************/
1666 * Driver done interrupt service routine for channel 4. We need this done ISR
1667 * mainly because the driver needs to release the DMA program buffer.
1668 * This is the one that connects the GIC
1670 * @param InstPtr is the DMA instance.
1676 ******************************************************************************/
1677 void XDmaPs_DoneISR_4(XDmaPs *InstPtr)
1679 XDmaPs_DoneISR_n(InstPtr, 4);
1682 /*****************************************************************************/
1685 * Driver done interrupt service routine for channel 5. We need this done ISR
1686 * mainly because the driver needs to release the DMA program buffer.
1687 * This is the one that connects the GIC
1689 * @param InstPtr is the DMA instance.
1695 ******************************************************************************/
1696 void XDmaPs_DoneISR_5(XDmaPs *InstPtr)
1698 XDmaPs_DoneISR_n(InstPtr, 5);
1701 /*****************************************************************************/
1704 * Driver done interrupt service routine for channel 6. We need this done ISR
1705 * mainly because the driver needs to release the DMA program buffer.
1706 * This is the one that connects the GIC
1708 * @param InstPtr is the DMA instance.
1714 ******************************************************************************/
1715 void XDmaPs_DoneISR_6(XDmaPs *InstPtr)
1717 XDmaPs_DoneISR_n(InstPtr, 6);
1720 /*****************************************************************************/
1723 * Driver done interrupt service routine for channel 7. We need this done ISR
1724 * mainly because the driver needs to release the DMA program buffer.
1725 * This is the one that connects the GIC
1727 * @param InstPtr is the DMA instance.
1733 ******************************************************************************/
1734 void XDmaPs_DoneISR_7(XDmaPs *InstPtr)
1736 XDmaPs_DoneISR_n(InstPtr, 7);
1739 #ifndef XDMAPS_MAX_WAIT
1740 #define XDMAPS_MAX_WAIT 4000
1743 /****************************************************************************/
1745 * Use the debug registers to kill the DMA thread.
1747 * @param BaseAddr is DMA device base address.
1748 * @param Channel is the DMA channel number.
1749 * @param Thread is Debug thread encoding.
1750 * 0: DMA manager thread, 1: DMA channel.
1752 * @return 0 on success, -1 on time out
1756 *****************************************************************************/
1757 static int XDmaPs_Exec_DMAKILL(u32 BaseAddr,
1758 unsigned int Channel,
1759 unsigned int Thread)
1764 DbgInst0 = XDmaPs_DBGINST0(0, 0x01, Channel, Thread);
1766 /* wait while debug status is busy */
1768 while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET)
1769 & XDMAPS_DBGSTATUS_BUSY)
1770 && (WaitCount < XDMAPS_MAX_WAIT))
1773 if (WaitCount >= XDMAPS_MAX_WAIT) {
1775 xil_printf("PL330 device at %x debug status busy time out\n",
1781 /* write debug instruction 0 */
1782 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0);
1784 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, 0);
1787 /* run the command in DbgInst0 and DbgInst1 */
1788 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0);
1793 /****************************************************************************/
1797 * Free a buffer of the DMA program buffer.
1798 * @param Pool the DMA program pool.
1799 * @param Buf the DMA program buffer to be release.
1805 *****************************************************************************/
1806 static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf)
1809 Xil_AssertVoid(Pool != NULL);
1811 for (Index = 0; Index < XDMAPS_MAX_CHAN_BUFS; Index++) {
1812 if (Pool[Index].Buf == Buf) {
1813 if (Pool[Index].Allocated) {
1814 Pool[Index].Allocated = 0;
1820 /*****************************************************************************/
1822 * XDmaPs_Exec_DMAGO - Execute the DMAGO to start a channel.
1824 * @param BaseAddr PL330 device base address
1825 * @param Channel Channel number for the device
1826 * @param DmaProg DMA program starting address, this should be DMA address
1828 * @return 0 on success, -1 on time out
1832 ****************************************************************************/
1833 static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg)
1841 XDmaPs_Instr_DMAGO(DmaGoProg, Channel, DmaProg, 0);
1843 DbgInst0 = XDmaPs_DBGINST0(*(DmaGoProg + 1), *DmaGoProg, 0, 0);
1844 DbgInst1 = (u32)DmaProg;
1846 /* wait while debug status is busy */
1848 while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET)
1849 & XDMAPS_DBGSTATUS_BUSY)
1850 && (WaitCount < XDMAPS_MAX_WAIT)) {
1855 if (WaitCount >= XDMAPS_MAX_WAIT) {
1856 xil_printf("PL330 device at %x debug status busy time out\r\n",
1861 /* write debug instruction 0 */
1862 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0);
1863 /* write debug instruction 1 */
1864 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, DbgInst1);
1867 /* wait while the DMA Manager is busy */
1869 while ((XDmaPs_ReadReg(BaseAddr,
1870 XDMAPS_DS_OFFSET) & XDMAPS_DS_DMA_STATUS)
1871 != XDMAPS_DS_DMA_STATUS_STOPPED
1872 && WaitCount <= XDMAPS_MAX_WAIT) {
1876 if (WaitCount >= XDMAPS_MAX_WAIT) {
1877 xil_printf("PL330 device at %x debug status busy time out\r\n",
1882 /* run the command in DbgInst0 and DbgInst1 */
1883 XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0);
1889 /****************************************************************************/
1892 * It's the generic Done ISR.
1893 * @param InstPtr is the DMA instance.
1894 * @param Channel is the DMA channel numer.
1900 *****************************************************************************/
1901 static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel)
1905 XDmaPs_ChannelData *ChanData;
1909 ChanData = InstPtr->Chans + Channel;
1911 /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1912 XDMAPS_INTSTATUS_OFFSET);*/
1914 /* clear the interrupt status */
1915 XDmaPs_WriteReg(InstPtr->Config.BaseAddress,
1916 XDMAPS_INTCLR_OFFSET,
1917 1 << ChanData->ChanId);
1919 /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1920 XDMAPS_INTSTATUS_OFFSET);*/
1923 if ((DmaCmd = ChanData->DmaCmdToHw)) {
1924 if (!ChanData->HoldDmaProg) {
1925 DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg;
1927 XDmaPs_BufPool_Free(ChanData->ProgBufPool,
1929 DmaCmd->GeneratedDmaProg = NULL;
1932 DmaCmd->DmaStatus = 0;
1933 ChanData->DmaCmdToHw = NULL;
1934 ChanData->DmaCmdFromHw = DmaCmd;
1936 if (ChanData->DoneHandler)
1937 ChanData->DoneHandler(Channel, DmaCmd,
1944 /****************************************************************************/
1946 * Prints the content of the buffer in bytes
1947 * @param Buf is the buffer.
1948 * @param Length is the length of the DMA program.
1953 ****************************************************************************/
1954 static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length)
1957 for (Index = 0; Index < Length; Index++)
1958 xil_printf("[%x] %x\r\n", Index, Buf[Index]);
1961 /****************************************************************************/
1963 * Print the Dma Prog Contents.
1965 * @param Cmd is the command buffer.
1971 *****************************************************************************/
1972 void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd)
1974 if (Cmd->GeneratedDmaProg && Cmd->GeneratedDmaProgLength) {
1975 xil_printf("Generated DMA program (%d):\r\n",
1976 Cmd->GeneratedDmaProgLength);
1977 XDmaPs_Print_DmaProgBuf((char *)Cmd->GeneratedDmaProg,
1978 Cmd->GeneratedDmaProgLength);
1981 if (Cmd->UserDmaProg && Cmd->UserDmaProgLength) {
1982 xil_printf("User defined DMA program (%d):\r\n",
1983 Cmd->UserDmaProgLength);
1984 XDmaPs_Print_DmaProgBuf((char *)Cmd->UserDmaProg,
1985 Cmd->UserDmaProgLength);