• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/arm/mach-bcmring/csp/dmac/
1/*****************************************************************************
2* Copyright 2003 - 2008 Broadcom Corporation.  All rights reserved.
3*
4* Unless you and Broadcom execute a separate written software license
5* agreement governing use of this software, this software is licensed to you
6* under the terms of the GNU General Public License version 2, available at
7* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
8*
9* Notwithstanding the above, under no circumstances may you combine this
10* software in any way with any other Broadcom software provided under a
11* license other than the GPL, without Broadcom's express prior written
12* consent.
13*****************************************************************************/
14
15/****************************************************************************/
16/**
17*  @file    dmacHw_extra.c
18*
19*  @brief   Extra Low level DMA controller driver routines
20*
21*  @note
22*
23*   These routines provide basic DMA functionality only.
24*/
25/****************************************************************************/
26
27/* ---- Include Files ---------------------------------------------------- */
28
29#include <csp/stdint.h>
30#include <stddef.h>
31
32#include <csp/dmacHw.h>
33#include <mach/csp/dmacHw_reg.h>
34#include <mach/csp/dmacHw_priv.h>
35
36extern dmacHw_CBLK_t dmacHw_gCblk[dmacHw_MAX_CHANNEL_COUNT];	/* Declared in dmacHw.c */
37
38/* ---- External Function Prototypes ------------------------------------- */
39
40/* ---- Internal Use Function Prototypes --------------------------------- */
41/****************************************************************************/
42/**
43*  @brief   Overwrites data length in the descriptor
44*
45*  This function overwrites data length in the descriptor
46*
47*
48*  @return   void
49*
50*  @note
51*          This is only used for PCM channel
52*/
53/****************************************************************************/
54void dmacHw_setDataLength(dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
55			  void *pDescriptor,	/*   [ IN ] Descriptor buffer */
56			  size_t dataLen	/*   [ IN ] Data length in bytes */
57    );
58
59/****************************************************************************/
60/**
61*  @brief   Helper function to display DMA registers
62*
63*  @return  void
64*
65*
66*  @note
67*     None
68*/
69/****************************************************************************/
70static void DisplayRegisterContents(int module,	/*   [ IN ] DMA Controller unit  (0-1) */
71				    int channel,	/*   [ IN ] DMA Channel          (0-7) / -1(all) */
72				    int (*fpPrint) (const char *, ...)	/*   [ IN ] Callback to the print function */
73    ) {
74	int chan;
75
76	(*fpPrint) ("Displaying register content \n\n");
77	(*fpPrint) ("Module %d: Interrupt raw transfer              0x%X\n",
78		    module, (uint32_t) (dmacHw_REG_INT_RAW_TRAN(module)));
79	(*fpPrint) ("Module %d: Interrupt raw block                 0x%X\n",
80		    module, (uint32_t) (dmacHw_REG_INT_RAW_BLOCK(module)));
81	(*fpPrint) ("Module %d: Interrupt raw src transfer          0x%X\n",
82		    module, (uint32_t) (dmacHw_REG_INT_RAW_STRAN(module)));
83	(*fpPrint) ("Module %d: Interrupt raw dst transfer          0x%X\n",
84		    module, (uint32_t) (dmacHw_REG_INT_RAW_DTRAN(module)));
85	(*fpPrint) ("Module %d: Interrupt raw error                 0x%X\n",
86		    module, (uint32_t) (dmacHw_REG_INT_RAW_ERROR(module)));
87	(*fpPrint) ("--------------------------------------------------\n");
88	(*fpPrint) ("Module %d: Interrupt stat transfer             0x%X\n",
89		    module, (uint32_t) (dmacHw_REG_INT_STAT_TRAN(module)));
90	(*fpPrint) ("Module %d: Interrupt stat block                0x%X\n",
91		    module, (uint32_t) (dmacHw_REG_INT_STAT_BLOCK(module)));
92	(*fpPrint) ("Module %d: Interrupt stat src transfer         0x%X\n",
93		    module, (uint32_t) (dmacHw_REG_INT_STAT_STRAN(module)));
94	(*fpPrint) ("Module %d: Interrupt stat dst transfer         0x%X\n",
95		    module, (uint32_t) (dmacHw_REG_INT_STAT_DTRAN(module)));
96	(*fpPrint) ("Module %d: Interrupt stat error                0x%X\n",
97		    module, (uint32_t) (dmacHw_REG_INT_STAT_ERROR(module)));
98	(*fpPrint) ("--------------------------------------------------\n");
99	(*fpPrint) ("Module %d: Interrupt mask transfer             0x%X\n",
100		    module, (uint32_t) (dmacHw_REG_INT_MASK_TRAN(module)));
101	(*fpPrint) ("Module %d: Interrupt mask block                0x%X\n",
102		    module, (uint32_t) (dmacHw_REG_INT_MASK_BLOCK(module)));
103	(*fpPrint) ("Module %d: Interrupt mask src transfer         0x%X\n",
104		    module, (uint32_t) (dmacHw_REG_INT_MASK_STRAN(module)));
105	(*fpPrint) ("Module %d: Interrupt mask dst transfer         0x%X\n",
106		    module, (uint32_t) (dmacHw_REG_INT_MASK_DTRAN(module)));
107	(*fpPrint) ("Module %d: Interrupt mask error                0x%X\n",
108		    module, (uint32_t) (dmacHw_REG_INT_MASK_ERROR(module)));
109	(*fpPrint) ("--------------------------------------------------\n");
110	(*fpPrint) ("Module %d: Interrupt clear transfer            0x%X\n",
111		    module, (uint32_t) (dmacHw_REG_INT_CLEAR_TRAN(module)));
112	(*fpPrint) ("Module %d: Interrupt clear block               0x%X\n",
113		    module, (uint32_t) (dmacHw_REG_INT_CLEAR_BLOCK(module)));
114	(*fpPrint) ("Module %d: Interrupt clear src transfer        0x%X\n",
115		    module, (uint32_t) (dmacHw_REG_INT_CLEAR_STRAN(module)));
116	(*fpPrint) ("Module %d: Interrupt clear dst transfer        0x%X\n",
117		    module, (uint32_t) (dmacHw_REG_INT_CLEAR_DTRAN(module)));
118	(*fpPrint) ("Module %d: Interrupt clear error               0x%X\n",
119		    module, (uint32_t) (dmacHw_REG_INT_CLEAR_ERROR(module)));
120	(*fpPrint) ("--------------------------------------------------\n");
121	(*fpPrint) ("Module %d: SW source req                       0x%X\n",
122		    module, (uint32_t) (dmacHw_REG_SW_HS_SRC_REQ(module)));
123	(*fpPrint) ("Module %d: SW dest req                         0x%X\n",
124		    module, (uint32_t) (dmacHw_REG_SW_HS_DST_REQ(module)));
125	(*fpPrint) ("Module %d: SW source signal                    0x%X\n",
126		    module, (uint32_t) (dmacHw_REG_SW_HS_SRC_SGL_REQ(module)));
127	(*fpPrint) ("Module %d: SW dest signal                      0x%X\n",
128		    module, (uint32_t) (dmacHw_REG_SW_HS_DST_SGL_REQ(module)));
129	(*fpPrint) ("Module %d: SW source last                      0x%X\n",
130		    module, (uint32_t) (dmacHw_REG_SW_HS_SRC_LST_REQ(module)));
131	(*fpPrint) ("Module %d: SW dest last                        0x%X\n",
132		    module, (uint32_t) (dmacHw_REG_SW_HS_DST_LST_REQ(module)));
133	(*fpPrint) ("--------------------------------------------------\n");
134	(*fpPrint) ("Module %d: misc config                         0x%X\n",
135		    module, (uint32_t) (dmacHw_REG_MISC_CFG(module)));
136	(*fpPrint) ("Module %d: misc channel enable                 0x%X\n",
137		    module, (uint32_t) (dmacHw_REG_MISC_CH_ENABLE(module)));
138	(*fpPrint) ("Module %d: misc ID                             0x%X\n",
139		    module, (uint32_t) (dmacHw_REG_MISC_ID(module)));
140	(*fpPrint) ("Module %d: misc test                           0x%X\n",
141		    module, (uint32_t) (dmacHw_REG_MISC_TEST(module)));
142
143	if (channel == -1) {
144		for (chan = 0; chan < 8; chan++) {
145			(*fpPrint)
146			    ("--------------------------------------------------\n");
147			(*fpPrint)
148			    ("Module %d: Channel %d Source                   0x%X\n",
149			     module, chan,
150			     (uint32_t) (dmacHw_REG_SAR(module, chan)));
151			(*fpPrint)
152			    ("Module %d: Channel %d Destination              0x%X\n",
153			     module, chan,
154			     (uint32_t) (dmacHw_REG_DAR(module, chan)));
155			(*fpPrint)
156			    ("Module %d: Channel %d LLP                      0x%X\n",
157			     module, chan,
158			     (uint32_t) (dmacHw_REG_LLP(module, chan)));
159			(*fpPrint)
160			    ("Module %d: Channel %d Control (LO)             0x%X\n",
161			     module, chan,
162			     (uint32_t) (dmacHw_REG_CTL_LO(module, chan)));
163			(*fpPrint)
164			    ("Module %d: Channel %d Control (HI)             0x%X\n",
165			     module, chan,
166			     (uint32_t) (dmacHw_REG_CTL_HI(module, chan)));
167			(*fpPrint)
168			    ("Module %d: Channel %d Source Stats             0x%X\n",
169			     module, chan,
170			     (uint32_t) (dmacHw_REG_SSTAT(module, chan)));
171			(*fpPrint)
172			    ("Module %d: Channel %d Dest Stats               0x%X\n",
173			     module, chan,
174			     (uint32_t) (dmacHw_REG_DSTAT(module, chan)));
175			(*fpPrint)
176			    ("Module %d: Channel %d Source Stats Addr        0x%X\n",
177			     module, chan,
178			     (uint32_t) (dmacHw_REG_SSTATAR(module, chan)));
179			(*fpPrint)
180			    ("Module %d: Channel %d Dest Stats Addr          0x%X\n",
181			     module, chan,
182			     (uint32_t) (dmacHw_REG_DSTATAR(module, chan)));
183			(*fpPrint)
184			    ("Module %d: Channel %d Config (LO)              0x%X\n",
185			     module, chan,
186			     (uint32_t) (dmacHw_REG_CFG_LO(module, chan)));
187			(*fpPrint)
188			    ("Module %d: Channel %d Config (HI)              0x%X\n",
189			     module, chan,
190			     (uint32_t) (dmacHw_REG_CFG_HI(module, chan)));
191		}
192	} else {
193		chan = channel;
194		(*fpPrint)
195		    ("--------------------------------------------------\n");
196		(*fpPrint)
197		    ("Module %d: Channel %d Source                   0x%X\n",
198		     module, chan, (uint32_t) (dmacHw_REG_SAR(module, chan)));
199		(*fpPrint)
200		    ("Module %d: Channel %d Destination              0x%X\n",
201		     module, chan, (uint32_t) (dmacHw_REG_DAR(module, chan)));
202		(*fpPrint)
203		    ("Module %d: Channel %d LLP                      0x%X\n",
204		     module, chan, (uint32_t) (dmacHw_REG_LLP(module, chan)));
205		(*fpPrint)
206		    ("Module %d: Channel %d Control (LO)             0x%X\n",
207		     module, chan,
208		     (uint32_t) (dmacHw_REG_CTL_LO(module, chan)));
209		(*fpPrint)
210		    ("Module %d: Channel %d Control (HI)             0x%X\n",
211		     module, chan,
212		     (uint32_t) (dmacHw_REG_CTL_HI(module, chan)));
213		(*fpPrint)
214		    ("Module %d: Channel %d Source Stats             0x%X\n",
215		     module, chan, (uint32_t) (dmacHw_REG_SSTAT(module, chan)));
216		(*fpPrint)
217		    ("Module %d: Channel %d Dest Stats               0x%X\n",
218		     module, chan, (uint32_t) (dmacHw_REG_DSTAT(module, chan)));
219		(*fpPrint)
220		    ("Module %d: Channel %d Source Stats Addr        0x%X\n",
221		     module, chan,
222		     (uint32_t) (dmacHw_REG_SSTATAR(module, chan)));
223		(*fpPrint)
224		    ("Module %d: Channel %d Dest Stats Addr          0x%X\n",
225		     module, chan,
226		     (uint32_t) (dmacHw_REG_DSTATAR(module, chan)));
227		(*fpPrint)
228		    ("Module %d: Channel %d Config (LO)              0x%X\n",
229		     module, chan,
230		     (uint32_t) (dmacHw_REG_CFG_LO(module, chan)));
231		(*fpPrint)
232		    ("Module %d: Channel %d Config (HI)              0x%X\n",
233		     module, chan,
234		     (uint32_t) (dmacHw_REG_CFG_HI(module, chan)));
235	}
236}
237
238/****************************************************************************/
239/**
240*  @brief   Helper function to display descriptor ring
241*
242*  @return  void
243*
244*
245*  @note
246*     None
247*/
248/****************************************************************************/
249static void DisplayDescRing(void *pDescriptor,	/*   [ IN ] Descriptor buffer */
250			    int (*fpPrint) (const char *, ...)	/*   [ IN ] Callback to the print function */
251    ) {
252	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
253	dmacHw_DESC_t *pStart;
254
255	if (pRing->pHead == NULL) {
256		return;
257	}
258
259	pStart = pRing->pHead;
260
261	while ((dmacHw_DESC_t *) pStart->llp != pRing->pHead) {
262		if (pStart == pRing->pHead) {
263			(*fpPrint) ("Head\n");
264		}
265		if (pStart == pRing->pTail) {
266			(*fpPrint) ("Tail\n");
267		}
268		if (pStart == pRing->pProg) {
269			(*fpPrint) ("Prog\n");
270		}
271		if (pStart == pRing->pEnd) {
272			(*fpPrint) ("End\n");
273		}
274		if (pStart == pRing->pFree) {
275			(*fpPrint) ("Free\n");
276		}
277		(*fpPrint) ("0x%X:\n", (uint32_t) pStart);
278		(*fpPrint) ("sar    0x%0X\n", pStart->sar);
279		(*fpPrint) ("dar    0x%0X\n", pStart->dar);
280		(*fpPrint) ("llp    0x%0X\n", pStart->llp);
281		(*fpPrint) ("ctl.lo 0x%0X\n", pStart->ctl.lo);
282		(*fpPrint) ("ctl.hi 0x%0X\n", pStart->ctl.hi);
283		(*fpPrint) ("sstat  0x%0X\n", pStart->sstat);
284		(*fpPrint) ("dstat  0x%0X\n", pStart->dstat);
285		(*fpPrint) ("devCtl 0x%0X\n", pStart->devCtl);
286
287		pStart = (dmacHw_DESC_t *) pStart->llp;
288	}
289	if (pStart == pRing->pHead) {
290		(*fpPrint) ("Head\n");
291	}
292	if (pStart == pRing->pTail) {
293		(*fpPrint) ("Tail\n");
294	}
295	if (pStart == pRing->pProg) {
296		(*fpPrint) ("Prog\n");
297	}
298	if (pStart == pRing->pEnd) {
299		(*fpPrint) ("End\n");
300	}
301	if (pStart == pRing->pFree) {
302		(*fpPrint) ("Free\n");
303	}
304	(*fpPrint) ("0x%X:\n", (uint32_t) pStart);
305	(*fpPrint) ("sar    0x%0X\n", pStart->sar);
306	(*fpPrint) ("dar    0x%0X\n", pStart->dar);
307	(*fpPrint) ("llp    0x%0X\n", pStart->llp);
308	(*fpPrint) ("ctl.lo 0x%0X\n", pStart->ctl.lo);
309	(*fpPrint) ("ctl.hi 0x%0X\n", pStart->ctl.hi);
310	(*fpPrint) ("sstat  0x%0X\n", pStart->sstat);
311	(*fpPrint) ("dstat  0x%0X\n", pStart->dstat);
312	(*fpPrint) ("devCtl 0x%0X\n", pStart->devCtl);
313}
314
315/****************************************************************************/
316/**
317*  @brief   Check if DMA channel is the flow controller
318*
319*  @return  1 : If DMA is a flow controler
320*           0 : Peripheral is the flow controller
321*
322*  @note
323*     None
324*/
325/****************************************************************************/
326static inline int DmaIsFlowController(void *pDescriptor	/*   [ IN ] Descriptor buffer */
327    ) {
328	uint32_t ttfc =
329	    (dmacHw_GET_DESC_RING(pDescriptor))->pTail->ctl.
330	    lo & dmacHw_REG_CTL_TTFC_MASK;
331
332	switch (ttfc) {
333	case dmacHw_REG_CTL_TTFC_MM_DMAC:
334	case dmacHw_REG_CTL_TTFC_MP_DMAC:
335	case dmacHw_REG_CTL_TTFC_PM_DMAC:
336	case dmacHw_REG_CTL_TTFC_PP_DMAC:
337		return 1;
338	}
339
340	return 0;
341}
342
343/****************************************************************************/
344/**
345*  @brief   Overwrites data length in the descriptor
346*
347*  This function overwrites data length in the descriptor
348*
349*
350*  @return   void
351*
352*  @note
353*          This is only used for PCM channel
354*/
355/****************************************************************************/
356void dmacHw_setDataLength(dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
357			  void *pDescriptor,	/*   [ IN ] Descriptor buffer */
358			  size_t dataLen	/*   [ IN ] Data length in bytes */
359    ) {
360	dmacHw_DESC_t *pProg;
361	dmacHw_DESC_t *pHead;
362	int srcTs = 0;
363	int srcTrSize = 0;
364
365	pHead = (dmacHw_GET_DESC_RING(pDescriptor))->pHead;
366	pProg = pHead;
367
368	srcTrSize = dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth);
369	srcTs = dataLen / srcTrSize;
370	do {
371		pProg->ctl.hi = srcTs & dmacHw_REG_CTL_BLOCK_TS_MASK;
372		pProg = (dmacHw_DESC_t *) pProg->llp;
373	} while (pProg != pHead);
374}
375
376/****************************************************************************/
377/**
378*  @brief   Clears the interrupt
379*
380*  This function clears the DMA channel specific interrupt
381*
382*
383*  @return   void
384*
385*  @note
386*     Must be called under the context of ISR
387*/
388/****************************************************************************/
389void dmacHw_clearInterrupt(dmacHw_HANDLE_t handle	/* [ IN ] DMA Channel handle */
390    ) {
391	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle);
392
393	dmacHw_TRAN_INT_CLEAR(pCblk->module, pCblk->channel);
394	dmacHw_BLOCK_INT_CLEAR(pCblk->module, pCblk->channel);
395	dmacHw_ERROR_INT_CLEAR(pCblk->module, pCblk->channel);
396}
397
398/****************************************************************************/
399/**
400*  @brief   Returns the cause of channel specific DMA interrupt
401*
402*  This function returns the cause of interrupt
403*
404*  @return  Interrupt status, each bit representing a specific type of interrupt
405*
406*  @note
407*     Should be called under the context of ISR
408*/
409/****************************************************************************/
410dmacHw_INTERRUPT_STATUS_e dmacHw_getInterruptStatus(dmacHw_HANDLE_t handle	/* [ IN ] DMA Channel handle */
411    ) {
412	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle);
413	dmacHw_INTERRUPT_STATUS_e status = dmacHw_INTERRUPT_STATUS_NONE;
414
415	if (dmacHw_REG_INT_STAT_TRAN(pCblk->module) &
416	    ((0x00000001 << pCblk->channel))) {
417		status |= dmacHw_INTERRUPT_STATUS_TRANS;
418	}
419	if (dmacHw_REG_INT_STAT_BLOCK(pCblk->module) &
420	    ((0x00000001 << pCblk->channel))) {
421		status |= dmacHw_INTERRUPT_STATUS_BLOCK;
422	}
423	if (dmacHw_REG_INT_STAT_ERROR(pCblk->module) &
424	    ((0x00000001 << pCblk->channel))) {
425		status |= dmacHw_INTERRUPT_STATUS_ERROR;
426	}
427
428	return status;
429}
430
431/****************************************************************************/
432/**
433*  @brief   Indentifies a DMA channel causing interrupt
434*
435*  This functions returns a channel causing interrupt of type dmacHw_INTERRUPT_STATUS_e
436*
437*  @return  NULL   : No channel causing DMA interrupt
438*           ! NULL : Handle to a channel causing DMA interrupt
439*  @note
440*     dmacHw_clearInterrupt() must be called with a valid handle after calling this function
441*/
442/****************************************************************************/
443dmacHw_HANDLE_t dmacHw_getInterruptSource(void)
444{
445	uint32_t i;
446
447	for (i = 0; i < dmaChannelCount_0 + dmaChannelCount_1; i++) {
448		if ((dmacHw_REG_INT_STAT_TRAN(dmacHw_gCblk[i].module) &
449		     ((0x00000001 << dmacHw_gCblk[i].channel)))
450		    || (dmacHw_REG_INT_STAT_BLOCK(dmacHw_gCblk[i].module) &
451			((0x00000001 << dmacHw_gCblk[i].channel)))
452		    || (dmacHw_REG_INT_STAT_ERROR(dmacHw_gCblk[i].module) &
453			((0x00000001 << dmacHw_gCblk[i].channel)))
454		    ) {
455			return dmacHw_CBLK_TO_HANDLE(&dmacHw_gCblk[i]);
456		}
457	}
458	return dmacHw_CBLK_TO_HANDLE(NULL);
459}
460
461/****************************************************************************/
462/**
463*  @brief  Estimates number of descriptor needed to perform certain DMA transfer
464*
465*
466*  @return  On failure : -1
467*           On success : Number of descriptor count
468*
469*
470*/
471/****************************************************************************/
472int dmacHw_calculateDescriptorCount(dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
473				    void *pSrcAddr,	/*   [ IN ] Source (Peripheral/Memory) address */
474				    void *pDstAddr,	/*   [ IN ] Destination (Peripheral/Memory) address */
475				    size_t dataLen	/*   [ IN ] Data length in bytes */
476    ) {
477	int srcTs = 0;
478	int oddSize = 0;
479	int descCount = 0;
480	int dstTrSize = 0;
481	int srcTrSize = 0;
482	uint32_t maxBlockSize = dmacHw_MAX_BLOCKSIZE;
483	dmacHw_TRANSACTION_WIDTH_e dstTrWidth;
484	dmacHw_TRANSACTION_WIDTH_e srcTrWidth;
485
486	dstTrSize = dmacHw_GetTrWidthInBytes(pConfig->dstMaxTransactionWidth);
487	srcTrSize = dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth);
488
489	/* Skip Tx if buffer is NULL  or length is unknown */
490	if ((pSrcAddr == NULL) || (pDstAddr == NULL) || (dataLen == 0)) {
491		/* Do not initiate transfer */
492		return -1;
493	}
494
495	/* Ensure scatter and gather are transaction aligned */
496	if (pConfig->srcGatherWidth % srcTrSize
497	    || pConfig->dstScatterWidth % dstTrSize) {
498		return -1;
499	}
500
501	/*
502	   Background 1: DMAC can not perform DMA if source and destination addresses are
503	   not properly aligned with the channel's transaction width. So, for successful
504	   DMA transfer, transaction width must be set according to the alignment of the
505	   source and destination address.
506	 */
507
508	/* Adjust destination transaction width if destination address is not aligned properly */
509	dstTrWidth = pConfig->dstMaxTransactionWidth;
510	while (dmacHw_ADDRESS_MASK(dstTrSize) & (uint32_t) pDstAddr) {
511		dstTrWidth = dmacHw_GetNextTrWidth(dstTrWidth);
512		dstTrSize = dmacHw_GetTrWidthInBytes(dstTrWidth);
513	}
514
515	/* Adjust source transaction width if source address is not aligned properly */
516	srcTrWidth = pConfig->srcMaxTransactionWidth;
517	while (dmacHw_ADDRESS_MASK(srcTrSize) & (uint32_t) pSrcAddr) {
518		srcTrWidth = dmacHw_GetNextTrWidth(srcTrWidth);
519		srcTrSize = dmacHw_GetTrWidthInBytes(srcTrWidth);
520	}
521
522	/* Find the maximum transaction per descriptor */
523	if (pConfig->maxDataPerBlock
524	    && ((pConfig->maxDataPerBlock / srcTrSize) <
525		dmacHw_MAX_BLOCKSIZE)) {
526		maxBlockSize = pConfig->maxDataPerBlock / srcTrSize;
527	}
528
529	/* Find number of source transactions needed to complete the DMA transfer */
530	srcTs = dataLen / srcTrSize;
531	/* Find the odd number of bytes that need to be transferred as single byte transaction width */
532	if (srcTs && (dstTrSize > srcTrSize)) {
533		oddSize = dataLen % dstTrSize;
534		/* Adjust source transaction count due to "oddSize" */
535		srcTs = srcTs - (oddSize / srcTrSize);
536	} else {
537		oddSize = dataLen % srcTrSize;
538	}
539	/* Adjust "descCount" due to "oddSize" */
540	if (oddSize) {
541		descCount++;
542	}
543
544	/* Find the number of descriptor needed for total "srcTs" */
545	if (srcTs) {
546		descCount += ((srcTs - 1) / maxBlockSize) + 1;
547	}
548
549	return descCount;
550}
551
552/****************************************************************************/
553/**
554*  @brief   Check the existance of pending descriptor
555*
556*  This function confirmes if there is any pending descriptor in the chain
557*  to program the channel
558*
559*  @return  1 : Channel need to be programmed with pending descriptor
560*           0 : No more pending descriptor to programe the channel
561*
562*  @note
563*     - This function should be called from ISR in case there are pending
564*       descriptor to program the channel.
565*
566*     Example:
567*
568*     dmac_isr ()
569*     {
570*         ...
571*         if (dmacHw_descriptorPending (handle))
572*         {
573*            dmacHw_initiateTransfer (handle);
574*         }
575*     }
576*
577*/
578/****************************************************************************/
579uint32_t dmacHw_descriptorPending(dmacHw_HANDLE_t handle,	/*   [ IN ] DMA Channel handle */
580				  void *pDescriptor	/*   [ IN ] Descriptor buffer */
581    ) {
582	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle);
583	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
584
585	/* Make sure channel is not busy */
586	if (!CHANNEL_BUSY(pCblk->module, pCblk->channel)) {
587		/* Check if pEnd is not processed */
588		if (pRing->pEnd) {
589			/* Something left for processing */
590			return 1;
591		}
592	}
593	return 0;
594}
595
596/****************************************************************************/
597/**
598*  @brief   Program channel register to stop transfer
599*
600*  Ensures the channel is not doing any transfer after calling this function
601*
602*  @return  void
603*
604*/
605/****************************************************************************/
606void dmacHw_stopTransfer(dmacHw_HANDLE_t handle	/*   [ IN ] DMA Channel handle */
607    ) {
608	dmacHw_CBLK_t *pCblk;
609
610	pCblk = dmacHw_HANDLE_TO_CBLK(handle);
611
612	/* Stop the channel */
613	dmacHw_DMA_STOP(pCblk->module, pCblk->channel);
614}
615
616/****************************************************************************/
617/**
618*  @brief   Deallocates source or destination memory, allocated
619*
620*  This function can be called to deallocate data memory that was DMAed successfully
621*
622*  @return  On failure : -1
623*           On success : Number of buffer freed
624*
625*  @note
626*     This function will be called ONLY, when source OR destination address is pointing
627*     to dynamic memory
628*/
629/****************************************************************************/
630int dmacHw_freeMem(dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
631		   void *pDescriptor,	/*   [ IN ] Descriptor buffer */
632		   void (*fpFree) (void *)	/*   [ IN ] Function pointer to free data memory */
633    ) {
634	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
635	uint32_t count = 0;
636
637	if (fpFree == NULL) {
638		return -1;
639	}
640
641	while ((pRing->pFree != pRing->pTail)
642	       && (pRing->pFree->ctl.lo & dmacHw_DESC_FREE)) {
643		if (pRing->pFree->devCtl == dmacHw_FREE_USER_MEMORY) {
644			/* Identify, which memory to free */
645			if (dmacHw_DST_IS_MEMORY(pConfig->transferType)) {
646				(*fpFree) ((void *)pRing->pFree->dar);
647			} else {
648				/* Destination was a peripheral */
649				(*fpFree) ((void *)pRing->pFree->sar);
650			}
651			/* Unmark user memory to indicate it is freed */
652			pRing->pFree->devCtl = ~dmacHw_FREE_USER_MEMORY;
653		}
654		dmacHw_NEXT_DESC(pRing, pFree);
655
656		count++;
657	}
658
659	return count;
660}
661
662/****************************************************************************/
663/**
664*  @brief   Prepares descriptor ring, when source peripheral working as a flow controller
665*
666*  This function will update the discriptor ring by allocating buffers, when source peripheral
667*  has to work as a flow controller to transfer data from:
668*           - Peripheral to memory.
669*
670*  @return  On failure : -1
671*           On success : Number of descriptor updated
672*
673*
674*  @note
675*     Channel must be configured for peripheral to memory transfer
676*
677*/
678/****************************************************************************/
679int dmacHw_setVariableDataDescriptor(dmacHw_HANDLE_t handle,	/*   [ IN ] DMA Channel handle */
680				     dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
681				     void *pDescriptor,	/*   [ IN ] Descriptor buffer */
682				     uint32_t srcAddr,	/*   [ IN ] Source peripheral address */
683				     void *(*fpAlloc) (int len),	/*   [ IN ] Function pointer  that provides destination memory */
684				     int len,	/*   [ IN ] Number of bytes "fpAlloc" will allocate for destination */
685				     int num	/*   [ IN ] Number of descriptor to set */
686    ) {
687	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle);
688	dmacHw_DESC_t *pProg = NULL;
689	dmacHw_DESC_t *pLast = NULL;
690	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
691	uint32_t dstAddr;
692	uint32_t controlParam;
693	int i;
694
695	dmacHw_ASSERT(pConfig->transferType ==
696		      dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM);
697
698	if (num > pRing->num) {
699		return -1;
700	}
701
702	pLast = pRing->pEnd;	/* Last descriptor updated */
703	pProg = pRing->pHead;	/* First descriptor in the new list */
704
705	controlParam = pConfig->srcUpdate |
706	    pConfig->dstUpdate |
707	    pConfig->srcMaxTransactionWidth |
708	    pConfig->dstMaxTransactionWidth |
709	    pConfig->srcMasterInterface |
710	    pConfig->dstMasterInterface |
711	    pConfig->srcMaxBurstWidth |
712	    pConfig->dstMaxBurstWidth |
713	    dmacHw_REG_CTL_TTFC_PM_PERI |
714	    dmacHw_REG_CTL_LLP_DST_EN |
715	    dmacHw_REG_CTL_LLP_SRC_EN | dmacHw_REG_CTL_INT_EN;
716
717	for (i = 0; i < num; i++) {
718		/* Allocate Rx buffer only for idle descriptor */
719		if (((pRing->pHead->ctl.hi & dmacHw_DESC_FREE) == 0) ||
720		    ((dmacHw_DESC_t *) pRing->pHead->llp == pRing->pTail)
721		    ) {
722			/* Rx descriptor is not idle */
723			break;
724		}
725		/* Set source address */
726		pRing->pHead->sar = srcAddr;
727		if (fpAlloc) {
728			/* Allocate memory for buffer in descriptor */
729			dstAddr = (uint32_t) (*fpAlloc) (len);
730			/* Check the destination address */
731			if (dstAddr == 0) {
732				if (i == 0) {
733					/* Not a single descriptor is available */
734					return -1;
735				}
736				break;
737			}
738			/* Set destination address */
739			pRing->pHead->dar = dstAddr;
740		}
741		/* Set control information */
742		pRing->pHead->ctl.lo = controlParam;
743		/* Use "devCtl" to mark the memory that need to be freed later */
744		pRing->pHead->devCtl = dmacHw_FREE_USER_MEMORY;
745		/* Descriptor is now owned by the channel */
746		pRing->pHead->ctl.hi = 0;
747		/* Remember the descriptor last updated */
748		pRing->pEnd = pRing->pHead;
749		/* Update next descriptor */
750		dmacHw_NEXT_DESC(pRing, pHead);
751	}
752
753	/* Mark the end of the list */
754	pRing->pEnd->ctl.lo &=
755	    ~(dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN);
756	/* Connect the list */
757	if (pLast != pProg) {
758		pLast->ctl.lo |=
759		    dmacHw_REG_CTL_LLP_DST_EN | dmacHw_REG_CTL_LLP_SRC_EN;
760	}
761	/* Mark the descriptors are updated */
762	pCblk->descUpdated = 1;
763	if (!pCblk->varDataStarted) {
764		/* LLP must be pointing to the first descriptor */
765		dmacHw_SET_LLP(pCblk->module, pCblk->channel,
766			       (uint32_t) pProg - pRing->virt2PhyOffset);
767		/* Channel, handling variable data started */
768		pCblk->varDataStarted = 1;
769	}
770
771	return i;
772}
773
774/****************************************************************************/
775/**
776*  @brief   Read data DMAed to memory
777*
778*  This function will read data that has been DMAed to memory while transfering from:
779*          - Memory to memory
780*          - Peripheral to memory
781*
782*  @param    handle     -
783*  @param    ppBbuf     -
784*  @param    pLen       -
785*
786*  @return  0 - No more data is available to read
787*           1 - More data might be available to read
788*
789*/
790/****************************************************************************/
791int dmacHw_readTransferredData(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle */
792			       dmacHw_CONFIG_t *pConfig,	/*   [ IN ]  Configuration settings */
793			       void *pDescriptor,	/*   [ IN ] Descriptor buffer */
794			       void **ppBbuf,	/*   [ OUT ] Data received */
795			       size_t *pLlen	/*   [ OUT ] Length of the data received */
796    ) {
797	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
798
799	(void)handle;
800
801	if (pConfig->transferMode != dmacHw_TRANSFER_MODE_CONTINUOUS) {
802		if (((pRing->pTail->ctl.hi & dmacHw_DESC_FREE) == 0) ||
803		    (pRing->pTail == pRing->pHead)
804		    ) {
805			/* No receive data available */
806			*ppBbuf = (char *)NULL;
807			*pLlen = 0;
808
809			return 0;
810		}
811	}
812
813	/* Return read buffer and length */
814	*ppBbuf = (char *)pRing->pTail->dar;
815
816	/* Extract length of the received data */
817	if (DmaIsFlowController(pDescriptor)) {
818		uint32_t srcTrSize = 0;
819
820		switch (pRing->pTail->ctl.lo & dmacHw_REG_CTL_SRC_TR_WIDTH_MASK) {
821		case dmacHw_REG_CTL_SRC_TR_WIDTH_8:
822			srcTrSize = 1;
823			break;
824		case dmacHw_REG_CTL_SRC_TR_WIDTH_16:
825			srcTrSize = 2;
826			break;
827		case dmacHw_REG_CTL_SRC_TR_WIDTH_32:
828			srcTrSize = 4;
829			break;
830		case dmacHw_REG_CTL_SRC_TR_WIDTH_64:
831			srcTrSize = 8;
832			break;
833		default:
834			dmacHw_ASSERT(0);
835		}
836		/* Calculate length from the block size */
837		*pLlen =
838		    (pRing->pTail->ctl.hi & dmacHw_REG_CTL_BLOCK_TS_MASK) *
839		    srcTrSize;
840	} else {
841		/* Extract length from the source peripheral */
842		*pLlen = pRing->pTail->sstat;
843	}
844
845	/* Advance tail to next descriptor */
846	dmacHw_NEXT_DESC(pRing, pTail);
847
848	return 1;
849}
850
851/****************************************************************************/
852/**
853*  @brief   Set descriptor carrying control information
854*
855*  This function will be used to send specific control information to the device
856*  using the DMA channel
857*
858*
859*  @return  -1 - On failure
860*            0 - On success
861*
862*  @note
863*     None
864*/
865/****************************************************************************/
866int dmacHw_setControlDescriptor(dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
867				void *pDescriptor,	/*   [ IN ] Descriptor buffer */
868				uint32_t ctlAddress,	/*   [ IN ] Address of the device control register */
869				uint32_t control	/*   [ IN ] Device control information */
870    ) {
871	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor);
872
873	if (ctlAddress == 0) {
874		return -1;
875	}
876
877	/* Check the availability of descriptors in the ring */
878	if ((pRing->pHead->ctl.hi & dmacHw_DESC_FREE) == 0) {
879		return -1;
880	}
881	/* Set control information */
882	pRing->pHead->devCtl = control;
883	/* Set source and destination address */
884	pRing->pHead->sar = (uint32_t) &pRing->pHead->devCtl;
885	pRing->pHead->dar = ctlAddress;
886	/* Set control parameters */
887	if (pConfig->flowControler == dmacHw_FLOW_CONTROL_DMA) {
888		pRing->pHead->ctl.lo = pConfig->transferType |
889		    dmacHw_SRC_ADDRESS_UPDATE_MODE_INC |
890		    dmacHw_DST_ADDRESS_UPDATE_MODE_INC |
891		    dmacHw_SRC_TRANSACTION_WIDTH_32 |
892		    pConfig->dstMaxTransactionWidth |
893		    dmacHw_SRC_BURST_WIDTH_0 |
894		    dmacHw_DST_BURST_WIDTH_0 |
895		    pConfig->srcMasterInterface |
896		    pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN;
897	} else {
898		uint32_t transferType = 0;
899		switch (pConfig->transferType) {
900		case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM:
901			transferType = dmacHw_REG_CTL_TTFC_PM_PERI;
902			break;
903		case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL:
904			transferType = dmacHw_REG_CTL_TTFC_MP_PERI;
905			break;
906		default:
907			dmacHw_ASSERT(0);
908		}
909		pRing->pHead->ctl.lo = transferType |
910		    dmacHw_SRC_ADDRESS_UPDATE_MODE_INC |
911		    dmacHw_DST_ADDRESS_UPDATE_MODE_INC |
912		    dmacHw_SRC_TRANSACTION_WIDTH_32 |
913		    pConfig->dstMaxTransactionWidth |
914		    dmacHw_SRC_BURST_WIDTH_0 |
915		    dmacHw_DST_BURST_WIDTH_0 |
916		    pConfig->srcMasterInterface |
917		    pConfig->dstMasterInterface |
918		    pConfig->flowControler | dmacHw_REG_CTL_INT_EN;
919	}
920
921	/* Set block transaction size to one 32 bit transaction */
922	pRing->pHead->ctl.hi = dmacHw_REG_CTL_BLOCK_TS_MASK & 1;
923
924	/* Remember the descriptor to initialize the registers */
925	if (pRing->pProg == dmacHw_DESC_INIT) {
926		pRing->pProg = pRing->pHead;
927	}
928	pRing->pEnd = pRing->pHead;
929
930	/* Advance the descriptor */
931	dmacHw_NEXT_DESC(pRing, pHead);
932
933	/* Update Tail pointer if destination is a peripheral */
934	if (!dmacHw_DST_IS_MEMORY(pConfig->transferType)) {
935		pRing->pTail = pRing->pHead;
936	}
937	return 0;
938}
939
940/****************************************************************************/
941/**
942*  @brief   Sets channel specific user data
943*
944*  This function associates user data to a specif DMA channel
945*
946*/
947/****************************************************************************/
948void dmacHw_setChannelUserData(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle */
949			       void *userData	/*  [ IN ] User data */
950    ) {
951	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle);
952
953	pCblk->userData = userData;
954}
955
956/****************************************************************************/
957/**
958*  @brief   Gets channel specific user data
959*
960*  This function returns user data specific to a DMA channel
961*
962*  @return   user data
963*/
964/****************************************************************************/
965void *dmacHw_getChannelUserData(dmacHw_HANDLE_t handle	/*  [ IN ] DMA Channel handle */
966    ) {
967	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle);
968
969	return pCblk->userData;
970}
971
972/****************************************************************************/
973/**
974*  @brief   Resets descriptor control information
975*
976*  @return  void
977*/
978/****************************************************************************/
979void dmacHw_resetDescriptorControl(void *pDescriptor	/*   [ IN ] Descriptor buffer  */
980    ) {
981	int i;
982	dmacHw_DESC_RING_t *pRing;
983	dmacHw_DESC_t *pDesc;
984
985	pRing = dmacHw_GET_DESC_RING(pDescriptor);
986	pDesc = pRing->pHead;
987
988	for (i = 0; i < pRing->num; i++) {
989		/* Mark descriptor is ready to use */
990		pDesc->ctl.hi = dmacHw_DESC_FREE;
991		/* Look into next link list item */
992		pDesc++;
993	}
994	pRing->pFree = pRing->pTail = pRing->pEnd = pRing->pHead;
995	pRing->pProg = dmacHw_DESC_INIT;
996}
997
998/****************************************************************************/
999/**
1000*  @brief   Displays channel specific registers and other control parameters
1001*
1002*  @return  void
1003*
1004*
1005*  @note
1006*     None
1007*/
1008/****************************************************************************/
1009void dmacHw_printDebugInfo(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle */
1010			   void *pDescriptor,	/*   [ IN ] Descriptor buffer */
1011			   int (*fpPrint) (const char *, ...)	/*  [ IN ] Print callback function */
1012    ) {
1013	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle);
1014
1015	DisplayRegisterContents(pCblk->module, pCblk->channel, fpPrint);
1016	DisplayDescRing(pDescriptor, fpPrint);
1017}
1018