]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/edma3_lld.git/blob - examples/CSL2_DAT_DEMO/src/dat_edma3LLD/csl2_dat.c
Minor fixes in DAT example
[keystone-rtos/edma3_lld.git] / examples / CSL2_DAT_DEMO / src / dat_edma3LLD / csl2_dat.c
1 /*
2  * csl2_dat.c
3  *
4  * Implements the CSL DAT2 API using EDMA3 Driver and Resource Manager Package
5  * (EDMA3LLD). Behaviour mimics DAT2 on EDMA2 hardware.
6  *
7  * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
8  *
9  *
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions
12  *  are met:
13  *
14  *    Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  *
17  *    Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the
20  *    distribution.
21  *
22  *    Neither the name of Texas Instruments Incorporated nor the names of
23  *    its contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *
38 */
40 #include <stdio.h>
41 #include <csl_dat.h>
43 /*
44  * Includes for accessing EDMA3 DRV and RM layer
45  */
46 #include <ti/sdo/edma3/drv/edma3_drv.h>
49 /*
50  * Include for setting up the EDMA3 LLD
51  */
52 #include <csl2_dat_edma3lld.h>
55 /*
56  * extern declarations
57  */
59 /*
60  * OS dependent functions, that must be implemented by user of CSL DAT adapter
61  * These functions mark the entry and exit to critical sections of the code
62  */
63 extern void _dat_critical_section_enter();
64 extern void _dat_critical_section_exit();
66 /*
67  * Flag to indicate if EDMA3 LLD was initialized before calling the DAT APIs
68  */
69 extern int DAT_EDMA3LLD_initCalled;
71 /*
72  * typedef declarations
73  */
75 typedef struct DAT_EDMA3LLD_ChannelDesc {
77     /* Holds the param number allocated */
78     Uint32 paramNo;
80     /* Holds the tcc number allocated */
81     Uint32 tccNo;
83 }  DAT_EDMA3LLD_ChannelDesc;
85 /*
86  * static variable definitions
87  */
89 /*
90  * Max size array to hold the allocated resources for DAT
91  */
92 static DAT_EDMA3LLD_ChannelDesc
93         DAT_allocatedChannels[DAT_EDMA3LLD_HW_MAXPHYCHANNELS];
94 /*
95  * Flag to indicate that the DAT instance has been opened
96  */
97 static Uint32 DAT_EDMA3LLD_openFlag = 0;
99 /*
100  * 64 bit internal Transfer completion register, used to hold status
101  * of the channel
102  * It has a bit set to one whenever a Transfer is submitted, and cleared
103  * when it completes
104  */
105 static volatile Uint32 TransferCompleteH = 0x0;
106 static volatile Uint32 TransferCompleteL = 0x0;
108 /*
109  * Set to the last allocated bit index number in the TransferComplete fxn
110  */
111 static Uint32 lastAllocatedIndex = DAT_INVALID_ID;
113 /*
114  * static function declarations
115  */
116 /*
117  * Obtain the next free channel from available channels
118  */
119 static inline Uint32 _getFreeChannel(Uint32 *tccNum);
121 /*
122  * global variable definitions
123  */
125 /*
126  * Holds the EDMA3 driver handle
127  */
128 EDMA3_DRV_Handle DAT_EDMA3LLD_hEdma = NULL;
130 /*
131  * number of EDMA3 channels allocated for the DAT module
132  */
133 int DAT_EDMA3LLD_numAllocatedChannels = 0;
136 /*
137  * global function definitions
138  */
141 /*
142  *  ======== DAT_open =========
143  * Opens the DAT module, called before all other DAT APIs
144  * Ignore all paramters of DAT_open, open any channel,
145  * all channels are opened with equal priority
146  * All channels can be used in 2D mode etc, flags are not applicable
147  */
148 int DAT_open(int chNum, int priority, Uint32 flags) {
150     int i = 0;
151     int j = 0;
152     Uint32 chaNum = DAT_INVALID_ID;
153     Uint32 tccNum = DAT_INVALID_ID;
155     chNum = chNum;
156     priority = priority;
157     flags = flags;
159     /*
160      * Ensure _initCalled is called before DAT_open
161      * Also ensure DAT_open is called only once
162      */
163     _dat_critical_section_enter();
165     if (DAT_EDMA3LLD_initCalled == 0) {
166         _dat_critical_section_exit();
167         return 0;
168     }
170     if (1 == DAT_EDMA3LLD_openFlag) {
171         _dat_critical_section_exit();
172         return 0;
173     }
174     DAT_EDMA3LLD_openFlag = 1;
175     _dat_critical_section_exit();
177     /*
178      * Request default number of channels and Tccs from the EDMA3 DRV package
179      */
180     for(i=0; i < DAT_EDMA3LLD_numAllocatedChannels; i++) {
181         chaNum = EDMA3_DRV_QDMA_CHANNEL_ANY;
182         tccNum = EDMA3_DRV_TCC_ANY;
184         /*
185          * EDMA3 DRV call to request for channel and tcc resources
186          */
187         if (EDMA3_DRV_SOK != EDMA3_DRV_requestChannel(DAT_EDMA3LLD_hEdma,
188                 &chaNum, &tccNum,
189                 (EDMA3_RM_EventQueue)DAT_EDMA3LLD_HW_EVT_QUEUE_ID,
190                 NULL /*(EDMA3_RM_TccCallback)&_transferComplete*/, NULL)) {
192             /*
193              * Error requesting channels, Clean up all channels requested so far
194              */
195             for(j = i-1; j >=0; j--) {
196                 EDMA3_DRV_freeChannel(DAT_EDMA3LLD_hEdma,
197                     DAT_allocatedChannels[j].paramNo);
198                 DAT_allocatedChannels[i].paramNo = DAT_INVALID_ID;
199                 DAT_allocatedChannels[i].tccNo = DAT_INVALID_ID;
200             }
202             if (EDMA3_DRV_SOK != EDMA3_DRV_close(DAT_EDMA3LLD_hEdma, NULL)){
203                 printf("Error closing DRV instance \n");
204             }
205             else {
206                 if (EDMA3_DRV_SOK != EDMA3_DRV_delete(DAT_EDMA3LLD_HW_INST_ID,
207                     NULL)){
208                     printf("Error deleting EDMA3 DRV\n");
209                 }
210             }
212             DAT_EDMA3LLD_openFlag = 0;
213             return 0;
214         }
216         /*
217          * Store the allocated Channels in an array
218          */
219         /* DMA/QDMA Channel */
220         DAT_allocatedChannels[i].paramNo = chaNum;
221         /* TCC */
222         DAT_allocatedChannels[i].tccNo = tccNum;
223     }
225     return 1;
228 /*
229  *  ======== DAT_close =========
230  * Close the DAT module
231  */
232 void DAT_close() {
233     int i = 0;
235     /*
236      * Ensure DAT_open was called
237      */
238     _dat_critical_section_enter();
239     if (DAT_EDMA3LLD_openFlag == 0)
240     {
241         _dat_critical_section_exit();
242         return;
243     }
244     DAT_EDMA3LLD_openFlag = 0;
245     _dat_critical_section_exit();
247     /*
248      * Wait for all pending transfers to complete
249      */
250     DAT_wait(DAT_XFRID_WAITALL);
252     /*
253      * Free all requested channels
254      */
255     for(i=0; i < DAT_EDMA3LLD_numAllocatedChannels; i++) {
256         EDMA3_DRV_freeChannel(DAT_EDMA3LLD_hEdma,
257                 DAT_allocatedChannels[i].paramNo);
258         DAT_allocatedChannels[i].paramNo = DAT_INVALID_ID;
259         DAT_allocatedChannels[i].tccNo = DAT_INVALID_ID;
260     }
264 /*
265  *  ======== DAT_copy =========
266  * One dimensional copy from source to destination of byteCnt bytes
267  */
268 Uint32 DAT_copy(void *src, void *dst, Uint16 byteCnt ) {
269     Uint32 chNum = 0;
270     Uint32 tccNum = 0;
271     EDMA3_DRV_PaRAMRegs paramSet = {0,0,0,0,0,0,0,0,0,0,0,0};
273     /*
274      * An alternate way to setup the params
275      * EDMA3_DRV_PaRAMRegs param;
276      * const EDMA3_DRV_PaRAMRegs *newPaRAM = &param;
277      */
279     /*
280      * Obtain a free channel
281      * This call spins till a free channel is obtained
282      */
283     chNum = _getFreeChannel(&tccNum);
285     /*
286      * Set up Transfer Paramters for this channel
287      */
288     /* Fill the PaRAM Set with transfer specific information */
289     paramSet.srcAddr    = (unsigned int)(src);
290     paramSet.destAddr   = (unsigned int)(dst);
291     paramSet.srcBIdx    = 0;
292     paramSet.destBIdx   = 0;
293     paramSet.srcCIdx    = 0;
294     paramSet.destCIdx   = 0;
295     paramSet.aCnt       = byteCnt;
296     paramSet.bCnt       = 1;
297         /* Trigger word is CCNT */
298     paramSet.cCnt       = 1;
299     paramSet.bCntReload = 0;
300     paramSet.linkAddr   = 0xFFFFu;
301     /* Src & Dest are in INCR modes */
302     paramSet.opt &= 0xFFFFFFFCu;
303     /* Program the TCC */
304     paramSet.opt |= ((tccNum << OPT_TCC_SHIFT) & OPT_TCC_MASK);
305     /* Enable Final transfer completion interrupt */
306     paramSet.opt |= (1 << OPT_TCINTEN_SHIFT);
307         /* AB Sync Transfer Mode */
308     paramSet.opt |= (1 << OPT_SYNCDIM_SHIFT);
309         /* Set the static bit */
310     paramSet.opt |= (1 << OPT_STATIC_SHIFT);
312     /*
313      * Set a 1 bit in the TransferComplete register corresponding to the tcc
314      */
315     if (tccNum < 32) {
316         SET_REGISTER32_BIT(TransferCompleteL,tccNum);
317     }
318     else {
319         SET_REGISTER32_BIT(TransferCompleteH,tccNum - 32);
320     }
322         /* trigger the transfer */
323         EDMA3_DRV_setPaRAM(DAT_EDMA3LLD_hEdma, chNum, &paramSet);
325         return tccNum;
329 /*
330  *  ======== DAT_copy2d =========
331  * 2-dimensional copy from src to dst of lineCnt lines each of length lineLen
332  * bytes. The pitch for the second dimension is linePitch bytes
333  */
334 Uint32 DAT_copy2d(Uint32 type, void *src, void *dst, Uint16 lineLen,
335         Uint16 lineCnt, Uint16 linePitch) {
336     Uint32 chNum = 0;
337     Uint32 tccNum = 0;
338     EDMA3_DRV_PaRAMRegs paramSet = {0,0,0,0,0,0,0,0,0,0,0,0};
340     /*
341      * Obtain a free channel
342      */
343     chNum = _getFreeChannel(&tccNum);
345     /* Fill the PaRAM Set with transfer specific information */
346     paramSet.srcAddr    = (unsigned int)(src);
347     paramSet.destAddr   = (unsigned int)(dst);
348     paramSet.aCnt       = lineLen;
349     paramSet.bCnt       = lineCnt;
350         /* Trigger word is CCNT */
351     paramSet.cCnt       = 1;
352     paramSet.bCntReload = 0;
353     paramSet.linkAddr   = 0xFFFFu;
354     /* Src & Dest are in INCR modes */
355     paramSet.opt &= 0xFFFFFFFCu;
356     /* Program the TCC */
357     paramSet.opt |= ((tccNum << OPT_TCC_SHIFT) & OPT_TCC_MASK);
358     /* Enable Final transfer completion interrupt */
359     paramSet.opt |= (1 << OPT_TCINTEN_SHIFT);
360         /* AB Sync Transfer Mode */
361     paramSet.opt |= (1 << OPT_SYNCDIM_SHIFT);
362         /* Set the static bit */
363     paramSet.opt |= (1 << OPT_STATIC_SHIFT);
365     /*
366      * Depending on type of transfer set the src and dest BIdx
367      * Different types of transfers differ only in the Src and Dst BIdx-es
368      */
369     switch (type) {
370         case DAT_1D2D:
371                     paramSet.srcBIdx    = lineLen;
372                     paramSet.destBIdx   = linePitch;
373                     paramSet.srcCIdx    = 0;
374                     paramSet.destCIdx   = 0;
375             break;
376         case DAT_2D1D:
377                     paramSet.srcBIdx    = linePitch;
378                     paramSet.destBIdx   = lineLen;
379                     paramSet.srcCIdx    = 0;
380                     paramSet.destCIdx   = 0;
381             break;
382         case DAT_2D2D:
383                     paramSet.srcBIdx    = linePitch;
384                     paramSet.destBIdx   = linePitch;
385                     paramSet.srcCIdx    = 0;
386                     paramSet.destCIdx   = 0;
387             break;
388     }
390     /*
391      * Set a 1 bit in the TransferComplete register corresponding to the tcc
392      */
393     if (tccNum < 32) {
394         SET_REGISTER32_BIT(TransferCompleteL,tccNum);
395     }
396     else {
397         SET_REGISTER32_BIT(TransferCompleteH,tccNum - 32);
398     }
400         /* trigger the transfer */
401         EDMA3_DRV_setPaRAM(DAT_EDMA3LLD_hEdma, chNum, &paramSet);
403         return tccNum;
407 /*
408  *  ======== DAT_fill =========
409  * Fills up dst with byteCnt bytes of the pattern pointed to be 'value'
410  */
411 Uint32 DAT_fill(void *dst, Uint16 byteCnt, Uint32 *value) {
412     Uint32 chNum = 0;
413     Uint32 tccNum = 0;
414     EDMA3_DRV_PaRAMRegs paramSet = {0,0,0,0,0,0,0,0,0,0,0,0};
416     /*
417      * Obtain a free channel
418      */
419     chNum = _getFreeChannel(&tccNum);
421     /* Fill the PaRAM Set with transfer specific information */
422     paramSet.srcAddr    = (unsigned int)(value);
423     paramSet.destAddr   = (unsigned int)(dst);
424     paramSet.srcBIdx    = 0;
425     paramSet.destBIdx   = 8;
426     paramSet.srcCIdx    = 0;
427     paramSet.destCIdx   = 0;
428     paramSet.aCnt       = 8;
429     paramSet.bCnt       = byteCnt>>3;
430         /* Trigger word is CCNT */
431     paramSet.cCnt       = 1;
432     paramSet.bCntReload = 0;
433     paramSet.linkAddr   = 0xFFFFu;
434     /* Src & Dest are in INCR modes */
435     paramSet.opt &= 0xFFFFFFFCu;
436     /* Program the TCC */
437     paramSet.opt |= ((tccNum << OPT_TCC_SHIFT) & OPT_TCC_MASK);
438     /* Enable Final transfer completion interrupt */
439     paramSet.opt |= (1 << OPT_TCINTEN_SHIFT);
440         /* AB Sync Transfer Mode */
441     paramSet.opt |= (1 << OPT_SYNCDIM_SHIFT);
442         /* Set the static bit */
443     paramSet.opt |= (1 << OPT_STATIC_SHIFT);
445     /*
446      * Set a 1 bit in the TransferComplete register corresponding to the tcc
447      */
448     if (tccNum < 32) {
449         SET_REGISTER32_BIT(TransferCompleteL,tccNum);
450     }
451     else {
452         SET_REGISTER32_BIT(TransferCompleteH,tccNum - 32);
453     }
455         /* trigger the transfer */
456         EDMA3_DRV_setPaRAM(DAT_EDMA3LLD_hEdma, chNum, &paramSet);
458         return tccNum;
463 /*
464  *  ======== DAT_wait =========
465  * Wait for the transfer identified by waitId, to complete
466  */
467 void DAT_wait(Uint32 waitId) {
468         int i;
469         Uint32 tcc;
471     /*
472      * If both the registers are zero, we're done !!
473      */
474     if (0x0 == (TransferCompleteL | TransferCompleteH)) {
475         return;
476     }
478     /*
479      * Check if we need to wait for all transfers or just this one ?
480      */
481     if (DAT_XFRID_WAITALL == waitId) {
482                 for (i = 0 ; i < DAT_EDMA3LLD_numAllocatedChannels; i++) {
483                         tcc = DAT_allocatedChannels[i].tccNo;
484                         if (tcc < 32) {
485                                 if (GET_REGISTER32_BIT(TransferCompleteL, tcc)) {
486                                         EDMA3_DRV_waitAndClearTcc (DAT_EDMA3LLD_hEdma, tcc);
487                                         CLEAR_REGISTER32_BIT(TransferCompleteL, tcc);
488                                 }
489                         } else {
490                                 if (GET_REGISTER32_BIT(TransferCompleteH, tcc - 32)) {
491                                         EDMA3_DRV_waitAndClearTcc (DAT_EDMA3LLD_hEdma, tcc);
492                                         CLEAR_REGISTER32_BIT(TransferCompleteH, tcc - 32);
493                                 }
494                         }
495                 }
496     } else {
497         EDMA3_DRV_waitAndClearTcc (DAT_EDMA3LLD_hEdma, waitId);
499                 /*
500              * Mark zero in bit position tccNum
501              */
502             if (waitId < 32) {
503                 CLEAR_REGISTER32_BIT(TransferCompleteL, waitId );
504             }
505             else {
506                 CLEAR_REGISTER32_BIT(TransferCompleteH, waitId -32 );
507             }
508         }
511 /*
512  *  ======== DAT_busy =========
513  * Check the busy status of transfer identified by waitId
514  */
515 int DAT_busy(Uint32 waitId) {
516         Uint16 status = 0;
518     /*
519      * Check if the particular transfer has completed by returning the status
520      * from the itnernal completion register
521      */
522     if (waitId < 32) {
523         if (GET_REGISTER32_BIT(TransferCompleteL,waitId)) {
524                         /** Bit is still set, check in the IPR and clear it
525                          * if the xfer has finished. Clear the local reg too.
526                          * Else leave everything like that
527                          */
528                         EDMA3_DRV_checkAndClearTcc(DAT_EDMA3LLD_hEdma, waitId, &status);
529                         if (status == 1) {
530                                 /* xfer finished, update local reg */
531                                 CLEAR_REGISTER32_BIT(TransferCompleteL, waitId);
532                                 return 0;
533                         } else {
534                                 /* xfer not finished, leave... */
535                                 return 1;
536                         }
538         } else
539                 return 0;
540     }
541     else {
542         if (GET_REGISTER32_BIT(TransferCompleteH,waitId - 32)) {
543                         EDMA3_DRV_checkAndClearTcc(DAT_EDMA3LLD_hEdma, waitId, &status);
544                         if (status == 1) {
545                                 CLEAR_REGISTER32_BIT(TransferCompleteH, waitId - 32);
546                                 return 0;
547                         } else {
548                                 return 1;
549                         }
550         } else
551                 return 0;
552     }
555 /*
556  * static function definitions
557  */
559 /*
560  *  ======== _getFreeChannel =========
561  * Used to obtain the next available channel to set up a new transfer
562  * Function spins till a channel becomes available
563  */
564 static inline Uint32 _getFreeChannel(Uint32 *tccNum) {
565     Uint32 chNum,index ;
566         Uint16 status=0;
568     /*
569      * Start looking for available channels from the index after the one
570      * that was allocated previously
571      */
572     index = (lastAllocatedIndex + 1)%(DAT_EDMA3LLD_numAllocatedChannels);
574     /*
575      * Spins till a free bit in TransferComplete is found
576      */
577     while (1) {
578         *tccNum = DAT_allocatedChannels[index].tccNo;
580         if (*tccNum < 32) {
581             if((GET_REGISTER32_BIT(TransferCompleteL,*tccNum)) == 0) {
582                                 /* tcc not allocated or already freed */
583                 chNum = DAT_allocatedChannels[index].paramNo;
584                 lastAllocatedIndex = index;
585                 return chNum;
586             } else {
587                     /** Tcc allocated but not yet freed, check the IPR bit now
588                      * corresponding to this tcc
589                      * if the bit is set, it means that xfer has finished
590                      * so clear it and use this tcc
591                      * else leave it like that
592                                  */
593                 EDMA3_DRV_checkAndClearTcc(DAT_EDMA3LLD_hEdma, *tccNum, &status);
594                                 if (1 == status)
595                                         {
596                                         /* xfer completed, IPR cleared too */
597                                         chNum = DAT_allocatedChannels[index].paramNo;
598                             lastAllocatedIndex = index;
600                                         /* clear the reg too */
601                                         CLEAR_REGISTER32_BIT(TransferCompleteL, *tccNum);
602                             return chNum;
603                                         }
604             }
606         }
607         else {
608             if((GET_REGISTER32_BIT(TransferCompleteH,*tccNum - 32)) == 0) {
609                 chNum = DAT_allocatedChannels[index].paramNo;
610                 lastAllocatedIndex = index;
611                 return chNum;
612             } else {
613                 EDMA3_DRV_checkAndClearTcc(DAT_EDMA3LLD_hEdma, *tccNum, &status);
614                                 if (1 == status)
615                                         {
616                                         chNum = DAT_allocatedChannels[index].paramNo;
617                             lastAllocatedIndex = index;
619                                         CLEAR_REGISTER32_BIT(TransferCompleteH, *tccNum - 32);
620                             return chNum;
621                                         }
622             }
623         }
625         /*
626          * Increment index
627          */
628         index = (index + 1)%(DAT_EDMA3LLD_numAllocatedChannels);
629     }