OpenCores
URL https://opencores.org/ocsvn/1g_ethernet_dpi/1g_ethernet_dpi/trunk

Subversion Repositories 1g_ethernet_dpi

[/] [1g_ethernet_dpi/] [tags/] [v0.0/] [sw/] [dev/] [test_main/] [src/] [_hdl/] [bsp/] [libsrc/] [axidma_v9_0/] [src/] [xaxidma.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 kuzmi4
/******************************************************************************
2
*
3
* Copyright (C) 2010 - 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 xaxidma.c
36
* @addtogroup axidma_v9_0
37
* @{
38
*
39
* This file implements DMA engine-wise initialization and control functions.
40
* For more information on the implementation of this driver, see xaxidma.h.
41
*
42
* <pre>
43
* MODIFICATION HISTORY:
44
*
45
* Ver   Who  Date     Changes
46
* ----- ---- -------- -------------------------------------------------------
47
* 1.00a jz   05/18/10 First release
48
* 2.00a jz   08/10/10 Second release, added in xaxidma_g.c, xaxidma_sinit.c,
49
*                     updated tcl file, added xaxidma_porting_guide.h
50
* 3.00a jz   11/22/10 Support IP core parameters change
51
* 4.00a rkv  02/22/11 Added support for simple DMA mode
52
*                     New API added for simple DMA mode are
53
*                       - XAxiDma_Busy
54
*                       - XAxiDma_SimpleTransfer
55
* 6.00a srt  01/24/12 Added support for Multi-Channel DMA mode.
56
*                     - Changed APIs:
57
*                       * XAxiDma_Start(XAxiDma * InstancePtr, int RingIndex)
58
*                       * XAxiDma_Started(XAxiDma * InstancePtr, int RingIndex)
59
*                       * XAxiDma_Pause(XAxiDma * InstancePtr, int RingIndex)
60
*                       * XAxiDma_Resume(XAxiDma * InstancePtr, int RingIndex)
61
*                       * XAxiDma_SimpleTransfer(XAxiDma *InstancePtr,
62
*                                               u32 BuffAddr, u32 Length,
63
*                                               int Direction, int RingIndex)
64
*                     - New API:
65
*                       * XAxiDma_SelectKeyHole(XAxiDma *InstancePtr,
66
*                                               int Direction, int Select)
67
* 7.00a srt  06/18/12  All the APIs changed in v6_00_a are reverted back for
68
*                      backward compatibility.
69
* 7.01a srt  10/26/12  Fixed issue with driver as it fails with IP version
70
*                      < 6.00a as the parameter C_NUM_*_CHANNELS is not
71
*                      applicable.
72
* 8.0   srt  01/29/14  Added support for Micro DMA Mode and Cyclic mode of
73
*                      operations.
74
*                     - New API:
75
*                       * XAxiDma_SelectCyclicMode(XAxiDma *InstancePtr,
76
*                                               int Direction, int Select)
77
*
78
* </pre>
79
******************************************************************************/
80
 
81
/***************************** Include Files *********************************/
82
 
83
#include "xaxidma.h"
84
 
85
/************************** Constant Definitions *****************************/
86
 
87
/* Loop counter to check reset done
88
 */
89
#define XAXIDMA_RESET_TIMEOUT   500
90
 
91
/**************************** Type Definitions *******************************/
92
 
93
 
94
/***************** Macros (Inline Functions) Definitions *********************/
95
 
96
 
97
/************************** Function Prototypes ******************************/
98
static int XAxiDma_Start(XAxiDma * InstancePtr);
99
static int XAxiDma_Started(XAxiDma * InstancePtr);
100
 
101
/************************** Variable Definitions *****************************/
102
 
103
/*****************************************************************************/
104
/**
105
 * This function initializes a DMA engine.  This function must be called
106
 * prior to using a DMA engine. Initializing a engine includes setting
107
 * up the register base address, setting up the instance data, and ensuring the
108
 * hardware is in a quiescent state.
109
 *
110
 * @param       InstancePtr is a pointer to the DMA engine instance to be
111
 *              worked on.
112
 * @param       Config is a pointer to an XAxiDma_Config structure. It contains
113
 *              the information about the hardware build, including base
114
 *              address,and whether status control stream (StsCntrlStrm), MM2S
115
 *              and S2MM are included in the build.
116
 *
117
 * @return
118
 *              - XST_SUCCESS for successful initialization
119
 *              - XST_INVALID_PARAM if pointer to the configuration structure
120
 *              is NULL
121
 *              - XST_DMA_ERROR if reset operation failed at the end of
122
 *              initialization
123
 *
124
 * @note        We assume the hardware building tool will check and error out
125
 *              for a hardware build that has no transfer channels.
126
 *****************************************************************************/
127
int XAxiDma_CfgInitialize(XAxiDma * InstancePtr, XAxiDma_Config *Config)
128
{
129
        u32 BaseAddr;
130
        int TimeOut;
131
        int Index;
132
        u32 MaxTransferLen;
133
 
134
        InstancePtr->Initialized = 0;
135
 
136
        if(!Config) {
137
                return XST_INVALID_PARAM;
138
        }
139
 
140
        BaseAddr = Config->BaseAddr;
141
 
142
        /* Setup the instance */
143
        memset(InstancePtr, 0, sizeof(XAxiDma));
144
        InstancePtr->RegBase = BaseAddr;
145
 
146
        /* Get hardware setting information from the configuration structure
147
         */
148
        InstancePtr->HasMm2S = Config->HasMm2S;
149
        InstancePtr->HasS2Mm = Config->HasS2Mm;
150
 
151
        InstancePtr->HasSg = Config->HasSg;
152
 
153
        InstancePtr->MicroDmaMode = Config->MicroDmaMode;
154
        InstancePtr->AddrWidth = Config->AddrWidth;
155
 
156
        /* Get the number of channels */
157
        InstancePtr->TxNumChannels = Config->Mm2sNumChannels;
158
        InstancePtr->RxNumChannels = Config->S2MmNumChannels;
159
 
160
        /* This condition is for IP version < 6.00a */
161
        if (!InstancePtr->TxNumChannels)
162
                InstancePtr->TxNumChannels = 1;
163
        if (!InstancePtr->RxNumChannels)
164
                InstancePtr->RxNumChannels = 1;
165
 
166
        if ((InstancePtr->RxNumChannels > 1) ||
167
                (InstancePtr->TxNumChannels > 1)) {
168
                MaxTransferLen =
169
                        XAXIDMA_MCHAN_MAX_TRANSFER_LEN;
170
        }
171
        else {
172
                MaxTransferLen =
173
                        XAXIDMA_MAX_TRANSFER_LEN;
174
        }
175
 
176
        /* Initialize the ring structures */
177
        InstancePtr->TxBdRing.RunState = AXIDMA_CHANNEL_HALTED;
178
        InstancePtr->TxBdRing.IsRxChannel = 0;
179
        if (!InstancePtr->MicroDmaMode) {
180
                InstancePtr->TxBdRing.MaxTransferLen = MaxTransferLen;
181
        }
182
        else {
183
                /* In MicroDMA mode, Maximum length that can be transferred
184
                 * is '(Memory Data Width / 4) * Burst Size'
185
                 */
186
                InstancePtr->TxBdRing.MaxTransferLen =
187
                                ((Config->Mm2SDataWidth / 4) *
188
                                 Config->Mm2SBurstSize);
189
        }
190
        InstancePtr->TxBdRing.RingIndex = 0;
191
 
192
        for (Index = 0; Index < InstancePtr->RxNumChannels; Index++) {
193
                InstancePtr->RxBdRing[Index].RunState
194
                                                 = AXIDMA_CHANNEL_HALTED;
195
                InstancePtr->RxBdRing[Index].IsRxChannel = 1;
196
                InstancePtr->RxBdRing[Index].RingIndex = Index;
197
        }
198
 
199
        if (InstancePtr->HasMm2S) {
200
                InstancePtr->TxBdRing.ChanBase =
201
                                BaseAddr + XAXIDMA_TX_OFFSET;
202
                InstancePtr->TxBdRing.HasStsCntrlStrm =
203
                                        Config->HasStsCntrlStrm;
204
                if (InstancePtr->AddrWidth > 32)
205
                        InstancePtr->TxBdRing.Addr_ext = 1;
206
                else
207
                        InstancePtr->TxBdRing.Addr_ext = 0;
208
 
209
                InstancePtr->TxBdRing.HasDRE = Config->HasMm2SDRE;
210
                InstancePtr->TxBdRing.DataWidth =
211
                        ((unsigned int)Config->Mm2SDataWidth >> 3);
212
        }
213
 
214
        if (InstancePtr->HasS2Mm) {
215
                for (Index = 0;
216
                        Index < InstancePtr->RxNumChannels; Index++) {
217
                        InstancePtr->RxBdRing[Index].ChanBase =
218
                                        BaseAddr + XAXIDMA_RX_OFFSET;
219
                        InstancePtr->RxBdRing[Index].HasStsCntrlStrm =
220
                                        Config->HasStsCntrlStrm;
221
                        InstancePtr->RxBdRing[Index].HasDRE =
222
                                        Config->HasS2MmDRE;
223
                        InstancePtr->RxBdRing[Index].DataWidth =
224
                        ((unsigned int)Config->S2MmDataWidth >> 3);
225
 
226
                        if (!InstancePtr->MicroDmaMode) {
227
                                InstancePtr->RxBdRing[Index].MaxTransferLen =
228
                                                        MaxTransferLen;
229
                        }
230
                        else {
231
                        /* In MicroDMA mode, Maximum length that can be transferred
232
                         * is '(Memory Data Width / 4) * Burst Size'
233
                         */
234
                                InstancePtr->RxBdRing[Index].MaxTransferLen =
235
                                                ((Config->S2MmDataWidth / 4) *
236
                                                Config->S2MmBurstSize);
237
                        }
238
                        if (InstancePtr->AddrWidth > 32)
239
                                InstancePtr->RxBdRing[Index].Addr_ext = 1;
240
                        else
241
                                InstancePtr->RxBdRing[Index].Addr_ext = 0;
242
                }
243
        }
244
 
245
        /* Reset the engine so the hardware starts from a known state
246
         */
247
        XAxiDma_Reset(InstancePtr);
248
 
249
        /* At the initialization time, hardware should finish reset quickly
250
         */
251
        TimeOut = XAXIDMA_RESET_TIMEOUT;
252
 
253
        while (TimeOut) {
254
 
255
                if(XAxiDma_ResetIsDone(InstancePtr)) {
256
                        break;
257
                }
258
 
259
                TimeOut -= 1;
260
 
261
        }
262
 
263
        if (!TimeOut) {
264
                xdbg_printf(XDBG_DEBUG_ERROR, "Failed reset in"
265
                                                        "initialize\r\n");
266
 
267
                /* Need system hard reset to recover
268
                 */
269
                InstancePtr->Initialized = 0;
270
                return XST_DMA_ERROR;
271
        }
272
 
273
        /* Initialization is successful
274
         */
275
        InstancePtr->Initialized = 1;
276
 
277
        return XST_SUCCESS;
278
}
279
 
280
/*****************************************************************************/
281
/**
282
* Reset both TX and RX channels of a DMA engine.
283
*
284
* Reset one channel resets the whole AXI DMA engine.
285
*
286
* Any DMA transaction in progress will finish gracefully before engine starts
287
* reset. Any other transactions that have been submitted to hardware will be
288
* discarded by the hardware.
289
*
290
* @param        InstancePtr is a pointer to the DMA engine instance to be
291
*               worked on.
292
*
293
* @return       None
294
*
295
* @note         After the reset:
296
*               - All interrupts are disabled.
297
*               - Engine is halted
298
*
299
******************************************************************************/
300
void XAxiDma_Reset(XAxiDma * InstancePtr)
301
{
302
        u32 RegBase;
303
        XAxiDma_BdRing *TxRingPtr;
304
        XAxiDma_BdRing *RxRingPtr;
305
        int RingIndex;
306
 
307
        TxRingPtr = XAxiDma_GetTxRing(InstancePtr);
308
 
309
        /* Save the locations of current BDs both rings are working on
310
         * before the reset so later we can resume the rings smoothly.
311
         */
312
        if(XAxiDma_HasSg(InstancePtr)){
313
                XAxiDma_BdRingSnapShotCurrBd(TxRingPtr);
314
 
315
                for (RingIndex = 0; RingIndex < InstancePtr->RxNumChannels;
316
                                                RingIndex++) {
317
                        RxRingPtr = XAxiDma_GetRxIndexRing(InstancePtr,
318
                                                RingIndex);
319
                        XAxiDma_BdRingSnapShotCurrBd(RxRingPtr);
320
                }
321
        }
322
 
323
        /* Reset
324
         */
325
        if (InstancePtr->HasMm2S) {
326
                RegBase = InstancePtr->RegBase + XAXIDMA_TX_OFFSET;
327
        }
328
        else {
329
                RegBase = InstancePtr->RegBase + XAXIDMA_RX_OFFSET;
330
        }
331
 
332
        XAxiDma_WriteReg(RegBase, XAXIDMA_CR_OFFSET, XAXIDMA_CR_RESET_MASK);
333
 
334
        /* Set TX/RX Channel state */
335
        if (InstancePtr->HasMm2S) {
336
                TxRingPtr->RunState = AXIDMA_CHANNEL_HALTED;
337
        }
338
 
339
        for (RingIndex = 0; RingIndex < InstancePtr->RxNumChannels;
340
                                        RingIndex++) {
341
                RxRingPtr = XAxiDma_GetRxIndexRing(InstancePtr, RingIndex);
342
                if (InstancePtr->HasS2Mm) {
343
                        RxRingPtr->RunState = AXIDMA_CHANNEL_HALTED;
344
                }
345
        }
346
}
347
 
348
/*****************************************************************************/
349
/**
350
*
351
* Check whether reset is done
352
*
353
* @param        InstancePtr is a pointer to the DMA engine instance to be
354
*               worked on.
355
*
356
* @return
357
*               - 1 if reset is done.
358
*               - 0 if reset is not done
359
*
360
* @note         None
361
*
362
******************************************************************************/
363
int XAxiDma_ResetIsDone(XAxiDma * InstancePtr)
364
{
365
        u32 RegisterValue;
366
        XAxiDma_BdRing *TxRingPtr;
367
        XAxiDma_BdRing *RxRingPtr;
368
 
369
        TxRingPtr = XAxiDma_GetTxRing(InstancePtr);
370
        RxRingPtr = XAxiDma_GetRxRing(InstancePtr);
371
 
372
        /* Check transmit channel
373
         */
374
        if (InstancePtr->HasMm2S) {
375
                RegisterValue = XAxiDma_ReadReg(TxRingPtr->ChanBase,
376
                        XAXIDMA_CR_OFFSET);
377
 
378
                /* Reset is done when the reset bit is low
379
                 */
380
                if(RegisterValue & XAXIDMA_CR_RESET_MASK) {
381
 
382
                        return 0;
383
                }
384
        }
385
 
386
        /* Check receive channel
387
         */
388
        if (InstancePtr->HasS2Mm) {
389
                RegisterValue = XAxiDma_ReadReg(RxRingPtr->ChanBase,
390
                                XAXIDMA_CR_OFFSET);
391
 
392
                /* Reset is done when the reset bit is low
393
                 */
394
                if(RegisterValue & XAXIDMA_CR_RESET_MASK) {
395
 
396
                        return 0;
397
                }
398
        }
399
 
400
        return 1;
401
}
402
/*****************************************************************************/
403
/*
404
* Start the DMA engine.
405
*
406
* Start a halted engine. Processing of BDs is not started.
407
*
408
* @param        InstancePtr is a pointer to the DMA engine instance to be
409
*               worked on.
410
*
411
* @return
412
*               - XST_SUCCESS for success
413
*               - XST_NOT_SGDMA if the driver instance has not been initialized
414
*               - XST_DMA_ERROR if starting the hardware channel fails
415
*
416
* @note         None
417
*
418
*****************************************************************************/
419
static int XAxiDma_Start(XAxiDma * InstancePtr)
420
{
421
        XAxiDma_BdRing *TxRingPtr;
422
        XAxiDma_BdRing *RxRingPtr;
423
        int Status;
424
        int RingIndex = 0;
425
 
426
        if (!InstancePtr->Initialized) {
427
 
428
                xdbg_printf(XDBG_DEBUG_ERROR, "Start: Driver not initialized "
429
                                "%d\r\n", InstancePtr->Initialized);
430
 
431
                return XST_NOT_SGDMA;
432
        }
433
 
434
        if (InstancePtr->HasMm2S) {
435
                TxRingPtr = XAxiDma_GetTxRing(InstancePtr);
436
 
437
                if (TxRingPtr->RunState == AXIDMA_CHANNEL_HALTED) {
438
 
439
                        /* Start the channel
440
                         */
441
                        if(XAxiDma_HasSg(InstancePtr)) {
442
                                Status = XAxiDma_BdRingStart(TxRingPtr);
443
                                if (Status != XST_SUCCESS) {
444
                                        xdbg_printf(XDBG_DEBUG_ERROR,
445
                                        "Start hw tx channel failed %d\r\n",
446
                                                                Status);
447
 
448
                                        return XST_DMA_ERROR;
449
                                }
450
                        }
451
                        else {
452
                                XAxiDma_WriteReg(TxRingPtr->ChanBase,
453
                                        XAXIDMA_CR_OFFSET,
454
                                        XAxiDma_ReadReg(TxRingPtr->ChanBase,
455
                                        XAXIDMA_CR_OFFSET)
456
                                        | XAXIDMA_CR_RUNSTOP_MASK);
457
                        }
458
                        TxRingPtr->RunState = AXIDMA_CHANNEL_NOT_HALTED;
459
                }
460
        }
461
 
462
        if (InstancePtr->HasS2Mm) {
463
 
464
                for (RingIndex = 0; RingIndex < InstancePtr->RxNumChannels;
465
                                                RingIndex++) {
466
                        RxRingPtr = XAxiDma_GetRxIndexRing(InstancePtr,
467
                                                         RingIndex);
468
 
469
                        if (RxRingPtr->RunState != AXIDMA_CHANNEL_HALTED) {
470
                                return XST_SUCCESS;
471
                        }
472
 
473
                        /* Start the channel
474
                         */
475
                        if(XAxiDma_HasSg(InstancePtr)) {
476
                                Status = XAxiDma_BdRingStart(RxRingPtr);
477
                                if (Status != XST_SUCCESS) {
478
                                        xdbg_printf(XDBG_DEBUG_ERROR,
479
                                        "Start hw tx channel failed %d\r\n",
480
                                                                Status);
481
 
482
                                        return XST_DMA_ERROR;
483
                                }
484
                        }
485
                        else {
486
                                XAxiDma_WriteReg(RxRingPtr->ChanBase,
487
                                        XAXIDMA_CR_OFFSET,
488
                                        XAxiDma_ReadReg(RxRingPtr->ChanBase,
489
                                        XAXIDMA_CR_OFFSET) |
490
                                        XAXIDMA_CR_RUNSTOP_MASK);
491
                        }
492
 
493
                        RxRingPtr->RunState = AXIDMA_CHANNEL_NOT_HALTED;
494
                }
495
        }
496
 
497
        return XST_SUCCESS;
498
}
499
/*****************************************************************************/
500
/**
501
* Pause DMA transactions on both channels.
502
*
503
* If the engine is running and doing transfers, this function does not stop
504
* the DMA transactions immediately, because then hardware will throw away
505
* our previously queued transfers. All submitted transfers will finish.
506
* Transfers submitted after this function will not start until
507
* XAxiDma_BdRingStart() or XAxiDma_Resume() is called.
508
*
509
* @param        InstancePtr is a pointer to the DMA engine instance to be
510
*               worked on.
511
*
512
* @return
513
*               - XST_SUCCESS if successful
514
*               - XST_NOT_SGDMA, if the driver instance is not initialized
515
*
516
* @note         None
517
*
518
*****************************************************************************/
519
int XAxiDma_Pause(XAxiDma * InstancePtr)
520
{
521
        XAxiDma_BdRing *TxRingPtr;
522
        XAxiDma_BdRing *RxRingPtr;
523
        int RingIndex = 0;
524
 
525
        if (!InstancePtr->Initialized) {
526
 
527
                xdbg_printf(XDBG_DEBUG_ERROR, "Pause: Driver not initialized"
528
                                        " %d\r\n",InstancePtr->Initialized);
529
 
530
                return XST_NOT_SGDMA;
531
        }
532
 
533
        if (InstancePtr->HasMm2S) {
534
                TxRingPtr = XAxiDma_GetTxRing(InstancePtr);
535
 
536
                /* If channel is halted, then we do not need to do anything
537
                 */
538
                if(!XAxiDma_HasSg(InstancePtr)) {
539
                        XAxiDma_WriteReg(TxRingPtr->ChanBase,
540
                                XAXIDMA_CR_OFFSET,
541
                                XAxiDma_ReadReg(TxRingPtr->ChanBase,
542
                                XAXIDMA_CR_OFFSET)
543
                                & ~XAXIDMA_CR_RUNSTOP_MASK);
544
                }
545
 
546
                TxRingPtr->RunState = AXIDMA_CHANNEL_HALTED;
547
        }
548
 
549
        if (InstancePtr->HasS2Mm) {
550
                for (RingIndex = 0; RingIndex < InstancePtr->RxNumChannels;
551
                                RingIndex++) {
552
                        RxRingPtr = XAxiDma_GetRxIndexRing(InstancePtr, RingIndex);
553
 
554
                        /* If channel is halted, then we do not need to do anything
555
                         */
556
 
557
                        if(!XAxiDma_HasSg(InstancePtr) && !RingIndex) {
558
                                XAxiDma_WriteReg(RxRingPtr->ChanBase,
559
                                        XAXIDMA_CR_OFFSET,
560
                                        XAxiDma_ReadReg(RxRingPtr->ChanBase,
561
                                        XAXIDMA_CR_OFFSET)
562
                                        & ~XAXIDMA_CR_RUNSTOP_MASK);
563
                        }
564
 
565
                        RxRingPtr->RunState = AXIDMA_CHANNEL_HALTED;
566
                }
567
        }
568
 
569
        return XST_SUCCESS;
570
 
571
}
572
 
573
/*****************************************************************************/
574
/**
575
* Resume DMA transactions on both channels.
576
*
577
* @param        InstancePtr is a pointer to the DMA engine instance to be
578
*               worked on.
579
*
580
* @return
581
*               - XST_SUCCESS for success
582
*               - XST_NOT_SGDMA if the driver instance has not been initialized
583
*               - XST_DMA_ERROR if one of the channels fails to start
584
*
585
* @note         None
586
*
587
*****************************************************************************/
588
int XAxiDma_Resume(XAxiDma * InstancePtr)
589
{
590
        XAxiDma_BdRing *TxRingPtr;
591
        XAxiDma_BdRing *RxRingPtr;
592
        int Status;
593
        int RingIndex = 0;
594
 
595
        if (!InstancePtr->Initialized) {
596
 
597
                xdbg_printf(XDBG_DEBUG_ERROR, "Resume: Driver not initialized"
598
                " %d\r\n",InstancePtr->Initialized);
599
 
600
                return XST_NOT_SGDMA;
601
        }
602
 
603
        /* If the DMA engine is not running, start it. Start may fail.
604
         */
605
        if (!XAxiDma_Started(InstancePtr)) {
606
                Status = XAxiDma_Start(InstancePtr);
607
 
608
                if (Status != XST_SUCCESS) {
609
                        xdbg_printf(XDBG_DEBUG_ERROR, "Resume: failed to start"
610
                                " engine %d\r\n", Status);
611
 
612
                        return Status;
613
                }
614
        }
615
 
616
        /* Mark the state to be not halted
617
         */
618
        if (InstancePtr->HasMm2S) {
619
                TxRingPtr = XAxiDma_GetTxRing(InstancePtr);
620
 
621
                if(XAxiDma_HasSg(InstancePtr)) {
622
                        Status = XAxiDma_BdRingStart(TxRingPtr);
623
                        if (Status != XST_SUCCESS) {
624
                                xdbg_printf(XDBG_DEBUG_ERROR, "Resume: failed"
625
                                " to start tx ring %d\r\n", Status);
626
 
627
                                return XST_DMA_ERROR;
628
                        }
629
                }
630
 
631
                TxRingPtr->RunState = AXIDMA_CHANNEL_NOT_HALTED;
632
        }
633
 
634
        if (InstancePtr->HasS2Mm) {
635
                for (RingIndex = 0 ; RingIndex < InstancePtr->RxNumChannels;
636
                                        RingIndex++) {
637
                        RxRingPtr = XAxiDma_GetRxIndexRing(InstancePtr, RingIndex);
638
 
639
                        if(XAxiDma_HasSg(InstancePtr)) {
640
                                Status = XAxiDma_BdRingStart(RxRingPtr);
641
                                if (Status != XST_SUCCESS) {
642
                                        xdbg_printf(XDBG_DEBUG_ERROR, "Resume: failed"
643
                                        "to start rx ring %d\r\n", Status);
644
 
645
                                        return XST_DMA_ERROR;
646
                                }
647
                        }
648
 
649
                        RxRingPtr->RunState = AXIDMA_CHANNEL_NOT_HALTED;
650
                }
651
        }
652
 
653
        return XST_SUCCESS;
654
}
655
 
656
/*****************************************************************************/
657
/*
658
* Check whether the DMA engine is started.
659
*
660
* @param        InstancePtr is a pointer to the DMA engine instance to be
661
*               worked on.
662
*
663
* @return
664
*               - 1 if engine is started
665
*               - 0 otherwise.
666
*
667
* @note         None
668
*
669
*****************************************************************************/
670
static int XAxiDma_Started(XAxiDma * InstancePtr)
671
{
672
        XAxiDma_BdRing *TxRingPtr;
673
        XAxiDma_BdRing *RxRingPtr;
674
 
675
        if (!InstancePtr->Initialized) {
676
 
677
                xdbg_printf(XDBG_DEBUG_ERROR, "Started: Driver not initialized"
678
                " %d\r\n",InstancePtr->Initialized);
679
 
680
                return 0;
681
        }
682
 
683
        if (InstancePtr->HasMm2S) {
684
                TxRingPtr = XAxiDma_GetTxRing(InstancePtr);
685
 
686
                if (!XAxiDma_BdRingHwIsStarted(TxRingPtr)) {
687
                        xdbg_printf(XDBG_DEBUG_ERROR,
688
                                "Started: tx ring not started\r\n");
689
 
690
                        return 0;
691
                }
692
        }
693
 
694
        if (InstancePtr->HasS2Mm) {
695
                RxRingPtr = XAxiDma_GetRxRing(InstancePtr);
696
 
697
                if (!XAxiDma_BdRingHwIsStarted(RxRingPtr)) {
698
                        xdbg_printf(XDBG_DEBUG_ERROR,
699
                                "Started: rx ring not started\r\n");
700
 
701
                        return 0;
702
                }
703
        }
704
 
705
        return 1;
706
}
707
 
708
/*****************************************************************************/
709
/**
710
 * This function checks whether specified DMA channel is busy
711
 *
712
 * @param       InstancePtr is the driver instance we are working on
713
 *
714
 * @param       Direction is DMA transfer direction, valid values are
715
 *                      - XAXIDMA_DMA_TO_DEVICE.
716
 *                      - XAXIDMA_DEVICE_TO_DMA.
717
 *
718
 * @return      - TRUE if channel is busy
719
 *              - FALSE if channel is idle
720
 *
721
 * @note        None.
722
 *
723
 *****************************************************************************/
724
u32 XAxiDma_Busy(XAxiDma *InstancePtr, int Direction)
725
{
726
 
727
        return ((XAxiDma_ReadReg(InstancePtr->RegBase +
728
                                (XAXIDMA_RX_OFFSET * Direction),
729
                                XAXIDMA_SR_OFFSET) &
730
                                XAXIDMA_IDLE_MASK) ? FALSE : TRUE);
731
}
732
 
733
 
734
/*****************************************************************************/
735
/**
736
 * This function Enable or Disable KeyHole Feature
737
 *
738
 * @param       InstancePtr is the driver instance we are working on
739
 *
740
 * @param       Direction is DMA transfer direction, valid values are
741
 *                      - XAXIDMA_DMA_TO_DEVICE.
742
 *                      - XAXIDMA_DEVICE_TO_DMA.
743
 * @Select      Select is the option to enable (TRUE) or disable (FALSE).
744
 *
745
 * @return      - XST_SUCCESS for success
746
 *
747
 * @note        None.
748
 *
749
 *****************************************************************************/
750
int XAxiDma_SelectKeyHole(XAxiDma *InstancePtr, int Direction, int Select)
751
{
752
        u32 Value;
753
 
754
        Value = XAxiDma_ReadReg(InstancePtr->RegBase +
755
                                (XAXIDMA_RX_OFFSET * Direction),
756
                                XAXIDMA_CR_OFFSET);
757
 
758
        if (Select)
759
                Value |= XAXIDMA_CR_KEYHOLE_MASK;
760
        else
761
                Value &= ~XAXIDMA_CR_KEYHOLE_MASK;
762
 
763
        XAxiDma_WriteReg(InstancePtr->RegBase +
764
                        (XAXIDMA_RX_OFFSET * Direction),
765
                        XAXIDMA_CR_OFFSET, Value);
766
 
767
        return XST_SUCCESS;
768
 
769
}
770
 
771
/*****************************************************************************/
772
/**
773
 * This function Enable or Disable Cyclic Mode Feature
774
 *
775
 * @param       InstancePtr is the driver instance we are working on
776
 *
777
 * @param       Direction is DMA transfer direction, valid values are
778
 *                      - XAXIDMA_DMA_TO_DEVICE.
779
 *                      - XAXIDMA_DEVICE_TO_DMA.
780
 * @Select      Select is the option to enable (TRUE) or disable (FALSE).
781
 *
782
 * @return      - XST_SUCCESS for success
783
 *
784
 * @note        None.
785
 *
786
 *****************************************************************************/
787
int XAxiDma_SelectCyclicMode(XAxiDma *InstancePtr, int Direction, int Select)
788
{
789
        u32 Value;
790
 
791
        Value = XAxiDma_ReadReg(InstancePtr->RegBase +
792
                                (XAXIDMA_RX_OFFSET * Direction),
793
                                XAXIDMA_CR_OFFSET);
794
 
795
        if (Select)
796
                Value |= XAXIDMA_CR_CYCLIC_MASK;
797
        else
798
                Value &= ~XAXIDMA_CR_CYCLIC_MASK;
799
 
800
        XAxiDma_WriteReg(InstancePtr->RegBase +
801
                        (XAXIDMA_RX_OFFSET * Direction),
802
                        XAXIDMA_CR_OFFSET, Value);
803
 
804
        return XST_SUCCESS;
805
}
806
 
807
/*****************************************************************************/
808
/**
809
 * This function does one simple transfer submission
810
 *
811
 * It checks in the following sequence:
812
 *      - if engine is busy, cannot submit
813
 *      - if engine is in SG mode , cannot submit
814
 *
815
 * @param       InstancePtr is the pointer to the driver instance
816
 * @param       BuffAddr is the address of the source/destination buffer
817
 * @param       Length is the length of the transfer
818
 * @param       Direction is DMA transfer direction, valid values are
819
 *                      - XAXIDMA_DMA_TO_DEVICE.
820
 *                      - XAXIDMA_DEVICE_TO_DMA.
821
 
822
 * @return
823
 *              - XST_SUCCESS for success of submission
824
 *              - XST_FAILURE for submission failure, maybe caused by:
825
 *              Another simple transfer is still going
826
 *              - XST_INVALID_PARAM if:Length out of valid range [1:8M]
827
 *              Or, address not aligned when DRE is not built in
828
 *
829
 * @note        This function is used only when system is configured as
830
 *              Simple mode.
831
 *
832
 *****************************************************************************/
833
u32 XAxiDma_SimpleTransfer(XAxiDma *InstancePtr, UINTPTR BuffAddr, u32 Length,
834
        int Direction)
835
{
836
        u32 WordBits;
837
        int RingIndex = 0;
838
 
839
        /* If Scatter Gather is included then, cannot submit
840
         */
841
        if (XAxiDma_HasSg(InstancePtr)) {
842
                xdbg_printf(XDBG_DEBUG_ERROR, "Simple DMA mode is not"
843
                                                        " supported\r\n");
844
 
845
                return XST_FAILURE;
846
        }
847
 
848
        if(Direction == XAXIDMA_DMA_TO_DEVICE){
849
                if ((Length < 1) ||
850
                        (Length > InstancePtr->TxBdRing.MaxTransferLen)) {
851
                        return XST_INVALID_PARAM;
852
                }
853
 
854
                if (!InstancePtr->HasMm2S) {
855
                        xdbg_printf(XDBG_DEBUG_ERROR, "MM2S channel is not"
856
                                                        "supported\r\n");
857
 
858
                        return XST_FAILURE;
859
                }
860
 
861
                /* If the engine is doing transfer, cannot submit
862
                 */
863
 
864
                if(!(XAxiDma_ReadReg(InstancePtr->TxBdRing.ChanBase,
865
                                XAXIDMA_SR_OFFSET) & XAXIDMA_HALTED_MASK)) {
866
                        if (XAxiDma_Busy(InstancePtr,Direction)) {
867
                                xdbg_printf(XDBG_DEBUG_ERROR,
868
                                                        "Engine is busy\r\n");
869
                                return XST_FAILURE;
870
                        }
871
                }
872
 
873
                if (!InstancePtr->MicroDmaMode) {
874
                        WordBits = (u32)((InstancePtr->TxBdRing.DataWidth) - 1);
875
                }
876
                else {
877
                        WordBits = XAXIDMA_MICROMODE_MIN_BUF_ALIGN;
878
                }
879
 
880
                if ((BuffAddr & WordBits)) {
881
 
882
                        if (!InstancePtr->TxBdRing.HasDRE) {
883
                                xdbg_printf(XDBG_DEBUG_ERROR,
884
                                        "Unaligned transfer without"
885
                                        " DRE %x\r\n",(unsigned int)BuffAddr);
886
 
887
                                return XST_INVALID_PARAM;
888
                        }
889
                }
890
 
891
 
892
                XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase,
893
                                 XAXIDMA_SRCADDR_OFFSET, LOWER_32_BITS(BuffAddr));
894
                if (InstancePtr->AddrWidth > 32)
895
                        XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase,
896
                                         XAXIDMA_SRCADDR_MSB_OFFSET,
897
                                         UPPER_32_BITS(BuffAddr));
898
 
899
                XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase,
900
                                XAXIDMA_CR_OFFSET,
901
                                XAxiDma_ReadReg(
902
                                InstancePtr->TxBdRing.ChanBase,
903
                                XAXIDMA_CR_OFFSET)| XAXIDMA_CR_RUNSTOP_MASK);
904
 
905
                /* Writing to the BTT register starts the transfer
906
                 */
907
                XAxiDma_WriteReg(InstancePtr->TxBdRing.ChanBase,
908
                                        XAXIDMA_BUFFLEN_OFFSET, Length);
909
        }
910
        else if(Direction == XAXIDMA_DEVICE_TO_DMA){
911
                if ((Length < 1) ||
912
                        (Length >
913
                        InstancePtr->RxBdRing[RingIndex].MaxTransferLen)) {
914
                        return XST_INVALID_PARAM;
915
                }
916
 
917
 
918
                if (!InstancePtr->HasS2Mm) {
919
                        xdbg_printf(XDBG_DEBUG_ERROR, "S2MM channel is not"
920
                                                        " supported\r\n");
921
 
922
                        return XST_FAILURE;
923
                }
924
 
925
                if(!(XAxiDma_ReadReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
926
                                XAXIDMA_SR_OFFSET) & XAXIDMA_HALTED_MASK)) {
927
                        if (XAxiDma_Busy(InstancePtr,Direction)) {
928
                                xdbg_printf(XDBG_DEBUG_ERROR,
929
                                                        "Engine is busy\r\n");
930
                                return XST_FAILURE;
931
                        }
932
                }
933
 
934
                if (!InstancePtr->MicroDmaMode) {
935
                        WordBits =
936
                         (u32)((InstancePtr->RxBdRing[RingIndex].DataWidth) - 1);
937
                }
938
                else {
939
                        WordBits = XAXIDMA_MICROMODE_MIN_BUF_ALIGN;
940
                }
941
 
942
                if ((BuffAddr & WordBits)) {
943
 
944
                        if (!InstancePtr->RxBdRing[RingIndex].HasDRE) {
945
                                xdbg_printf(XDBG_DEBUG_ERROR,
946
                                        "Unaligned transfer without"
947
                                " DRE %x\r\n", (unsigned int)BuffAddr);
948
 
949
                                return XST_INVALID_PARAM;
950
                        }
951
                }
952
 
953
 
954
                XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
955
                                 XAXIDMA_DESTADDR_OFFSET, LOWER_32_BITS(BuffAddr));
956
                if (InstancePtr->AddrWidth > 32)
957
                        XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
958
                                         XAXIDMA_DESTADDR_MSB_OFFSET,
959
                                         UPPER_32_BITS(BuffAddr));
960
 
961
                XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
962
                                XAXIDMA_CR_OFFSET,
963
                        XAxiDma_ReadReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
964
                        XAXIDMA_CR_OFFSET)| XAXIDMA_CR_RUNSTOP_MASK);
965
                /* Writing to the BTT register starts the transfer
966
                 */
967
                XAxiDma_WriteReg(InstancePtr->RxBdRing[RingIndex].ChanBase,
968
                                        XAXIDMA_BUFFLEN_OFFSET, Length);
969
 
970
        }
971
 
972
        return XST_SUCCESS;
973
}
974
/** @} */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.