]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/dmaps_v2_1/src/xdmaps.c
xTaskGenericNotify() now sets xYieldPending to pdTRUE even when the 'higher priority...
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo_bsp / ps7_cortexa9_0 / libsrc / dmaps_v2_1 / src / xdmaps.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2009 - 2015 Xilinx, Inc.  All rights reserved.
4 *
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:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
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.
18 *
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
25 * SOFTWARE.
26 *
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.
30 *
31 ******************************************************************************/
32 /****************************************************************************/
33 /**
34 *
35 * @file xdmaps.c
36 * @addtogroup dmaps_v2_1
37 * @{
38 *
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.
41 *
42 * <pre>
43 * MODIFICATION HISTORY:
44 *
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
52 *                         and CR 657898
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()
61 *                         function.
62 * 1.07a asa    11/02/13. Made changes to fix compilation issues for iarcc.
63 *                          Removed the PDBG prints. By default they were always
64 *                          defined out and never used. The PDBG is non-standard for
65 *                          Xilinx drivers and no other driver does something similar.
66 *                          Since there is no easy way to fix compilation issues with
67 *                          the IARCC compiler around PDBG, it is better to remove it.
68 *                          Users can always use xil_printfs if they want to debug.
69 * 2.01 kpc    08/23/14   Fixed the IAR compiler reported errors
70 * </pre>
71 *
72 *****************************************************************************/
73
74 /***************************** Include Files ********************************/
75
76 #include <string.h>
77
78 #include "xstatus.h"
79 #include "xdmaps.h"
80 #include "xil_io.h"
81 #include "xil_cache.h"
82
83 #include "xil_printf.h"
84
85
86 /************************** Constant Definitions ****************************/
87
88 /* The following constant defines the amount of error that is allowed for
89  * a specified baud rate. This error is the difference between the actual
90  * baud rate that will be generated using the specified clock and the
91  * desired baud rate.
92  */
93
94 /**************************** Type Definitions ******************************/
95
96 #ifdef __ICCARM__
97 #define INLINE
98 #else
99 #define INLINE __inline
100 #endif
101 /***************** Macros (Inline Functions) Definitions ********************/
102
103
104 /************************** Function Prototypes *****************************/
105 static int XDmaPs_Exec_DMAKILL(u32 BaseAddr,
106                                 unsigned int Channel,
107                                 unsigned int Thread);
108
109 static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf);
110
111 static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg);
112
113 static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel);
114 static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool);
115 static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd,
116                                 unsigned CacheLength);
117
118 static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length);
119
120
121
122 /************************** Variable Definitions ****************************/
123
124 /****************************************************************************/
125 /**
126 *
127 * Initializes a specific XDmaPs instance such that it is ready to be used.
128 * The data format of the device is setup for 8 data bits, 1 stop bit, and no
129 * parity by default. The baud rate is set to a default value specified by
130 * Config->DefaultBaudRate if set, otherwise it is set to 19.2K baud. The
131 * receive FIFO threshold is set for 8 bytes. The default operating mode of the
132 * driver is polled mode.
133 *
134 * @param        InstPtr is a pointer to the XDmaPs instance.
135 * @param        Config is a reference to a structure containing information
136 *               about a specific XDmaPs driver.
137 * @param        EffectiveAddr is the device base address in the virtual memory
138 *               address space. The caller is responsible for keeping the
139 *               address mapping from EffectiveAddr to the device physical base
140 *               address unchanged once this function is invoked. Unexpected
141 *               errors may occur if the address mapping changes after this
142 *               function is called. If address translation is not used, pass in
143 *               the physical address instead.
144 *
145 * @return
146 *
147 *               - XST_SUCCESS on initialization completion
148 *
149 * @note         None.
150 *
151 *****************************************************************************/
152 int XDmaPs_CfgInitialize(XDmaPs *InstPtr,
153                           XDmaPs_Config *Config,
154                           u32 EffectiveAddr)
155 {
156         int Status = XST_SUCCESS;
157         unsigned int CacheLength = 0;
158         u32 CfgReg;
159         unsigned Channel;
160         XDmaPs_ChannelData *ChanData;
161
162         /*
163          * Assert validates the input arguments
164          */
165         Xil_AssertNonvoid(InstPtr != NULL);
166         Xil_AssertNonvoid(Config != NULL);
167
168         /*
169          * Setup the driver instance using passed in parameters
170          */
171         InstPtr->Config.DeviceId = Config->DeviceId;
172         InstPtr->Config.BaseAddress = EffectiveAddr;
173
174         CfgReg = XDmaPs_ReadReg(EffectiveAddr, XDMAPS_CR1_OFFSET);
175         CacheLength = CfgReg & XDMAPS_CR1_I_CACHE_LEN_MASK;
176         if (CacheLength < 2 || CacheLength > 5)
177                 CacheLength = 0;
178         else
179                 CacheLength = 1 << CacheLength;
180
181         InstPtr->CacheLength = CacheLength;
182
183         memset(InstPtr->Chans, 0,
184                sizeof(XDmaPs_ChannelData[XDMAPS_CHANNELS_PER_DEV]));
185
186         for (Channel = 0; Channel < XDMAPS_CHANNELS_PER_DEV; Channel++) {
187                 ChanData = InstPtr->Chans + Channel;
188                 ChanData->ChanId = Channel;
189                 ChanData->DevId = Config->DeviceId;
190         }
191
192         InstPtr->IsReady = 1;
193
194         return Status;
195 }
196
197 /****************************************************************************/
198 /**
199 *
200 * Reset the DMA Manager.
201 *
202 * @param        InstPtr is the DMA instance.
203 *
204 * @return       0 on success, -1 on time out
205 *
206 * @note         None.
207 *
208 *****************************************************************************/
209 int XDmaPs_ResetManager(XDmaPs *InstPtr)
210 {
211         int Status;
212         Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress,
213                                       0, 0);
214
215         return Status;
216 }
217
218 /****************************************************************************/
219 /**
220 *
221 * Reset the specified DMA Channel.
222 *
223 * @param        InstPtr is the DMA instance.
224 * @param        Channel is the channel to be reset.
225 *
226 * @return       0 on success, -1 on time out
227 *
228 * @note         None.
229 *
230 *****************************************************************************/
231 int XDmaPs_ResetChannel(XDmaPs *InstPtr, unsigned int Channel)
232 {
233         int Status;
234         Status = XDmaPs_Exec_DMAKILL(InstPtr->Config.BaseAddress,
235                                       Channel, 1);
236
237         return Status;
238
239 }
240
241 /*****************************************************************************/
242 /**
243 *
244 * Driver fault interrupt service routine
245 * This is the one that connects the GIC
246 *
247 * @param        InstPtr is the DMA instance.
248 *
249 * @return       None.
250 *
251 * @note         None.
252 *
253 ******************************************************************************/
254 void XDmaPs_FaultISR(XDmaPs *InstPtr)
255 {
256
257         void *DmaProgBuf;
258         u32 Fsm; /* Fault status DMA manager register value */
259         u32 Fsc; /* Fault status DMA channel register value */
260         u32 FaultType; /* Fault type DMA manager register value */
261
262         u32 BaseAddr = InstPtr->Config.BaseAddress;
263
264         u32 Pc; /* DMA Pc or channel Pc */
265         XDmaPs_ChannelData *ChanData;
266
267         unsigned Chan;
268         unsigned DevId;
269
270         XDmaPs_Cmd *DmaCmd;
271
272         Fsm = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSM_OFFSET) & 0x01;
273         Fsc = XDmaPs_ReadReg(BaseAddr, XDMAPS_FSC_OFFSET) & 0xFF;
274
275
276         DevId = InstPtr->Config.DeviceId;
277
278         if (Fsm) {
279                 /*
280                  * if DMA manager is fault
281                  */
282                 FaultType = XDmaPs_ReadReg(BaseAddr, XDMAPS_FTM_OFFSET);
283                 Pc = XDmaPs_ReadReg(BaseAddr, XDMAPS_DPC_OFFSET);
284
285                 xil_printf("PL330 device %d fault with type: %x at Pc %x\n",
286                            DevId,
287                            FaultType, Pc);
288
289                 /* kill the DMA manager thread */
290                 /* Should we disable interrupt?*/
291                 XDmaPs_Exec_DMAKILL(BaseAddr, 0, 0);
292         }
293
294         /*
295          * check which channel faults and kill the channel thread
296          */
297         for (Chan = 0;
298              Chan < XDMAPS_CHANNELS_PER_DEV;
299              Chan++) {
300                 if (Fsc & (0x01 << Chan)) {
301                         FaultType =
302                                 XDmaPs_ReadReg(BaseAddr,
303                                                 XDmaPs_FTCn_OFFSET(Chan));
304                         Pc = XDmaPs_ReadReg(BaseAddr,
305                                              XDmaPs_CPCn_OFFSET(Chan));
306
307                         /* kill the channel thread */
308                         /* Should we disable interrupt? */
309                         XDmaPs_Exec_DMAKILL(BaseAddr, Chan, 1);
310
311                         /*
312                          * get the fault type and fault Pc and invoke the
313                          * fault callback.
314                          */
315                         ChanData = InstPtr->Chans + Chan;
316
317                         DmaCmd = ChanData->DmaCmdToHw;
318
319                         /* Should we check DmaCmd is not null */
320                         DmaCmd->DmaStatus = -1;
321                         DmaCmd->ChanFaultType = FaultType;
322                         DmaCmd->ChanFaultPCAddr = Pc;
323                         ChanData->DmaCmdFromHw = DmaCmd;
324                         ChanData->DmaCmdToHw = NULL;
325
326                         if (!ChanData->HoldDmaProg) {
327                                 DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg;
328                                 if (DmaProgBuf)
329                                         XDmaPs_BufPool_Free(ChanData->ProgBufPool,
330                                                              DmaProgBuf);
331                                 DmaCmd->GeneratedDmaProg = NULL;
332                         }
333
334                         if (InstPtr->FaultHandler)
335                                 InstPtr->FaultHandler(Chan,
336                                                       DmaCmd,
337                                                       InstPtr->FaultRef);
338
339                 }
340         }
341
342 }
343
344 /*****************************************************************************/
345 /**
346 *
347 * Set the done handler for a channel.
348 *
349 * @param        InstPtr is the DMA instance.
350 * @param        Channel is the channel number.
351 * @param        DoneHandler is the done interrupt handler.
352 * @param        CallbackRef is the callback reference data.
353 *
354 * @return       None.
355 *
356 * @note         None.
357 *
358 ******************************************************************************/
359 int XDmaPs_SetDoneHandler(XDmaPs *InstPtr,
360                            unsigned Channel,
361                            XDmaPsDoneHandler DoneHandler,
362                            void *CallbackRef)
363 {
364         XDmaPs_ChannelData *ChanData;
365
366         Xil_AssertNonvoid(InstPtr != NULL);
367
368         if (Channel >= XDMAPS_CHANNELS_PER_DEV)
369                 return XST_FAILURE;
370
371
372         ChanData = InstPtr->Chans + Channel;
373
374         ChanData->DoneHandler = DoneHandler;
375         ChanData->DoneRef = CallbackRef;
376
377         return 0;
378 }
379
380 /*****************************************************************************/
381 /**
382 *
383 * Set the fault handler for a channel.
384 *
385 * @param        InstPtr is the DMA instance.
386 * @param        FaultHandler is the fault interrupt handler.
387 * @param        CallbackRef is the callback reference data.
388 *
389 * @return       None.
390 *
391 * @note         None.
392 *
393 ******************************************************************************/
394 int XDmaPs_SetFaultHandler(XDmaPs *InstPtr,
395                             XDmaPsFaultHandler FaultHandler,
396                             void *CallbackRef)
397 {
398         Xil_AssertNonvoid(InstPtr != NULL);
399
400         InstPtr->FaultHandler = FaultHandler;
401         InstPtr->FaultRef = CallbackRef;
402
403         return XST_SUCCESS;
404 }
405
406
407
408 /****************************************************************************/
409 /**
410 * Construction function for DMAEND instruction. This function fills the program
411 * buffer with the constructed instruction.
412 *
413 * @param        DmaProg the DMA program buffer, it's the starting address for
414 *               the instruction being constructed
415 *
416 * @return       The number of bytes for this instruction which is 1.
417 *
418 * @note         None.
419 *
420 *****************************************************************************/
421 INLINE int XDmaPs_Instr_DMAEND(char *DmaProg)
422 {
423         /*
424          * DMAEND encoding:
425          * 7 6 5 4 3 2 1 0
426          * 0 0 0 0 0 0 0 0
427          */
428         *DmaProg = 0x0;
429
430         return 1;
431 }
432
433 INLINE void XDmaPs_Memcpy4(char *Dst, char *Src)
434 {
435         *Dst = *Src;
436         *(Dst + 1) = *(Src + 1);
437         *(Dst + 2) = *(Src + 2);
438         *(Dst + 3) = *(Src + 3);
439 }
440
441 /****************************************************************************/
442 /**
443 *
444 * Construction function for DMAGO instruction. This function fills the program
445 * buffer with the constructed instruction.
446 *
447 * @param        DmaProg is the DMA program buffer, it's the starting address
448 *               for the instruction being constructed
449 * @param        Cn is the Channel number, 0 - 7
450 * @param        Imm is 32-bit immediate number written to the Channel Program
451 *               Counter.
452 * @param        Ns is Non-secure flag. If Ns is 1, the DMA channel operates in
453 *               the Non-secure state. If Ns is 0, the execution depends on the
454 *               security state of the DMA manager:
455 *               DMA manager is in the Secure state, DMA channel operates in the
456 *               Secure state.
457 *               DMA manager is in the Non-secure state, DMAC aborts.
458 *
459 * @return       The number of bytes for this instruction which is 6.
460 *
461 * @note         None
462 *
463 *****************************************************************************/
464 INLINE int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn,
465                                u32 Imm, unsigned int Ns)
466 {
467         /*
468          * DMAGO encoding:
469          * 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
470          *  0  0  0  0  0 |cn[2:0]| 1  0  1  0  0  0 ns  0
471          *
472          * 47 ... 16
473          *  imm[32:0]
474          */
475         *DmaProg = 0xA0 | ((Ns << 1) & 0x02);
476
477         *(DmaProg + 1) = (u8)(Cn & 0x07);
478
479         // *((u32 *)(DmaProg + 2)) = Imm;
480         XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm);
481
482         /* success */
483         return 6;
484 }
485
486 /****************************************************************************/
487 /**
488 *
489 * Construction function for DMALD instruction. This function fills the program
490 * buffer with the constructed instruction.
491 *
492 * @param        DmaProg the DMA program buffer, it's the starting address for the
493 *               instruction being constructed
494 *
495 * @return       The number of bytes for this instruction which is 1.
496 *
497 * @note         None.
498 *
499 *****************************************************************************/
500 INLINE int XDmaPs_Instr_DMALD(char *DmaProg)
501 {
502         /*
503          * DMALD encoding
504          * 7 6 5 4 3 2 1  0
505          * 0 0 0 0 0 1 bs x
506          *
507          * Note: this driver doesn't support conditional load or store,
508          * so the bs bit is 0 and x bit is 0.
509          */
510         *DmaProg = 0x04;
511         return 1;
512 }
513
514 /****************************************************************************/
515 /**
516 *
517 * Construction function for DMALP instruction. This function fills the program
518 * buffer with the constructed instruction.
519 *
520 * @param        DmaProg is the DMA program buffer, it's the starting address
521 *               for the instruction being constructed
522 * @param        Lc is the Loop counter register, can either be 0 or 1.
523 * @param        LoopIterations: the number of interations, LoopInterations - 1
524 *               will be encoded in the DMALP instruction.
525 *
526 * @return       The number of bytes for this instruction which is 2.
527 *
528 * @note         None.
529 *
530 *****************************************************************************/
531 INLINE int XDmaPs_Instr_DMALP(char *DmaProg, unsigned Lc,
532                                unsigned LoopIterations)
533 {
534         /*
535          * DMALP encoding
536          * 15   ...   8 7 6 5 4 3 2 1  0
537          * | iter[7:0] |0 0 1 0 0 0 lc 0
538          */
539         *DmaProg = (u8)(0x20 | ((Lc & 1) << 1));
540         *(DmaProg + 1) = (u8)(LoopIterations - 1);
541         return 2;
542 }
543
544 /****************************************************************************/
545 /**
546 *
547 * Construction function for DMALPEND instruction. This function fills the
548 * program buffer with the constructed instruction.
549 *
550 * @param        DmaProg is the DMA program buffer, it's the starting address
551 *               for the instruction being constructed
552 * @param        BodyStart is the starting address of the loop body. It is used
553 *               to calculate the bytes of backward jump.
554 * @param        Lc is the Loop counter register, can either be 0 or 1.
555 *
556 * @return       The number of bytes for this instruction which is 2.
557 *
558 * @note None.
559 *
560 *****************************************************************************/
561 INLINE int XDmaPs_Instr_DMALPEND(char *DmaProg, char *BodyStart, unsigned Lc)
562 {
563         /*
564          * DMALPEND encoding
565          * 15       ...        8 7 6 5 4  3 2  1  0
566          * | backward_jump[7:0] |0 0 1 nf 1 lc bs x
567          *
568          * lc: loop counter
569          * nf is for loop forever. The driver does not support loop forever,
570          * so nf is 1.
571          * The driver does not support conditional LPEND, so bs is 0, x is 0.
572          */
573         *DmaProg = 0x38 | ((Lc & 1) << 2);
574         *(DmaProg + 1) = (u8)(DmaProg - BodyStart);
575
576         return 2;
577 }
578
579 /*
580  * Register number for the DMAMOV instruction
581  */
582 #define XDMAPS_MOV_SAR 0x0
583 #define XDMAPS_MOV_CCR 0x1
584 #define XDMAPS_MOV_DAR 0x2
585
586 /****************************************************************************/
587 /**
588 *
589 * Construction function for DMAMOV instruction. This function fills the
590 * program buffer with the constructed instruction.
591 *
592 * @param        DmaProg is the DMA program buffer, it's the starting address
593 *               for the instruction being constructed
594 * @param        Rd is the register id, 0 for SAR, 1 for CCR, and 2 for DAR
595 * @param        Imm is the 32-bit immediate number
596 *
597 * @return       The number of bytes for this instruction which is 6.
598 *
599 * @note         None.
600 *
601 *****************************************************************************/
602 INLINE int XDmaPs_Instr_DMAMOV(char *DmaProg, unsigned Rd, u32 Imm)
603 {
604         /*
605          * DMAMOV encoding
606          * 15 4 3 2 1 10 ... 8 7 6 5 4 3 2 1 0
607          *  0 0 0 0 0 |rd[2:0]|1 0 1 1 1 1 0 0
608          *
609          * 47 ... 16
610          *  imm[32:0]
611          *
612          * rd: b000 for SAR, b001 CCR, b010 DAR
613          */
614         *DmaProg = 0xBC;
615         *(DmaProg + 1) = Rd & 0x7;
616         // *((u32 *)(DmaProg + 2)) = Imm;
617         XDmaPs_Memcpy4(DmaProg + 2, (char *)&Imm);
618
619         return 6;
620 }
621
622 /****************************************************************************/
623 /**
624 *
625 * Construction function for DMANOP instruction. This function fills the
626 * program buffer with the constructed instruction.
627 *
628 * @param        DmaProg is the DMA program buffer, it's the starting address
629 *               for the instruction being constructed
630 * @return       The number of bytes for this instruction which is 1.
631 *
632 * @note         None.
633 *
634 *****************************************************************************/
635 INLINE int XDmaPs_Instr_DMANOP(char *DmaProg)
636 {
637         /*
638          * DMANOP encoding
639          * 7 6 5 4 3 2 1 0
640          * 0 0 0 1 1 0 0 0
641          */
642         *DmaProg = 0x18;
643         return 1;
644 }
645
646 /****************************************************************************/
647 /**
648 *
649 * Construction function for DMARMB instruction. This function fills the
650 * program buffer with the constructed instruction.
651 *
652 * @param        DmaProg is the DMA program buffer, it's the starting address
653 *               for the instruction being constructed
654 *
655 * @return       The number of bytes for this instruction which is 1.
656 *
657 * @note         None.
658 *
659 *****************************************************************************/
660 INLINE int XDmaPs_Instr_DMARMB(char *DmaProg)
661 {
662         /*
663          * DMARMB encoding
664          * 7 6 5 4 3 2 1 0
665          * 0 0 0 1 0 0 1 0
666          */
667         *DmaProg = 0x12;
668         return 1;
669 }
670
671 /****************************************************************************/
672 /**
673 *
674 * Construction function for DMASEV instruction. This function fills the
675 * program buffer with the constructed instruction.
676 *
677 * @param        DmaProg is the DMA program buffer, it's the starting address
678 *               for the instruction being constructed
679 * @param        EventNumber is the Event number to signal.
680 *
681 * @return       The number of bytes for this instruction which is 2.
682 *
683 * @note         None.
684 *
685 *****************************************************************************/
686 INLINE int XDmaPs_Instr_DMASEV(char *DmaProg, unsigned int EventNumber)
687 {
688         /*
689          * DMASEV encoding
690          * 15 4 3 2 1  10 9 8 7 6 5 4 3 2 1 0
691          * |event[4:0]| 0 0 0 0 0 1 1 0 1 0 0
692          */
693         *DmaProg = 0x34;
694         *(DmaProg + 1) = (u8)(EventNumber << 3);
695
696         return 2;
697 }
698
699
700 /****************************************************************************/
701 /**
702 *
703 * Construction function for DMAST instruction. This function fills the
704 * program buffer with the constructed instruction.
705 *
706 * @param        DmaProg is the DMA program buffer, it's the starting address
707 *               for the instruction being constructed
708 *
709 * @return       The number of bytes for this instruction which is 1.
710 *
711 * @note         None.
712 *
713 *****************************************************************************/
714 INLINE int XDmaPs_Instr_DMAST(char *DmaProg)
715 {
716         /*
717          * DMAST encoding
718          * 7 6 5 4 3 2 1  0
719          * 0 0 0 0 1 0 bs x
720          *
721          * Note: this driver doesn't support conditional load or store,
722          * so the bs bit is 0 and x bit is 0.
723          */
724         *DmaProg = 0x08;
725         return 1;
726 }
727
728
729 /****************************************************************************/
730 /**
731 *
732 * Construction function for DMAWMB instruction. This function fills the
733 * program buffer with the constructed instruction.
734 *
735 * @param        DmaProg is the DMA program buffer, it's the starting address
736 *               for the instruction being constructed
737 *
738 * @return       The number of bytes for this instruction which is 1.
739 *
740 * @note         None.
741 *
742 *****************************************************************************/
743 INLINE int XDmaPs_Instr_DMAWMB(char *DmaProg)
744 {
745         /*
746          * DMAWMB encoding
747          * 7 6 5 4 3 2 1 0
748          * 0 0 0 1 0 0 1 0
749          */
750         *DmaProg = 0x13;
751         return 1;
752 }
753
754 /****************************************************************************/
755 /**
756 *
757 * Conversion function from the endian swap size to the bit encoding of the CCR
758 *
759 * @param        EndianSwapSize is the endian swap size, in terms of bits, it
760 *               could be 8, 16, 32, 64, or 128(We are using DMA assembly syntax)
761 *
762 * @return       The endian swap size bit encoding for the CCR.
763 *
764 * @note None.
765 *
766 *****************************************************************************/
767 INLINE unsigned XDmaPs_ToEndianSwapSizeBits(unsigned int EndianSwapSize)
768 {
769         switch (EndianSwapSize) {
770         case 0:
771         case 8:
772                 return 0;
773         case 16:
774                 return 1;
775         case 32:
776                 return 2;
777         case 64:
778                 return 3;
779         case 128:
780                 return 4;
781         default:
782                 return 0;
783         }
784
785 }
786
787 /****************************************************************************/
788 /**
789 *
790 * Conversion function from the burst size to the bit encoding of the CCR
791 *
792 * @param        BurstSize is the burst size. It's the data width.
793 *               In terms of bytes, it could be 1, 2, 4, 8, 16, 32, 64, or 128.
794 *               It must be no larger than the bus width.
795 *               (We are using DMA assembly syntax.)
796 *
797 * @note         None.
798 *
799 *****************************************************************************/
800 INLINE unsigned XDmaPs_ToBurstSizeBits(unsigned BurstSize)
801 {
802         switch (BurstSize) {
803         case 1:
804                 return 0;
805         case 2:
806                 return 1;
807         case 4:
808                 return 2;
809         case 8:
810                 return 3;
811         case 16:
812                 return 4;
813         case 32:
814                 return 5;
815         case 64:
816                 return 6;
817         case 128:
818                 return 7;
819         default:
820                 return 0;
821         }
822 }
823
824
825 /****************************************************************************/
826 /**
827 *
828 * Conversion function from PL330 bus transfer descriptors to CCR value. All the
829 * values passed to the functions are in terms of assembly languages, not in
830 * terms of the register bit encoding.
831 *
832 * @param        ChanCtrl is the Instance of XDmaPs_ChanCtrl.
833 *
834 * @return       The 32-bit CCR value.
835 *
836 * @note         None.
837 *
838 *****************************************************************************/
839 u32 XDmaPs_ToCCRValue(XDmaPs_ChanCtrl *ChanCtrl)
840 {
841         /*
842          * Channel Control Register encoding
843          * [31:28] - endian_swap_size
844          * [27:25] - dst_cache_ctrl
845          * [24:22] - dst_prot_ctrl
846          * [21:18] - dst_burst_len
847          * [17:15] - dst_burst_size
848          * [14]    - dst_inc
849          * [13:11] - src_cache_ctrl
850          * [10:8] - src_prot_ctrl
851          * [7:4]  - src_burst_len
852          * [3:1]  - src_burst_size
853          * [0]     - src_inc
854          */
855
856         unsigned es =
857                 XDmaPs_ToEndianSwapSizeBits(ChanCtrl->EndianSwapSize);
858
859         unsigned dst_burst_size =
860                 XDmaPs_ToBurstSizeBits(ChanCtrl->DstBurstSize);
861         unsigned dst_burst_len = (ChanCtrl->DstBurstLen - 1) & 0x0F;
862         unsigned dst_cache_ctrl = (ChanCtrl->DstCacheCtrl & 0x03)
863                 | ((ChanCtrl->DstCacheCtrl & 0x08) >> 1);
864         unsigned dst_prot_ctrl = ChanCtrl->DstProtCtrl & 0x07;
865         unsigned dst_inc_bit = ChanCtrl->DstInc & 1;
866
867         unsigned src_burst_size =
868                 XDmaPs_ToBurstSizeBits(ChanCtrl->SrcBurstSize);
869         unsigned src_burst_len = (ChanCtrl->SrcBurstLen - 1) & 0x0F;
870         unsigned src_cache_ctrl = (ChanCtrl->SrcCacheCtrl & 0x03)
871                 | ((ChanCtrl->SrcCacheCtrl & 0x08) >> 1);
872         unsigned src_prot_ctrl = ChanCtrl->SrcProtCtrl & 0x07;
873         unsigned src_inc_bit = ChanCtrl->SrcInc & 1;
874
875         u32 ccr_value = (es << 28)
876                 | (dst_cache_ctrl << 25)
877                 | (dst_prot_ctrl << 22)
878                 | (dst_burst_len << 18)
879                 | (dst_burst_size << 15)
880                 | (dst_inc_bit << 14)
881                 | (src_cache_ctrl << 11)
882                 | (src_prot_ctrl << 8)
883                 | (src_burst_len << 4)
884                 | (src_burst_size << 1)
885                 | (src_inc_bit);
886
887         return ccr_value;
888 }
889
890 /****************************************************************************/
891 /**
892 * Construct a loop with only DMALD and DMAST as the body using loop counter 0.
893 * The function also makes sure the loop body and the lpend is in the same
894 * cache line.
895 *
896 * @param        DmaProgStart is the very start address of the DMA program.
897 *               This is used to calculate whether the loop is in a cache line.
898 * @param        CacheLength is the icache line length, in terms of bytes.
899 *               If it's zero, the performance enhancement feature will be
900 *               turned off.
901 * @param        DmaProgLoopStart The starting address of the loop (DMALP).
902 * @param        LoopCount The inner loop count. Loop count - 1 will be used to
903 *               initialize the loop counter.
904 *
905 * @return       The number of bytes the loop has.
906 *
907 * @note         None.
908 *
909 *****************************************************************************/
910 int XDmaPs_ConstructSingleLoop(char *DmaProgStart,
911                                 int CacheLength,
912                                 char *DmaProgLoopStart,
913                                 int LoopCount)
914 {
915         int CacheStartOffset;
916         int CacheEndOffset;
917         int NumNops;
918         char *DmaProgBuf = DmaProgLoopStart;
919
920         DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCount);
921
922         if (CacheLength > 0) {
923                 /*
924                  * the CacheLength > 0 switch is ued to turn on/off nop
925                  * insertion
926                  */
927                 CacheStartOffset = DmaProgBuf - DmaProgStart;
928                 CacheEndOffset = CacheStartOffset + 3;
929
930                 /*
931                  * check whether the body and lpend fit in one cache line
932                  */
933                 if (CacheStartOffset / CacheLength
934                     != CacheEndOffset / CacheLength) {
935                         /* insert the nops */
936                         NumNops = CacheLength
937                                 - CacheStartOffset % CacheLength;
938                         while (NumNops--) {
939                                 DmaProgBuf +=
940                                         XDmaPs_Instr_DMANOP(DmaProgBuf);
941                         }
942                 }
943         }
944
945         DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
946         DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
947         DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
948                                              DmaProgBuf - 2, 0);
949
950         return DmaProgBuf - DmaProgLoopStart;
951 }
952
953 /****************************************************************************/
954 /**
955 * Construct a nested loop with only DMALD and DMAST in the inner loop body.
956 * It uses loop counter 1 for the outer loop and loop counter 0 for the
957 * inner loop.
958 *
959 * @param        DmaProgStart is the very start address of the DMA program.
960 *               This is used to calculate whether the loop is in a cache line.
961 * @param        CacheLength is the icache line length, in terms of bytes.
962 *               If it's zero, the performance enhancement feature will be
963 *               turned off.
964 * @param        DmaProgLoopStart The starting address of the loop (DMALP).
965 * @param        LoopCountOuter The outer loop count. Loop count - 1 will be
966 *               used to initialize the loop counter.
967 * @param        LoopCountInner The inner loop count. Loop count - 1 will be
968 *               used to initialize the loop counter.
969 *
970 * @return       The number byes the nested loop program has.
971 *
972 * @note         None.
973 *
974 *****************************************************************************/
975 int XDmaPs_ConstructNestedLoop(char *DmaProgStart,
976                                 int CacheLength,
977                                 char *DmaProgLoopStart,
978                                 unsigned int LoopCountOuter,
979                                 unsigned int LoopCountInner)
980 {
981         int CacheStartOffset;
982         int CacheEndOffset;
983         int NumNops;
984         char *InnerLoopStart;
985         char *DmaProgBuf = DmaProgLoopStart;
986
987         DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 1, LoopCountOuter);
988         InnerLoopStart = DmaProgBuf;
989
990         if (CacheLength > 0) {
991                 /*
992                  * the CacheLength > 0 switch is ued to turn on/off nop
993                  * insertion
994                  */
995                 if (CacheLength < 8) {
996                         /*
997                          * if the cache line is too small to fit both loops
998                          * just align the inner loop
999                          */
1000                         DmaProgBuf +=
1001                                 XDmaPs_ConstructSingleLoop(DmaProgStart,
1002                                                             CacheLength,
1003                                                             DmaProgBuf,
1004                                                             LoopCountInner);
1005                         /* outer loop end */
1006                         DmaProgBuf +=
1007                                 XDmaPs_Instr_DMALPEND(DmaProgBuf,
1008                                                        InnerLoopStart,
1009                                                        1);
1010
1011                         /*
1012                          * the nested loop is constructed for
1013                          * smaller cache line
1014                          */
1015                         return DmaProgBuf - DmaProgLoopStart;
1016                 }
1017
1018                 /*
1019                  * Now let's handle the case where a cache line can
1020                  * fit the nested loops.
1021                  */
1022                 CacheStartOffset = DmaProgBuf - DmaProgStart;
1023                 CacheEndOffset = CacheStartOffset + 7;
1024
1025                 /*
1026                  * check whether the body and lpend fit in one cache line
1027                  */
1028                 if (CacheStartOffset / CacheLength
1029                     != CacheEndOffset / CacheLength) {
1030                         /* insert the nops */
1031                         NumNops = CacheLength
1032                                 - CacheStartOffset % CacheLength;
1033                         while (NumNops--) {
1034                                 DmaProgBuf +=
1035                                         XDmaPs_Instr_DMANOP(DmaProgBuf);
1036                         }
1037                 }
1038         }
1039
1040         /* insert the inner DMALP */
1041         DmaProgBuf += XDmaPs_Instr_DMALP(DmaProgBuf, 0, LoopCountInner);
1042
1043         /* DMALD and DMAST instructions */
1044         DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
1045         DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
1046
1047         /* inner DMALPEND */
1048         DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
1049                                              DmaProgBuf - 2, 0);
1050         /* outer DMALPEND */
1051         DmaProgBuf += XDmaPs_Instr_DMALPEND(DmaProgBuf,
1052                                              InnerLoopStart, 1);
1053
1054         /* return the number of bytes */
1055         return DmaProgBuf - DmaProgLoopStart;
1056 }
1057
1058 /*
1059  * [31:28] endian_swap_size     b0000
1060  * [27:25] dst_cache_ctrl       b000
1061  * [24:22] dst_prot_ctrl        b000
1062  * [21:18] dst_burst_len        b0000
1063  * [17:15] dst_burst_size       b000
1064  * [14]    dst_inc              b0
1065  * [27:25] src_cache_ctrl       b000
1066  * [24:22] src_prot_ctrl        b000
1067  * [21:18] src_burst_len        b0000
1068  * [17:15] src_burst_size       b000
1069  * [14]    src_inc              b0
1070  */
1071 #define XDMAPS_CCR_SINGLE_BYTE  (0x0)
1072 #define XDMAPS_CCR_M2M_SINGLE_BYTE      ((0x1 << 14) | 0x1)
1073
1074
1075 /****************************************************************************/
1076 /**
1077 *
1078 * Construct the DMA program based on the descriptions of the DMA transfer.
1079 * The function handles memory to memory DMA transfers.
1080 * It also handles unalgined head and small amount of residue tail.
1081 *
1082 * @param        Channel DMA channel number
1083 * @param        Cmd is the DMA command.
1084 * @param        CacheLength is the icache line length, in terms of bytes.
1085 *               If it's zero, the performance enhancement feature will be
1086 *               turned off.
1087 *
1088 * @returns      The number of bytes for the program.
1089 *
1090 * @note         None.
1091 *
1092 *****************************************************************************/
1093 static int XDmaPs_BuildDmaProg(unsigned Channel, XDmaPs_Cmd *Cmd,
1094                                 unsigned CacheLength)
1095 {
1096         /*
1097          * unpack arguments
1098          */
1099         char *DmaProgBuf = (char *)Cmd->GeneratedDmaProg;
1100         unsigned DevChan = Channel;
1101         unsigned long DmaLength = Cmd->BD.Length;
1102         u32 SrcAddr = Cmd->BD.SrcAddr;
1103
1104         unsigned SrcInc = Cmd->ChanCtrl.SrcInc;
1105         u32 DstAddr = Cmd->BD.DstAddr;
1106         unsigned DstInc = Cmd->ChanCtrl.DstInc;
1107
1108         char *DmaProgStart = DmaProgBuf;
1109
1110         unsigned int BurstBytes;
1111         unsigned int LoopCount;
1112         unsigned int LoopCount1 = 0;
1113         unsigned int LoopResidue = 0;
1114         unsigned int TailBytes;
1115         unsigned int TailWords;
1116         int DmaProgBytes;
1117         u32 CCRValue;
1118         unsigned int Unaligned;
1119         unsigned int UnalignedCount;
1120         unsigned int MemBurstSize = 1;
1121         u32 MemAddr = 0;
1122         unsigned int Index;
1123         unsigned int SrcUnaligned = 0;
1124         unsigned int DstUnaligned = 0;
1125
1126         XDmaPs_ChanCtrl *ChanCtrl;
1127         XDmaPs_ChanCtrl WordChanCtrl;
1128         static XDmaPs_ChanCtrl Mem2MemByteCC;
1129
1130         Mem2MemByteCC.EndianSwapSize = 0;
1131         Mem2MemByteCC.DstCacheCtrl = 0;
1132         Mem2MemByteCC.DstProtCtrl = 0;
1133         Mem2MemByteCC.DstBurstLen = 1;
1134         Mem2MemByteCC.DstBurstSize = 1;
1135         Mem2MemByteCC.DstInc = 1;
1136         Mem2MemByteCC.SrcCacheCtrl = 0;
1137         Mem2MemByteCC.SrcProtCtrl = 0;
1138         Mem2MemByteCC.SrcBurstLen = 1;
1139         Mem2MemByteCC.SrcBurstSize = 1;
1140         Mem2MemByteCC.SrcInc = 1;
1141
1142         ChanCtrl = &Cmd->ChanCtrl;
1143
1144         /* insert DMAMOV for SAR and DAR */
1145         DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1146                                            XDMAPS_MOV_SAR,
1147                                            SrcAddr);
1148         DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1149                                          XDMAPS_MOV_DAR,
1150                                          DstAddr);
1151
1152
1153         if (ChanCtrl->SrcInc)
1154                 SrcUnaligned = SrcAddr % ChanCtrl->SrcBurstSize;
1155
1156         if (ChanCtrl->DstInc)
1157                 DstUnaligned = DstAddr % ChanCtrl->DstBurstSize;
1158
1159         if ((SrcUnaligned && DstInc) || (DstUnaligned && SrcInc)) {
1160                 ChanCtrl = &Mem2MemByteCC;
1161         }
1162
1163         if (ChanCtrl->SrcInc) {
1164                 MemBurstSize = ChanCtrl->SrcBurstSize;
1165                 MemAddr = SrcAddr;
1166
1167         } else if (ChanCtrl->DstInc) {
1168                 MemBurstSize = ChanCtrl->DstBurstSize;
1169                 MemAddr = DstAddr;
1170         }
1171
1172         /* check whether the head is aligned or not */
1173         Unaligned = MemAddr % MemBurstSize;
1174
1175         if (Unaligned) {
1176                 /* if head is unaligned, transfer head in bytes */
1177                 UnalignedCount = MemBurstSize - Unaligned;
1178                 CCRValue = XDMAPS_CCR_SINGLE_BYTE
1179                         | (SrcInc & 1)
1180                         | ((DstInc & 1) << 14);
1181
1182                 DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1183                                                    XDMAPS_MOV_CCR,
1184                                                    CCRValue);
1185
1186                 for (Index = 0; Index < UnalignedCount; Index++) {
1187                         DmaProgBuf += XDmaPs_Instr_DMALD(DmaProgBuf);
1188                         DmaProgBuf += XDmaPs_Instr_DMAST(DmaProgBuf);
1189                 }
1190
1191                 DmaLength -= UnalignedCount;
1192         }
1193
1194         /* now the burst transfer part */
1195         CCRValue = XDmaPs_ToCCRValue(ChanCtrl);
1196         DmaProgBuf += XDmaPs_Instr_DMAMOV(DmaProgBuf,
1197                                            XDMAPS_MOV_CCR,
1198                                            CCRValue);
1199
1200         BurstBytes = ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen;
1201
1202         LoopCount = DmaLength / BurstBytes;
1203         TailBytes = DmaLength % BurstBytes;
1204
1205         /*
1206          * the loop count register is 8-bit wide, so if we need
1207          * a larger loop, we need to have nested loops
1208          */
1209         if (LoopCount > 256) {
1210                 LoopCount1 = LoopCount / 256;
1211                 if (LoopCount1 > 256) {
1212                         xil_printf("DMA operation cannot fit in a 2-level "
1213                                    "loop for channel %d, please reduce the "
1214                                    "DMA length or increase the burst size or "
1215                                    "length",
1216                                    Channel);
1217                         return 0;
1218                 }
1219                 LoopResidue = LoopCount % 256;
1220
1221                 if (LoopCount1 > 1)
1222                         DmaProgBuf +=
1223                                 XDmaPs_ConstructNestedLoop(DmaProgStart,
1224                                                             CacheLength,
1225                                                             DmaProgBuf,
1226                                                             LoopCount1,
1227                                                             256);
1228                 else
1229                         DmaProgBuf +=
1230                                 XDmaPs_ConstructSingleLoop(DmaProgStart,
1231                                                             CacheLength,
1232                                                             DmaProgBuf,
1233                                                             256);
1234
1235                 /* there will be some that cannot be covered by
1236                  * nested loops
1237                  */
1238                 LoopCount = LoopResidue;
1239         }
1240
1241         if (LoopCount > 0) {
1242                 DmaProgBuf += XDmaPs_ConstructSingleLoop(DmaProgStart,
1243                                                             CacheLength,
1244                                                             DmaProgBuf,
1245                                                             LoopCount);
1246         }
1247
1248         if (TailBytes) {
1249                 /* handle the tail */
1250                 TailWords = TailBytes / MemBurstSize;
1251                 TailBytes = TailBytes % MemBurstSize;
1252
1253                 if (TailWords) {
1254                         WordChanCtrl = *ChanCtrl;
1255                         /*
1256                          * if we can transfer the tail in words, we will
1257                          * transfer words as much as possible
1258                          */
1259                         WordChanCtrl.SrcBurstSize = MemBurstSize;
1260                         WordChanCtrl.SrcBurstLen = 1;
1261                         WordChanCtrl.DstBurstSize = MemBurstSize;
1262                         WordChanCtrl.DstBurstLen = 1;
1263
1264
1265                         /*
1266                          * the burst length is 1
1267                          */
1268                         CCRValue = XDmaPs_ToCCRValue(&WordChanCtrl);
1269
1270                         DmaProgBuf +=
1271                                 XDmaPs_Instr_DMAMOV(DmaProgBuf,
1272                                                    XDMAPS_MOV_CCR,
1273                                                    CCRValue);
1274                         DmaProgBuf +=
1275                                 XDmaPs_ConstructSingleLoop(DmaProgStart,
1276                                                             CacheLength,
1277                                                             DmaProgBuf,
1278                                                             TailWords);
1279
1280                 }
1281
1282                 if (TailBytes) {
1283                         /*
1284                          * for the rest, we'll tranfer in bytes
1285                          */
1286                         /*
1287                          * So far just to be safe, the tail bytes
1288                          * are transfered in a loop. We can optimize a little
1289                          * to perform a burst.
1290                          */
1291                         CCRValue = XDMAPS_CCR_SINGLE_BYTE
1292                                 | (SrcInc & 1)
1293                                 | ((DstInc & 1) << 14);
1294
1295                         DmaProgBuf +=
1296                                 XDmaPs_Instr_DMAMOV(DmaProgBuf,
1297                                                    XDMAPS_MOV_CCR,
1298                                                    CCRValue);
1299
1300                         DmaProgBuf +=
1301                                 XDmaPs_ConstructSingleLoop(DmaProgStart,
1302                                                             CacheLength,
1303                                                             DmaProgBuf,
1304                                                             TailBytes);
1305
1306                 }
1307         }
1308
1309         DmaProgBuf += XDmaPs_Instr_DMASEV(DmaProgBuf, DevChan);
1310         DmaProgBuf += XDmaPs_Instr_DMAEND(DmaProgBuf);
1311
1312         DmaProgBytes = DmaProgBuf - DmaProgStart;
1313
1314         Xil_DCacheFlushRange((u32)DmaProgStart, DmaProgBytes);
1315
1316         return DmaProgBytes;
1317
1318 }
1319
1320
1321 /****************************************************************************/
1322 /**
1323 *
1324 * Generate a DMA program based for the DMA command, the buffer will be pointed
1325 * by the GeneratedDmaProg field of the command.
1326 *
1327 * @param        InstPtr is then DMA instance.
1328 * @param        Channel is the DMA channel number.
1329 * @param        Cmd is the DMA command.
1330 *
1331 * @return       - XST_SUCCESS on success.
1332 *               - XST_FAILURE if it fails
1333 *
1334 * @note         None.
1335 *
1336 *****************************************************************************/
1337 int XDmaPs_GenDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd)
1338 {
1339         void *Buf;
1340         int ProgLen;
1341         XDmaPs_ChannelData *ChanData;
1342         XDmaPs_ChanCtrl *ChanCtrl;
1343
1344         Xil_AssertNonvoid(InstPtr != NULL);
1345         Xil_AssertNonvoid(Cmd != NULL);
1346
1347
1348         if (Channel > XDMAPS_CHANNELS_PER_DEV)
1349                 return XST_FAILURE;
1350
1351         ChanData = InstPtr->Chans + Channel;
1352         ChanCtrl = &Cmd->ChanCtrl;
1353
1354         if (ChanCtrl->SrcBurstSize * ChanCtrl->SrcBurstLen
1355             != ChanCtrl->DstBurstSize * ChanCtrl->DstBurstLen) {
1356                 return XST_FAILURE;
1357         }
1358
1359
1360         /*
1361          * unaligned fixed address is not supported
1362          */
1363         if (!ChanCtrl->SrcInc && Cmd->BD.SrcAddr % ChanCtrl->SrcBurstSize) {
1364                 return XST_FAILURE;
1365         }
1366
1367         if (!ChanCtrl->DstInc && Cmd->BD.DstAddr % ChanCtrl->DstBurstSize) {
1368                 return XST_FAILURE;
1369         }
1370
1371         Buf = XDmaPs_BufPool_Allocate(ChanData->ProgBufPool);
1372         if (Buf == NULL) {
1373                 return XST_FAILURE;
1374         }
1375
1376         Cmd->GeneratedDmaProg = Buf;
1377         ProgLen = XDmaPs_BuildDmaProg(Channel, Cmd,
1378                                        InstPtr->CacheLength);
1379         Cmd->GeneratedDmaProgLength = ProgLen;
1380
1381
1382 #ifdef XDMAPS_DEBUG
1383         XDmaPs_Print_DmaProg(Cmd);
1384 #endif
1385
1386         if (ProgLen <= 0) {
1387                 /* something wrong, release the buffer */
1388                 XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf);
1389                 Cmd->GeneratedDmaProgLength = 0;
1390                 Cmd->GeneratedDmaProg = NULL;
1391                 return XST_FAILURE;
1392         }
1393
1394         return XST_SUCCESS;
1395 }
1396
1397
1398 /****************************************************************************/
1399 /**
1400  * Free the DMA program buffer that is pointed by the GeneratedDmaProg field
1401  * of the command.
1402  *
1403  * @param       InstPtr is then DMA instance.
1404  * @param       Channel is the DMA channel number.
1405  * @param       Cmd is the DMA command.
1406  *
1407  * @return      XST_SUCCESS on success.
1408  *              XST_FAILURE if there is any error.
1409  *
1410  * @note        None.
1411  *
1412  ****************************************************************************/
1413 int XDmaPs_FreeDmaProg(XDmaPs *InstPtr, unsigned int Channel, XDmaPs_Cmd *Cmd)
1414 {
1415
1416         void *Buf;
1417         XDmaPs_ChannelData *ChanData;
1418
1419         Xil_AssertNonvoid(InstPtr != NULL);
1420         Xil_AssertNonvoid(Cmd != NULL);
1421
1422         if (Channel > XDMAPS_CHANNELS_PER_DEV)
1423                 return XST_FAILURE;
1424
1425         Buf = (void *)Cmd->GeneratedDmaProg;
1426         ChanData = InstPtr->Chans + Channel;
1427
1428         if (Buf) {
1429                 XDmaPs_BufPool_Free(ChanData->ProgBufPool, Buf);
1430                 Cmd->GeneratedDmaProg = 0;
1431                 Cmd->GeneratedDmaProgLength = 0;
1432         }
1433
1434         return XST_SUCCESS;
1435 }
1436
1437
1438 /****************************************************************************/
1439 /**
1440 *
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.
1444 *
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
1452 *               buffer.
1453 *
1454 * @return
1455 *               - XST_SUCCESS on success
1456 *               - XST_DEVICE_BUSY if DMA is busy
1457 *               - XST_FAILURE on other failures
1458 *
1459 * @note         None.
1460 *
1461 ****************************************************************************/
1462 int XDmaPs_Start(XDmaPs *InstPtr, unsigned int Channel,
1463                   XDmaPs_Cmd *Cmd,
1464                   int HoldDmaProg)
1465 {
1466         int Status;
1467         u32 DmaProg = 0;
1468         u32 Inten;
1469
1470         Xil_AssertNonvoid(InstPtr != NULL);
1471         Xil_AssertNonvoid(Cmd != NULL);
1472
1473
1474         Cmd->DmaStatus = XST_FAILURE;
1475
1476         if (XDmaPs_IsActive(InstPtr, Channel))
1477                 return XST_DEVICE_BUSY;
1478
1479         if (!Cmd->UserDmaProg && !Cmd->GeneratedDmaProg) {
1480                 Status = XDmaPs_GenDmaProg(InstPtr, Channel, Cmd);
1481                 if (Status)
1482                         return XST_FAILURE;
1483         }
1484
1485         InstPtr->Chans[Channel].HoldDmaProg = HoldDmaProg;
1486
1487         if (Cmd->UserDmaProg)
1488                 DmaProg = (u32)Cmd->UserDmaProg;
1489         else if (Cmd->GeneratedDmaProg)
1490                 DmaProg = (u32)Cmd->GeneratedDmaProg;
1491
1492         if (DmaProg) {
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,
1499                                  Inten);
1500                 Inten = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1501                                 XDMAPS_INTEN_OFFSET);
1502
1503                 InstPtr->Chans[Channel].DmaCmdToHw = Cmd;
1504
1505                 if (Cmd->ChanCtrl.SrcInc) {
1506                         Xil_DCacheFlushRange(Cmd->BD.SrcAddr, Cmd->BD.Length);
1507                 }
1508                 if (Cmd->ChanCtrl.DstInc) {
1509                         Xil_DCacheInvalidateRange(Cmd->BD.DstAddr,
1510                                         Cmd->BD.Length);
1511                 }
1512
1513                 Status = XDmaPs_Exec_DMAGO(InstPtr->Config.BaseAddress,
1514                                             Channel, DmaProg);
1515         }
1516         else {
1517                 InstPtr->Chans[Channel].DmaCmdToHw = NULL;
1518                 Status = XST_FAILURE;
1519         }
1520
1521         return Status;
1522 }
1523
1524 /****************************************************************************/
1525 /**
1526 *
1527 * Checks  whether the DMA channel is active or idle.
1528 *
1529 * @param        InstPtr is the DMA instance.
1530 * @param        Channel is the DMA channel number.
1531 *
1532 * @return       0: if the channel is idle
1533 *               1: otherwise
1534 *
1535 * @note         None.
1536 *
1537 *****************************************************************************/
1538 int XDmaPs_IsActive(XDmaPs *InstPtr, unsigned int Channel)
1539 {
1540         Xil_AssertNonvoid(InstPtr != NULL);
1541
1542         /* Need to assert Channel is in range */
1543         if (Channel > XDMAPS_CHANNELS_PER_DEV)
1544                 return  0;
1545
1546         return InstPtr->Chans[Channel].DmaCmdToHw != NULL;
1547 }
1548
1549
1550
1551 /****************************************************************************/
1552 /**
1553 *
1554 * Allocate a buffer of the DMA program buffer from the pool.
1555 *
1556 * @param        Pool the DMA program pool.
1557 *
1558 * @return       The allocated buffer, NULL if there is any error.
1559 *
1560 * @note         None.
1561 *
1562 *****************************************************************************/
1563 static void *XDmaPs_BufPool_Allocate(XDmaPs_ProgBuf *Pool)
1564 {
1565         int Index;
1566
1567         Xil_AssertNonvoid(Pool != NULL);
1568
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;
1573                 }
1574         }
1575
1576         return NULL;
1577
1578 }
1579
1580 /*****************************************************************************/
1581 /**
1582 *
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
1586 *
1587 * @param        InstPtr is the DMA instance.
1588 *
1589 * @return       None.
1590 *
1591 * @note         None.
1592 *
1593 ******************************************************************************/
1594 void XDmaPs_DoneISR_0(XDmaPs *InstPtr)
1595 {
1596         XDmaPs_DoneISR_n(InstPtr, 0);
1597 }
1598
1599 /*****************************************************************************/
1600 /**
1601 *
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
1605 *
1606 * @param        InstPtr is the DMA instance.
1607 *
1608 * @return       None.
1609 *
1610 * @note         None.
1611 *
1612 ******************************************************************************/
1613 void XDmaPs_DoneISR_1(XDmaPs *InstPtr)
1614 {
1615         XDmaPs_DoneISR_n(InstPtr, 1);
1616 }
1617
1618 /*****************************************************************************/
1619 /**
1620 *
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
1624 *
1625 * @param        InstPtr is the DMA instance.
1626 *
1627 * @return       None.
1628 *
1629 * @note         None.
1630 *
1631 ******************************************************************************/
1632 void XDmaPs_DoneISR_2(XDmaPs *InstPtr)
1633 {
1634         XDmaPs_DoneISR_n(InstPtr, 2);
1635 }
1636
1637 /*****************************************************************************/
1638 /**
1639 *
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
1643 *
1644 * @param        InstPtr is the DMA instance.
1645 *
1646 * @return       None.
1647 *
1648 * @note         None.
1649 *
1650 ******************************************************************************/
1651 void XDmaPs_DoneISR_3(XDmaPs *InstPtr)
1652 {
1653         XDmaPs_DoneISR_n(InstPtr, 3);
1654 }
1655
1656 /*****************************************************************************/
1657 /**
1658 *
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
1662 *
1663 * @param        InstPtr is the DMA instance.
1664 *
1665 * @return       None.
1666 *
1667 * @note         None.
1668 *
1669 ******************************************************************************/
1670 void XDmaPs_DoneISR_4(XDmaPs *InstPtr)
1671 {
1672         XDmaPs_DoneISR_n(InstPtr, 4);
1673 }
1674
1675 /*****************************************************************************/
1676 /**
1677 *
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
1681 *
1682 * @param        InstPtr is the DMA instance.
1683 *
1684 * @return       None.
1685 *
1686 * @note         None.
1687 *
1688 ******************************************************************************/
1689 void XDmaPs_DoneISR_5(XDmaPs *InstPtr)
1690 {
1691         XDmaPs_DoneISR_n(InstPtr, 5);
1692 }
1693
1694 /*****************************************************************************/
1695 /**
1696 *
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
1700 *
1701 * @param        InstPtr is the DMA instance.
1702 *
1703 * @return       None.
1704 *
1705 * @note         None.
1706 *
1707 ******************************************************************************/
1708 void XDmaPs_DoneISR_6(XDmaPs *InstPtr)
1709 {
1710         XDmaPs_DoneISR_n(InstPtr, 6);
1711 }
1712
1713 /*****************************************************************************/
1714 /**
1715 *
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
1719 *
1720 * @param        InstPtr is the DMA instance.
1721 *
1722 * @return       None.
1723 *
1724 * @note         None.
1725 *
1726 ******************************************************************************/
1727 void XDmaPs_DoneISR_7(XDmaPs *InstPtr)
1728 {
1729         XDmaPs_DoneISR_n(InstPtr, 7);
1730 }
1731
1732 #ifndef XDMAPS_MAX_WAIT
1733 #define XDMAPS_MAX_WAIT 4000
1734 #endif
1735
1736 /****************************************************************************/
1737 /**
1738 * Use the debug registers to kill the DMA thread.
1739 *
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.
1744 *
1745 * @return       0 on success, -1 on time out
1746 *
1747 * @note         None.
1748 *
1749 *****************************************************************************/
1750 static int XDmaPs_Exec_DMAKILL(u32 BaseAddr,
1751                                 unsigned int Channel,
1752                                 unsigned int Thread)
1753 {
1754         u32 DbgInst0;
1755         int WaitCount;
1756
1757         DbgInst0 = XDmaPs_DBGINST0(0, 0x01, Channel, Thread);
1758
1759         /* wait while debug status is busy */
1760         WaitCount = 0;
1761         while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET)
1762                & XDMAPS_DBGSTATUS_BUSY)
1763                && (WaitCount < XDMAPS_MAX_WAIT))
1764                 WaitCount++;
1765
1766         if (WaitCount >= XDMAPS_MAX_WAIT) {
1767                 /* wait time out */
1768                 xil_printf("PL330 device at %x debug status busy time out\n",
1769                        BaseAddr);
1770
1771                 return -1;
1772         }
1773
1774         /* write debug instruction 0 */
1775         XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST0_OFFSET, DbgInst0);
1776
1777         XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGINST1_OFFSET, 0);
1778
1779
1780         /* run the command in DbgInst0 and DbgInst1 */
1781         XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0);
1782
1783         return 0;
1784 }
1785
1786 /****************************************************************************/
1787 /**
1788 *
1789 *
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.
1793 *
1794 * @return       None
1795 *
1796 * @note         None.
1797 *
1798 *****************************************************************************/
1799 static void XDmaPs_BufPool_Free(XDmaPs_ProgBuf *Pool, void *Buf)
1800 {
1801         int Index;
1802         Xil_AssertVoid(Pool != NULL);
1803
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;
1808                         }
1809                 }
1810         }
1811 }
1812
1813 /*****************************************************************************/
1814 /**
1815 * XDmaPs_Exec_DMAGO - Execute the DMAGO to start a channel.
1816 *
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
1820 *
1821 * @return       0 on success, -1 on time out
1822 *
1823 * @note         None.
1824 *
1825 ****************************************************************************/
1826 static int XDmaPs_Exec_DMAGO(u32 BaseAddr, unsigned int Channel, u32 DmaProg)
1827 {
1828         char DmaGoProg[8];
1829         u32 DbgInst0;
1830         u32 DbgInst1;
1831
1832         int WaitCount;
1833
1834         XDmaPs_Instr_DMAGO(DmaGoProg, Channel, DmaProg, 0);
1835
1836         DbgInst0 = XDmaPs_DBGINST0(*(DmaGoProg + 1), *DmaGoProg, 0, 0);
1837         DbgInst1 = (u32)DmaProg;
1838
1839         /* wait while debug status is busy */
1840         WaitCount = 0;
1841         while ((XDmaPs_ReadReg(BaseAddr, XDMAPS_DBGSTATUS_OFFSET)
1842                & XDMAPS_DBGSTATUS_BUSY)
1843                && (WaitCount < XDMAPS_MAX_WAIT)) {
1844
1845                 WaitCount++;
1846         }
1847
1848         if (WaitCount >= XDMAPS_MAX_WAIT) {
1849                 xil_printf("PL330 device at %x debug status busy time out\r\n",
1850                            BaseAddr);
1851                 return -1;
1852         }
1853
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);
1858
1859
1860         /* wait while the DMA Manager is busy */
1861         WaitCount = 0;
1862         while ((XDmaPs_ReadReg(BaseAddr,
1863                                 XDMAPS_DS_OFFSET) & XDMAPS_DS_DMA_STATUS)
1864                != XDMAPS_DS_DMA_STATUS_STOPPED
1865                && WaitCount <= XDMAPS_MAX_WAIT) {
1866                 WaitCount++;
1867         }
1868
1869         if (WaitCount >= XDMAPS_MAX_WAIT) {
1870                 xil_printf("PL330 device at %x debug status busy time out\r\n",
1871                            BaseAddr);
1872                 return -1;
1873         }
1874
1875         /* run the command in DbgInst0 and DbgInst1 */
1876         XDmaPs_WriteReg(BaseAddr, XDMAPS_DBGCMD_OFFSET, 0);
1877
1878         return 0;
1879 }
1880
1881
1882 /****************************************************************************/
1883 /**
1884 *
1885 * It's the generic Done ISR.
1886 * @param        InstPtr is the DMA instance.
1887 * @param        Channel is the DMA channel numer.
1888 *
1889 * @return       None.*
1890 *
1891 * @note         None.
1892 *
1893 *****************************************************************************/
1894 static void XDmaPs_DoneISR_n(XDmaPs *InstPtr, unsigned Channel)
1895 {
1896
1897         void *DmaProgBuf;
1898         XDmaPs_ChannelData *ChanData;
1899         XDmaPs_Cmd *DmaCmd;
1900         //u32 Value;
1901
1902         ChanData = InstPtr->Chans + Channel;
1903
1904         /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1905                         XDMAPS_INTSTATUS_OFFSET);*/
1906
1907         /* clear the interrupt status */
1908         XDmaPs_WriteReg(InstPtr->Config.BaseAddress,
1909                         XDMAPS_INTCLR_OFFSET,
1910                         1 << ChanData->ChanId);
1911
1912         /*Value = XDmaPs_ReadReg(InstPtr->Config.BaseAddress,
1913                         XDMAPS_INTSTATUS_OFFSET);*/
1914
1915
1916         DmaCmd = ChanData->DmaCmdToHw;
1917         if (DmaCmd) {
1918                 if (!ChanData->HoldDmaProg) {
1919                         DmaProgBuf = (void *)DmaCmd->GeneratedDmaProg;
1920                         if (DmaProgBuf)
1921                                 XDmaPs_BufPool_Free(ChanData->ProgBufPool,
1922                                                      DmaProgBuf);
1923                         DmaCmd->GeneratedDmaProg = NULL;
1924                 }
1925
1926                 DmaCmd->DmaStatus = 0;
1927                 ChanData->DmaCmdToHw = NULL;
1928                 ChanData->DmaCmdFromHw = DmaCmd;
1929
1930                 if (ChanData->DoneHandler)
1931                         ChanData->DoneHandler(Channel, DmaCmd,
1932                                               ChanData->DoneRef);
1933         }
1934
1935 }
1936
1937
1938 /****************************************************************************/
1939 /**
1940 * Prints the content of the buffer in bytes
1941 * @param        Buf is the buffer.
1942 * @param        Length is the length of the DMA program.
1943 *
1944 * @return       None.
1945 *
1946 * @note         None.
1947 ****************************************************************************/
1948 static void XDmaPs_Print_DmaProgBuf(char *Buf, int Length)
1949 {
1950         int Index;
1951         for (Index = 0; Index < Length; Index++)
1952                 xil_printf("[%x] %x\r\n", Index, Buf[Index]);
1953
1954 }
1955 /****************************************************************************/
1956 /**
1957 * Print the Dma Prog Contents.
1958 *
1959 * @param        Cmd is the command buffer.
1960 *
1961 * @return       None.
1962 *
1963 * @note         None.
1964 *
1965 *****************************************************************************/
1966  void XDmaPs_Print_DmaProg(XDmaPs_Cmd *Cmd)
1967 {
1968         if (Cmd->GeneratedDmaProg && Cmd->GeneratedDmaProgLength) {
1969                 xil_printf("Generated DMA program (%d):\r\n",
1970                            Cmd->GeneratedDmaProgLength);
1971                 XDmaPs_Print_DmaProgBuf((char *)Cmd->GeneratedDmaProg,
1972                                          Cmd->GeneratedDmaProgLength);
1973         }
1974
1975         if (Cmd->UserDmaProg && Cmd->UserDmaProgLength) {
1976                 xil_printf("User defined DMA program (%d):\r\n",
1977                            Cmd->UserDmaProgLength);
1978                 XDmaPs_Print_DmaProgBuf((char *)Cmd->UserDmaProg,
1979                                          Cmd->UserDmaProgLength);
1980         }
1981 }
1982
1983
1984 /** @} */