1 /******************************************************************************
3 * Copyright (C) 2009 - 2014 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_0
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.
71 *****************************************************************************/
73 /***************************** Include Files ********************************/
80 #include "xil_cache.h"
82 #include "xil_printf.h"
85 /************************** Constant Definitions ****************************/
87 /* The following constant defines the amount of error that is allowed for
88 * a specified baud rate. This error is the difference between the actual
89 * baud rate that will be generated using the specified clock and the
93 /**************************** Type Definitions ******************************/
95 /***************** Macros (Inline Functions) Definitions ********************/
98 /************************** Function Prototypes *****************************/
99 static int XDmaPs_Exec_DMAKILL(u32 BaseAddr,
100 unsigned int Channel,
101 unsigned int Thread);
103 static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf);
105 static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg);
107 static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel);
108 static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool);
109 static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd,
110 unsigned CacheLength);
112 static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length);
116 /************************** Variable Definitions ****************************/
118 /****************************************************************************/
121 * Initializes a specific XDmaPs instance such that it is ready to be used.
122 * The data format of the device is setup for 8 data bits, 1 stop bit, and no
123 * parity by default. The baud rate is set to a default value specified by
124 * Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The
125 * receive FIFO threshold is set for 8 bytes. The default operating mode of the
126 * driver is polled mode.
128 * @param InstPtr is a pointer to the XDmaPs instance.
129 * @param Config is a reference to a structure containing information
130 * about a specific XDmaPs driver.
131 * @param EffectiveAddr is the device base address in the virtual memory
132 * address space. The caller is responsible for keeping the
133 * address mapping from EffectiveAddr to the device physical base
134 * address unchanged once this function is invoked. Unexpected
135 * errors may occur if the address mapping changes after this
136 * function is called. If address translation is not used, pass in
137 * the physical address instead.
141 * - XST_SUCCESS on initialization completion
145 *****************************************************************************/
146 int XDmaPs_CfgInitialize(XDmaPs *InstPtr,
147 XDmaPs_Config *Config,
150 int Status = XST_SUCCESS;
151 unsigned int CacheLength = 0;
154 XDmaPs_ChannelData *ChanData;
157 * Assert validates the input arguments
159 Xil_AssertNonvoid(InstPtr != NULL);
160 Xil_AssertNonvoid(Config != NULL);
163 * Setup the driver instance using passed in parameters
165 InstPtr->Config.DeviceId = Config->DeviceId;
166 InstPtr->Config.BaseAddress = EffectiveAddr;
168 CfgReg = XDmaPs_ReadReg(EffectiveAddr, XDMAPS_CR1_OFFSET);
169 CacheLength = CfgReg & XDMAPS_CR1_I_CACHE_LEN_MASK;
170 if (CacheLength < 2 || CacheLength > 5)
173 CacheLength = 1 << CacheLength;
175 InstPtr->CacheLength = CacheLength;
177 memset(InstPtr->Chans, 0,
178 sizeof(XDmaPs_ChannelData[XDMAPS_CHANNELS_PER_DEV]));
180 for (Channel = 0; Channel < XDMAPS_CHANNELS_PER_DEV; Channel++) {
181 ChanData = InstPtr->Chans + Channel;
182 ChanData->ChanId = Channel;
183 ChanData->DevId = Config->DeviceId;
186 InstPtr->IsReady = 1;
191 /****************************************************************************/
194 * Reset the DMA Manager.
196 * @param InstPtr is the DMA instance.
198 * @return 0 on success, -1 on time out
202 *****************************************************************************/
203 int XDmaPs_ResetManager(XDmaPs *InstPtr)
206 Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress,
212 /****************************************************************************/
215 * Reset the specified DMA Channel.
217 * @param InstPtr is the DMA instance.
218 * @param Channel is the channel to be reset.
220 * @return 0 on success, -1 on time out
224 *****************************************************************************/
225 int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel)
228 Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress,
235 /*****************************************************************************/
238 * Driver fault interrupt service routine
239 * This is the one that connects the GIC
241 * @param InstPtr is the DMA instance.
247 ******************************************************************************/
248 void XDmaPs_FaultISR(XDmaPs *InstPtr)
252 u32 Fsm; /* Fault status DMA manager register value */
253 u32 Fsc; /* Fault status DMA channel register value */
254 u32 FaultType; /* Fault type DMA manager register value */
256 u32 BaseAddr = InstPtr->Config.BaseAddress;
258 u32 Pc; /* DMA Pc or channel Pc */
259 XDmaPs_ChannelData *ChanData;
266 Fsm = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSM_OFFSET) & 0x01;
267 Fsc = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSC_OFFSET) & 0xFF;
270 DevId = InstPtr->Config.DeviceId;
274 * if DMA manager is fault
276 FaultType = XDmaPs_ReadReg(BaseAddr, XDMAPS_FTM_OFFSET);
277 Pc = XDmaPs_ReadReg(BaseAddr, XDMAPS_DPC_OFFSET);
279 xil_printf("PL330 device %d fault with type: %x at Pc %x\n",
283 /* kill the DMA manager thread */
284 /* Should we disable interrupt?*/
285 XDmaPs_Exec_DMAKILL(BaseAddr, 0, 0);
289 * check which channel faults and kill the channel thread
292 Chan < XDMAPS_CHANNELS_PER_DEV;
294 if (Fsc & (0x01 << Chan)) {
296 XDmaPs_ReadReg(BaseAddr,
297 XDmaPs_FTCn_OFFSET(Chan));
298 Pc = XDmaPs_ReadReg(BaseAddr,
299 XDmaPs_CPCn_OFFSET(Chan));
301 /* kill the channel thread */
302 /* Should we disable interrupt? */
303 XDmaPs_Exec_DMAKILL(BaseAddr, Chan, 1);
306 * get the fault type and fault Pc and invoke the
309 ChanData = InstPtr->Chans + Chan;
311 DmaCmd = ChanData->DmaCmdToHw;
313 /* Should we check DmaCmd is not null */
314 DmaCmd->DmaStatus = -1;
315 DmaCmd->ChanFaultType = FaultType;
316 DmaCmd->ChanFaultPCAddr = Pc;
317 ChanData->DmaCmdFromHw = DmaCmd;
318 ChanData->DmaCmdToHw = NULL;
320 if (!ChanData->HoldDmaProg) {
321 DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg;
323 XDmaPs_BufPool_Free(ChanData->ProgBufPool,
325 DmaCmd->GeneratedDmaProg = NULL;
328 if (InstPtr->FaultHandler)
329 InstPtr->FaultHandler(Chan,
338 /*****************************************************************************/
341 * Set the done handler for a channel.
343 * @param InstPtr is the DMA instance.
344 * @param Channel is the channel number.
345 * @param DoneHandler is the done interrupt handler.
346 * @param CallbackRef is the callback reference data.
352 ******************************************************************************/
353 int XDmaPs_SetDoneHandler(XDmaPs *InstPtr,
355 XDmaPsDoneHandler DoneHandler,
358 XDmaPs_ChannelData *ChanData;
360 Xil_AssertNonvoid(InstPtr != NULL);
362 if (Channel >= XDMAPS_CHANNELS_PER_DEV)
366 ChanData = InstPtr->Chans + Channel;
368 ChanData->DoneHandler = DoneHandler;
369 ChanData->DoneRef = CallbackRef;
374 /*****************************************************************************/
377 * Set the fault handler for a channel.
379 * @param InstPtr is the DMA instance.
380 * @param FaultHandler is the fault interrupt handler.
381 * @param CallbackRef is the callback reference data.
387 ******************************************************************************/
388 int XDmaPs_SetFaultHandler(XDmaPs *InstPtr,
389 XDmaPsFaultHandler FaultHandler,
392 Xil_AssertNonvoid(InstPtr != NULL);
394 InstPtr->FaultHandler = FaultHandler;
395 InstPtr->FaultRef = CallbackRef;
402 /****************************************************************************/
404 * Construction function for DMAEND instruction. This function fills the program
405 * buffer with the constructed instruction.
407 * @param DmaProg the DMA program buffer, it's the starting address for
408 * the instruction being constructed
410 * @return The number of bytes for this instruction which is 1.
414 *****************************************************************************/
415 __inline int XDmaPs_Instr_DMAEND(char *DmaProg)
427 __inline void XDmaPs_Memcpy4(char *Dst, char *Src)
430 *(Dst + 1) = *(Src + 1);
431 *(Dst + 2) = *(Src + 2);
432 *(Dst + 3) = *(Src + 3);
435 /****************************************************************************/
438 * Construction function for DMAGO instruction. This function fills the program
439 * buffer with the constructed instruction.
441 * @param DmaProg is the DMA program buffer, it's the starting address
442 * for the instruction being constructed
443 * @param Cn is the Channel number, 0 - 7
444 * @param Imm is 32-bit immediate number written to the Channel Program
446 * @param Ns is Non-secure flag. If Ns is 1, the DMA channel operates in
447 * the Non-secure state. If Ns is 0, the execution depends on the
448 * security state of the DMA manager:
449 * DMA manager is in the Secure state, DMA channel operates in the
451 * DMA manager is in the Non-secure state, DMAC aborts.
453 * @return The number of bytes for this instruction which is 6.
457 *****************************************************************************/
458 __inline int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn,
459 u32 Imm, unsigned int Ns)
463 * 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
464 * 0 0 0 0 0 |cn[2:0]| 1 0 1 0 0 0 ns 0
469 *DmaProg = 0xA0 | ((Ns << 1) & 0x02);
471 *(DmaProg + 1) = (u8)(Cn & 0x07);
473 // *((u32 *)(DmaProg + 2)) = Imm;
474 XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm);
480 /****************************************************************************/
483 * Construction function for DMALD instruction. This function fills the program
484 * buffer with the constructed instruction.
486 * @param DmaProg the DMA program buffer, it's the starting address for the
487 * instruction being constructed
489 * @return The number of bytes for this instruction which is 1.
493 *****************************************************************************/
494 __inline int XDmaPs_Instr_DMALD(char *DmaProg)
501 * Note: this driver doesn't support conditional load or store,
502 * so the bs bit is 0 and x bit is 0.
508 /****************************************************************************/
511 * Construction function for DMALP instruction. This function fills the program
512 * buffer with the constructed instruction.
514 * @param DmaProg is the DMA program buffer, it's the starting address
515 * for the instruction being constructed
516 * @param Lc is the Loop counter register, can either be 0 or 1.
517 * @param LoopIterations: the number of interations, LoopInterations - 1
518 * will be encoded in the DMALP instruction.
520 * @return The number of bytes for this instruction which is 2.
524 *****************************************************************************/
525 __inline int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc,
526 unsigned LoopIterations)
530 * 15 ... 8 7 6 5 4 3 2 1 0
531 * | iter[7:0] |0 0 1 0 0 0 lc 0
533 *DmaProg = (u8)(0x20 | ((Lc & 1) << 1));
534 *(DmaProg + 1) = (u8)(LoopIterations - 1);
538 /****************************************************************************/
541 * Construction function for DMALPEND instruction. This function fills the
542 * program buffer with the constructed instruction.
544 * @param DmaProg is the DMA program buffer, it's the starting address
545 * for the instruction being constructed
546 * @param BodyStart is the starting address of the loop body. It is used
547 * to calculate the bytes of backward jump.
548 * @param Lc is the Loop counter register, can either be 0 or 1.
550 * @return The number of bytes for this instruction which is 2.
554 *****************************************************************************/
555 __inline int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc)
559 * 15 ... 8 7 6 5 4 3 2 1 0
560 * | backward_jump[7:0] |0 0 1 nf 1 lc bs x
563 * nf is for loop forever. The driver does not support loop forever,
565 * The driver does not support conditional LPEND, so bs is 0, x is 0.
567 *DmaProg = 0x38 | ((Lc & 1) << 2);
568 *(DmaProg + 1) = (u8)(DmaProg - BodyStart);
574 * Register number for the DMAMOV instruction
576 #define XDMAPS_MOV_SAR 0x0
577 #define XDMAPS_MOV_CCR 0x1
578 #define XDMAPS_MOV_DAR 0x2
580 /****************************************************************************/
583 * Construction function for DMAMOV instruction. This function fills the
584 * program buffer with the constructed instruction.
586 * @param DmaProg is the DMA program buffer, it's the starting address
587 * for the instruction being constructed
588 * @param Rd is the register id, 0 for SAR, 1 for CCR, and 2 for DAR
589 * @param Imm is the 32-bit immediate number
591 * @return The number of bytes for this instruction which is 6.
595 *****************************************************************************/
596 __inline int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm)
600 * 15 4 3 2 1 10 ... 8 7 6 5 4 3 2 1 0
601 * 0 0 0 0 0 |rd[2:0]|1 0 1 1 1 1 0 0
606 * rd: b000 for SAR, b001 CCR, b010 DAR
609 *(DmaProg + 1) = Rd & 0x7;
610 // *((u32 *)(DmaProg + 2)) = Imm;
611 XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm);
616 /****************************************************************************/
619 * Construction function for DMANOP instruction. This function fills the
620 * program buffer with the constructed instruction.
622 * @param DmaProg is the DMA program buffer, it's the starting address
623 * for the instruction being constructed
624 * @return The number of bytes for this instruction which is 1.
628 *****************************************************************************/
629 __inline int XDmaPs_Instr_DMANOP(char *DmaProg)
640 /****************************************************************************/
643 * Construction function for DMARMB instruction. This function fills the
644 * program buffer with the constructed instruction.
646 * @param DmaProg is the DMA program buffer, it's the starting address
647 * for the instruction being constructed
649 * @return The number of bytes for this instruction which is 1.
653 *****************************************************************************/
654 __inline int XDmaPs_Instr_DMARMB(char *DmaProg)
665 /****************************************************************************/
668 * Construction function for DMASEV instruction. This function fills the
669 * program buffer with the constructed instruction.
671 * @param DmaProg is the DMA program buffer, it's the starting address
672 * for the instruction being constructed
673 * @param EventNumber is the Event number to signal.
675 * @return The number of bytes for this instruction which is 2.
679 *****************************************************************************/
680 __inline int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber)
684 * 15 4 3 2 1 10 9 8 7 6 5 4 3 2 1 0
685 * |event[4:0]| 0 0 0 0 0 1 1 0 1 0 0
688 *(DmaProg + 1) = (u8)(EventNumber << 3);
694 /****************************************************************************/
697 * Construction function for DMAST instruction. This function fills the
698 * program buffer with the constructed instruction.
700 * @param DmaProg is the DMA program buffer, it's the starting address
701 * for the instruction being constructed
703 * @return The number of bytes for this instruction which is 1.
707 *****************************************************************************/
708 __inline int XDmaPs_Instr_DMAST(char *DmaProg)
715 * Note: this driver doesn't support conditional load or store,
716 * so the bs bit is 0 and x bit is 0.
723 /****************************************************************************/
726 * Construction function for DMAWMB instruction. This function fills the
727 * program buffer with the constructed instruction.
729 * @param DmaProg is the DMA program buffer, it's the starting address
730 * for the instruction being constructed
732 * @return The number of bytes for this instruction which is 1.
736 *****************************************************************************/
737 __inline int XDmaPs_Instr_DMAWMB(char *DmaProg)
748 /****************************************************************************/
751 * Conversion function from the endian swap size to the bit encoding of the CCR
753 * @param EndianSwapSize is the endian swap size, in terms of bits, it
754 * could be 8, 16, 32, 64, or 128(We are using DMA assembly syntax)
756 * @return The endian swap size bit encoding for the CCR.
760 *****************************************************************************/
761 __inline unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize)
763 switch (EndianSwapSize) {
781 /****************************************************************************/
784 * Conversion function from the burst size to the bit encoding of the CCR
786 * @param BurstSize is the burst size. It's the data width.
787 * In terms of bytes, it could be 1, 2, 4, 8, 16, 32, 64, or 128.
788 * It must be no larger than the bus width.
789 * (We are using DMA assembly syntax.)
793 *****************************************************************************/
794 __inline unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize)
819 /****************************************************************************/
822 * Conversion function from PL330 bus transfer descriptors to CCR value. All the
823 * values passed to the functions are in terms of assembly languages, not in
824 * terms of the register bit encoding.
826 * @param ChanCtrl is the Instance of XDmaPs_ChanCtrl.
828 * @return The 32-bit CCR value.
832 *****************************************************************************/
833 u32 XDmaPs_ToCCRValue(XDmaPs_ChanCtrl *ChanCtrl)
836 * Channel Control Register encoding
837 * [31:28] - endian_swap_size
838 * [27:25] - dst_cache_ctrl
839 * [24:22] - dst_prot_ctrl
840 * [21:18] - dst_burst_len
841 * [17:15] - dst_burst_size
843 * [13:11] - src_cache_ctrl
844 * [10:8] - src_prot_ctrl
845 * [7:4] - src_burst_len
846 * [3:1] - src_burst_size
851 XDmaPs_ToEndianSwapSizeBits(ChanCtrl->EndianSwapSize);
853 unsigned dst_burst_size =
854 XDmaPs_ToBurstSizeBits(ChanCtrl->DstBurstSize);
855 unsigned dst_burst_len = (ChanCtrl->DstBurstLen - 1) & 0x0F;
856 unsigned dst_cache_ctrl = (ChanCtrl->DstCacheCtrl & 0x03)
857 | ((ChanCtrl->DstCacheCtrl & 0x08) >> 1);
858 unsigned dst_prot_ctrl = ChanCtrl->DstProtCtrl & 0x07;
859 unsigned dst_inc_bit = ChanCtrl->DstInc & 1;
861 unsigned src_burst_size =
862 XDmaPs_ToBurstSizeBits(ChanCtrl->SrcBurstSize);
863 unsigned src_burst_len = (ChanCtrl->SrcBurstLen - 1) & 0x0F;
864 unsigned src_cache_ctrl = (ChanCtrl->SrcCacheCtrl & 0x03)
865 | ((ChanCtrl->SrcCacheCtrl & 0x08) >> 1);
866 unsigned src_prot_ctrl = ChanCtrl->SrcProtCtrl & 0x07;
867 unsigned src_inc_bit = ChanCtrl->SrcInc & 1;
869 u32 ccr_value = (es << 28)
870 | (dst_cache_ctrl << 25)
871 | (dst_prot_ctrl << 22)
872 | (dst_burst_len << 18)
873 | (dst_burst_size << 15)
874 | (dst_inc_bit << 14)
875 | (src_cache_ctrl << 11)
876 | (src_prot_ctrl << 8)
877 | (src_burst_len << 4)
878 | (src_burst_size << 1)
884 /****************************************************************************/
886 * Construct a loop with only DMALD and DMAST as the body using loop counter 0.
887 * The function also makes sure the loop body and the lpend is in the same
890 * @param DmaProgStart is the very start address of the DMA program.
891 * This is used to calculate whether the loop is in a cache line.
892 * @param CacheLength is the icache line length, in terms of bytes.
893 * If it's zero, the performance enhancement feature will be
895 * @param DmaProgLoopStart The starting address of the loop (DMALP).
896 * @param LoopCount The inner loop count. Loop count - 1 will be used to
897 * initialize the loop counter.
899 * @return The number of bytes the loop has.
903 *****************************************************************************/
904 int XDmaPs_ConstructSingleLoop(char *DmaProgStart,
906 char *DmaProgLoopStart,
909 int CacheStartOffset;
912 char *DmaProgBuf = DmaProgLoopStart;
914 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCount);
916 if (CacheLength > 0) {
918 * the CacheLength > 0 switch is ued to turn on/off nop
921 CacheStartOffset = DmaProgBuf - DmaProgStart;
922 CacheEndOffset = CacheStartOffset + 3;
925 * check whether the body and lpend fit in one cache line
927 if (CacheStartOffset / CacheLength
928 != CacheEndOffset / CacheLength) {
929 /* insert the nops */
930 NumNops = CacheLength
931 - CacheStartOffset % CacheLength;
934 XDmaPs_Instr_DMANOP(DmaProgBuf);
939 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
940 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
941 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
944 return DmaProgBuf - DmaProgLoopStart;
947 /****************************************************************************/
949 * Construct a nested loop with only DMALD and DMAST in the inner loop body.
950 * It uses loop counter 1 for the outer loop and loop counter 0 for the
953 * @param DmaProgStart is the very start address of the DMA program.
954 * This is used to calculate whether the loop is in a cache line.
955 * @param CacheLength is the icache line length, in terms of bytes.
956 * If it's zero, the performance enhancement feature will be
958 * @param DmaProgLoopStart The starting address of the loop (DMALP).
959 * @param LoopCountOuter The outer loop count. Loop count - 1 will be
960 * used to initialize the loop counter.
961 * @param LoopCountInner The inner loop count. Loop count - 1 will be
962 * used to initialize the loop counter.
964 * @return The number byes the nested loop program has.
968 *****************************************************************************/
969 int XDmaPs_ConstructNestedLoop(char *DmaProgStart,
971 char *DmaProgLoopStart,
972 unsigned int LoopCountOuter,
973 unsigned int LoopCountInner)
975 int CacheStartOffset;
978 char *InnerLoopStart;
979 char *DmaProgBuf = DmaProgLoopStart;
981 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 1, LoopCountOuter);
982 InnerLoopStart = DmaProgBuf;
984 if (CacheLength > 0) {
986 * the CacheLength > 0 switch is ued to turn on/off nop
989 if (CacheLength < 8) {
991 * if the cache line is too small to fit both loops
992 * just align the inner loop
995 XDmaPs_ConstructSingleLoop(DmaProgStart,
1001 XDmaPs_Instr_DMALPEND(DmaProgBuf,
1006 * the nested loop is constructed for
1007 * smaller cache line
1009 return DmaProgBuf - DmaProgLoopStart;
1013 * Now let's handle the case where a cache line can
1014 * fit the nested loops.
1016 CacheStartOffset = DmaProgBuf - DmaProgStart;
1017 CacheEndOffset = CacheStartOffset + 7;
1020 * check whether the body and lpend fit in one cache line
1022 if (CacheStartOffset / CacheLength
1023 != CacheEndOffset / CacheLength) {
1024 /* insert the nops */
1025 NumNops = CacheLength
1026 - CacheStartOffset % CacheLength;
1029 XDmaPs_Instr_DMANOP(DmaProgBuf);
1034 /* insert the inner DMALP */
1035 DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCountInner);
1037 /* DMALD and DMAST instructions */
1038 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
1039 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
1041 /* inner DMALPEND */
1042 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
1044 /* outer DMALPEND */
1045 DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
1048 /* return the number of bytes */
1049 return DmaProgBuf - DmaProgLoopStart;
1053 * [31:28] endian_swap_size b0000
1054 * [27:25] dst_cache_ctrl b000
1055 * [24:22] dst_prot_ctrl b000
1056 * [21:18] dst_burst_len b0000
1057 * [17:15] dst_burst_size b000
1059 * [27:25] src_cache_ctrl b000
1060 * [24:22] src_prot_ctrl b000
1061 * [21:18] src_burst_len b0000
1062 * [17:15] src_burst_size b000
1065 #define XDMAPS_CCR_SINGLE_BYTE (0x0)
1066 #define XDMAPS_CCR_M2M_SINGLE_BYTE ((0x1 << 14) | 0x1)
1069 /****************************************************************************/
1072 * Construct the DMA program based on the descriptions of the DMA transfer.
1073 * The function handles memory to memory DMA transfers.
1074 * It also handles unalgined head and small amount of residue tail.
1076 * @param Channel DMA channel number
1077 * @param Cmd is the DMA command.
1078 * @param CacheLength is the icache line length, in terms of bytes.
1079 * If it's zero, the performance enhancement feature will be
1082 * @returns The number of bytes for the program.
1086 *****************************************************************************/
1087 static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd,
1088 unsigned CacheLength)
1093 char *DmaProgBuf = (char *)Cmd->GeneratedDmaProg;
1094 unsigned DevChan = Channel;
1095 unsigned long DmaLength = Cmd->BD.Length;
1096 u32 SrcAddr = Cmd->BD.SrcAddr;
1098 unsigned SrcInc = Cmd->ChanCtrl.SrcInc;
1099 u32 DstAddr = Cmd->BD.DstAddr;
1100 unsigned DstInc = Cmd->ChanCtrl.DstInc;
1102 char *DmaProgStart = DmaProgBuf;
1104 unsigned int BurstBytes;
1105 unsigned int LoopCount;
1106 unsigned int LoopCount1 = 0;
1107 unsigned int LoopResidue = 0;
1108 unsigned int TailBytes;
1109 unsigned int TailWords;
1112 unsigned int Unaligned;
1113 unsigned int UnalignedCount;
1114 unsigned int MemBurstSize = 1;
1117 unsigned int SrcUnaligned = 0;
1118 unsigned int DstUnaligned = 0;
1120 XDmaPs_ChanCtrl *ChanCtrl;
1121 XDmaPs_ChanCtrl WordChanCtrl;
1122 static XDmaPs_ChanCtrl Mem2MemByteCC;
1124 Mem2MemByteCC.EndianSwapSize = 0;
1125 Mem2MemByteCC.DstCacheCtrl = 0;
1126 Mem2MemByteCC.DstProtCtrl = 0;
1127 Mem2MemByteCC.DstBurstLen = 1;
1128 Mem2MemByteCC.DstBurstSize = 1;
1129 Mem2MemByteCC.DstInc = 1;
1130 Mem2MemByteCC.SrcCacheCtrl = 0;
1131 Mem2MemByteCC.SrcProtCtrl = 0;
1132 Mem2MemByteCC.SrcBurstLen = 1;
1133 Mem2MemByteCC.SrcBurstSize = 1;
1134 Mem2MemByteCC.SrcInc = 1;
1136 ChanCtrl = &Cmd->ChanCtrl;
1138 /* insert DMAMOV for SAR and DAR */
1139 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1142 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1147 if (ChanCtrl->SrcInc)
1148 SrcUnaligned = SrcAddr % ChanCtrl->SrcBurstSize;
1150 if (ChanCtrl->DstInc)
1151 DstUnaligned = DstAddr % ChanCtrl->DstBurstSize;
1153 if ((SrcUnaligned && DstInc) || (DstUnaligned && SrcInc)) {
1154 ChanCtrl = &Mem2MemByteCC;
1157 if (ChanCtrl->SrcInc) {
1158 MemBurstSize = ChanCtrl->SrcBurstSize;
1161 } else if (ChanCtrl->DstInc) {
1162 MemBurstSize = ChanCtrl->DstBurstSize;
1166 /* check whether the head is aligned or not */
1167 Unaligned = MemAddr % MemBurstSize;
1170 /* if head is unaligned, transfer head in bytes */
1171 UnalignedCount = MemBurstSize - Unaligned;
1172 CCRValue = XDMAPS_CCR_SINGLE_BYTE
1174 | ((DstInc & 1) << 14);
1176 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1180 for (Index = 0; Index < UnalignedCount; Index++) {
1181 DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
1182 DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
1185 DmaLength -= UnalignedCount;
1188 /* now the burst transfer part */
1189 CCRValue = XDmaPs_ToCCRValue(ChanCtrl);
1190 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1194 BurstBytes = ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen;
1196 LoopCount = DmaLength / BurstBytes;
1197 TailBytes = DmaLength % BurstBytes;
1200 * the loop count register is 8-bit wide, so if we need
1201 * a larger loop, we need to have nested loops
1203 if (LoopCount > 256) {
1204 LoopCount1 = LoopCount / 256;
1205 if (LoopCount1 > 256) {
1206 xil_printf("DMA operation cannot fit in a 2-level "
1207 "loop for channel %d, please reduce the "
1208 "DMA length or increase the burst size or "
1213 LoopResidue = LoopCount % 256;
1217 XDmaPs_ConstructNestedLoop(DmaProgStart,
1224 XDmaPs_ConstructSingleLoop(DmaProgStart,
1229 /* there will be some that cannot be covered by
1232 LoopCount = LoopResidue;
1235 if (LoopCount > 0) {
1236 DmaProgBuf += XDmaPs_ConstructSingleLoop(DmaProgStart,
1243 /* handle the tail */
1244 TailWords = TailBytes / MemBurstSize;
1245 TailBytes = TailBytes % MemBurstSize;
1248 WordChanCtrl = *ChanCtrl;
1250 * if we can transfer the tail in words, we will
1251 * transfer words as much as possible
1253 WordChanCtrl.SrcBurstSize = MemBurstSize;
1254 WordChanCtrl.SrcBurstLen = 1;
1255 WordChanCtrl.DstBurstSize = MemBurstSize;
1256 WordChanCtrl.DstBurstLen = 1;
1260 * the burst length is 1
1262 CCRValue = XDmaPs_ToCCRValue(&WordChanCtrl);
1265 XDmaPs_Instr_DMAMOV(DmaProgBuf,
1269 XDmaPs_ConstructSingleLoop(DmaProgStart,
1278 * for the rest, we'll tranfer in bytes
1281 * So far just to be safe, the tail bytes
1282 * are transfered in a loop. We can optimize a little
1283 * to perform a burst.
1285 CCRValue = XDMAPS_CCR_SINGLE_BYTE
1287 | ((DstInc & 1) << 14);
1290 XDmaPs_Instr_DMAMOV(DmaProgBuf,
1295 XDmaPs_ConstructSingleLoop(DmaProgStart,
1303 DmaProgBuf += XDmaPs_Instr_DMASEV(DmaProgBuf, DevChan);
1304 DmaProgBuf += XDmaPs_Instr_DMAEND(DmaProgBuf);
1306 DmaProgBytes = DmaProgBuf - DmaProgStart;
1308 Xil_DCacheFlushRange((u32)DmaProgStart, DmaProgBytes);
1310 return DmaProgBytes;
1315 /****************************************************************************/
1318 * Generate a DMA program based for the DMA command, the buffer will be pointed
1319 * by the GeneratedDmaProg field of the command.
1321 * @param InstPtr is then DMA instance.
1322 * @param Channel is the DMA channel number.
1323 * @param Cmd is the DMA command.
1325 * @return - XST_SUCCESS on success.
1326 * - XST_FAILURE if it fails
1330 *****************************************************************************/
1331 int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd)
1335 XDmaPs_ChannelData *ChanData;
1336 XDmaPs_ChanCtrl *ChanCtrl;
1338 Xil_AssertNonvoid(InstPtr != NULL);
1339 Xil_AssertNonvoid(Cmd != NULL);
1342 if (Channel > XDMAPS_CHANNELS_PER_DEV)
1345 ChanData = InstPtr->Chans + Channel;
1346 ChanCtrl = &Cmd->ChanCtrl;
1348 if (ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen
1349 != ChanCtrl->DstBurstSize * ChanCtrl->DstBurstLen) {
1350 xil_printf("source burst_size * burst_len does not match "
1351 "that of destination\r\n");
1357 * unaligned fixed address is not supported
1359 if (!ChanCtrl->SrcInc && Cmd->BD.SrcAddr % ChanCtrl->SrcBurstSize) {
1360 xil_printf("source address is fixed but is unaligned\r\n");
1364 if (!ChanCtrl->DstInc && Cmd->BD.DstAddr % ChanCtrl->DstBurstSize) {
1365 xil_printf("destination address is fixed but is "
1370 Buf = XDmaPs_BufPool_Allocate(ChanData->ProgBufPool);
1372 xil_printf("failed to allocate program buffer\r\n");
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 if ((DmaCmd = ChanData->DmaCmdToHw)) {
1917 if (!ChanData->HoldDmaProg) {
1918 DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg;
1920 XDmaPs_BufPool_Free(ChanData->ProgBufPool,
1922 DmaCmd->GeneratedDmaProg = NULL;
1925 DmaCmd->DmaStatus = 0;
1926 ChanData->DmaCmdToHw = NULL;
1927 ChanData->DmaCmdFromHw = DmaCmd;
1929 if (ChanData->DoneHandler)
1930 ChanData->DoneHandler(Channel, DmaCmd,
1937 /****************************************************************************/
1939 * Prints the content of the buffer in bytes
1940 * @param Buf is the buffer.
1941 * @param Length is the length of the DMA program.
1946 ****************************************************************************/
1947 static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length)
1950 for (Index = 0; Index < Length; Index++)
1951 xil_printf("[%x] %x\r\n", Index, Buf[Index]);
1954 /****************************************************************************/
1956 * Print the Dma Prog Contents.
1958 * @param Cmd is the command buffer.
1964 *****************************************************************************/
1965 void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd)
1967 if (Cmd->GeneratedDmaProg && Cmd->GeneratedDmaProgLength) {
1968 xil_printf("Generated DMA program (%d):\r\n",
1969 Cmd->GeneratedDmaProgLength);
1970 XDmaPs_Print_DmaProgBuf((char *)Cmd->GeneratedDmaProg,
1971 Cmd->GeneratedDmaProgLength);
1974 if (Cmd->UserDmaProg && Cmd->UserDmaProgLength) {
1975 xil_printf("User defined DMA program (%d):\r\n",
1976 Cmd->UserDmaProgLength);
1977 XDmaPs_Print_DmaProgBuf((char *)Cmd->UserDmaProg,
1978 Cmd->UserDmaProgLength);