diff options
Diffstat (limited to 'arch/arm/mach-bcmring/csp/dmac/dmacHw.c')
| -rw-r--r-- | arch/arm/mach-bcmring/csp/dmac/dmacHw.c | 917 | 
1 files changed, 0 insertions, 917 deletions
diff --git a/arch/arm/mach-bcmring/csp/dmac/dmacHw.c b/arch/arm/mach-bcmring/csp/dmac/dmacHw.c deleted file mode 100644 index 6b9be2e98e5..00000000000 --- a/arch/arm/mach-bcmring/csp/dmac/dmacHw.c +++ /dev/null @@ -1,917 +0,0 @@ -/***************************************************************************** -* Copyright 2003 - 2008 Broadcom Corporation.  All rights reserved. -* -* Unless you and Broadcom execute a separate written software license -* agreement governing use of this software, this software is licensed to you -* under the terms of the GNU General Public License version 2, available at -* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -* -* Notwithstanding the above, under no circumstances may you combine this -* software in any way with any other Broadcom software provided under a -* license other than the GPL, without Broadcom's express prior written -* consent. -*****************************************************************************/ - -/****************************************************************************/ -/** -*  @file    dmacHw.c -* -*  @brief   Low level DMA controller driver routines -* -*  @note -* -*   These routines provide basic DMA functionality only. -*/ -/****************************************************************************/ - -/* ---- Include Files ---------------------------------------------------- */ -#include <csp/stdint.h> -#include <csp/string.h> -#include <stddef.h> - -#include <csp/dmacHw.h> -#include <mach/csp/dmacHw_reg.h> -#include <mach/csp/dmacHw_priv.h> -#include <mach/csp/chipcHw_inline.h> - -/* ---- External Function Prototypes ------------------------------------- */ - -/* Allocate DMA control blocks */ -dmacHw_CBLK_t dmacHw_gCblk[dmacHw_MAX_CHANNEL_COUNT]; - -uint32_t dmaChannelCount_0 = dmacHw_MAX_CHANNEL_COUNT / 2; -uint32_t dmaChannelCount_1 = dmacHw_MAX_CHANNEL_COUNT / 2; - -/****************************************************************************/ -/** -*  @brief   Get maximum FIFO for a DMA channel -* -*  @return  Maximum allowable FIFO size -* -* -*/ -/****************************************************************************/ -static uint32_t GetFifoSize(dmacHw_HANDLE_t handle	/*   [ IN ] DMA Channel handle */ -    ) { -	uint32_t val = 0; -	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); -	dmacHw_MISC_t *pMiscReg = -	    (dmacHw_MISC_t *) dmacHw_REG_MISC_BASE(pCblk->module); - -	switch (pCblk->channel) { -	case 0: -		val = (pMiscReg->CompParm2.lo & 0x70000000) >> 28; -		break; -	case 1: -		val = (pMiscReg->CompParm3.hi & 0x70000000) >> 28; -		break; -	case 2: -		val = (pMiscReg->CompParm3.lo & 0x70000000) >> 28; -		break; -	case 3: -		val = (pMiscReg->CompParm4.hi & 0x70000000) >> 28; -		break; -	case 4: -		val = (pMiscReg->CompParm4.lo & 0x70000000) >> 28; -		break; -	case 5: -		val = (pMiscReg->CompParm5.hi & 0x70000000) >> 28; -		break; -	case 6: -		val = (pMiscReg->CompParm5.lo & 0x70000000) >> 28; -		break; -	case 7: -		val = (pMiscReg->CompParm6.hi & 0x70000000) >> 28; -		break; -	} - -	if (val <= 0x4) { -		return 8 << val; -	} else { -		dmacHw_ASSERT(0); -	} -	return 0; -} - -/****************************************************************************/ -/** -*  @brief   Program channel register to initiate transfer -* -*  @return  void -* -* -*  @note -*     - Descriptor buffer MUST ALWAYS be flushed before calling this function -*     - This function should also be called from ISR to program the channel with -*       pending descriptors -*/ -/****************************************************************************/ -void dmacHw_initiateTransfer(dmacHw_HANDLE_t handle,	/*   [ IN ] DMA Channel handle */ -			     dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */ -			     void *pDescriptor	/*   [ IN ] Descriptor buffer */ -    ) { -	dmacHw_DESC_RING_t *pRing; -	dmacHw_DESC_t *pProg; -	dmacHw_CBLK_t *pCblk; - -	pCblk = dmacHw_HANDLE_TO_CBLK(handle); -	pRing = dmacHw_GET_DESC_RING(pDescriptor); - -	if (CHANNEL_BUSY(pCblk->module, pCblk->channel)) { -		/* Not safe yet to program the channel */ -		return; -	} - -	if (pCblk->varDataStarted) { -		if (pCblk->descUpdated) { -			pCblk->descUpdated = 0; -			pProg = -			    (dmacHw_DESC_t *) ((uint32_t) -					       dmacHw_REG_LLP(pCblk->module, -							      pCblk->channel) + -					       pRing->virt2PhyOffset); - -			/* Load descriptor if not loaded */ -			if (!(pProg->ctl.hi & dmacHw_REG_CTL_DONE)) { -				dmacHw_SET_SAR(pCblk->module, pCblk->channel, -					       pProg->sar); -				dmacHw_SET_DAR(pCblk->module, pCblk->channel, -					       pProg->dar); -				dmacHw_REG_CTL_LO(pCblk->module, -						  pCblk->channel) = -				    pProg->ctl.lo; -				dmacHw_REG_CTL_HI(pCblk->module, -						  pCblk->channel) = -				    pProg->ctl.hi; -			} else if (pProg == (dmacHw_DESC_t *) pRing->pEnd->llp) { -				/* Return as end descriptor is processed */ -				return; -			} else { -				dmacHw_ASSERT(0); -			} -		} else { -			return; -		} -	} else { -		if (pConfig->transferMode == dmacHw_TRANSFER_MODE_PERIODIC) { -			/* Do not make a single chain, rather process one descriptor at a time */ -			pProg = pRing->pHead; -			/* Point to the next descriptor for next iteration */ -			dmacHw_NEXT_DESC(pRing, pHead); -		} else { -			/* Return if no more pending descriptor */ -			if (pRing->pEnd == NULL) { -				return; -			} - -			pProg = pRing->pProg; -			if (pConfig->transferMode == -			    dmacHw_TRANSFER_MODE_CONTINUOUS) { -				/* Make sure a complete ring can be formed */ -				dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pEnd-> -					      llp == pRing->pProg); -				/* Make sure pProg pointing to the pHead */ -				dmacHw_ASSERT((dmacHw_DESC_t *) pRing->pProg == -					      pRing->pHead); -				/* Make a complete ring */ -				do { -					pRing->pProg->ctl.lo |= -					    (dmacHw_REG_CTL_LLP_DST_EN | -					     dmacHw_REG_CTL_LLP_SRC_EN); -					pRing->pProg = -					    (dmacHw_DESC_t *) pRing->pProg->llp; -				} while (pRing->pProg != pRing->pHead); -			} else { -				/* Make a single long chain */ -				while (pRing->pProg != pRing->pEnd) { -					pRing->pProg->ctl.lo |= -					    (dmacHw_REG_CTL_LLP_DST_EN | -					     dmacHw_REG_CTL_LLP_SRC_EN); -					pRing->pProg = -					    (dmacHw_DESC_t *) pRing->pProg->llp; -				} -			} -		} - -		/* Program the channel registers */ -		dmacHw_SET_SAR(pCblk->module, pCblk->channel, pProg->sar); -		dmacHw_SET_DAR(pCblk->module, pCblk->channel, pProg->dar); -		dmacHw_SET_LLP(pCblk->module, pCblk->channel, -			       (uint32_t) pProg - pRing->virt2PhyOffset); -		dmacHw_REG_CTL_LO(pCblk->module, pCblk->channel) = -		    pProg->ctl.lo; -		dmacHw_REG_CTL_HI(pCblk->module, pCblk->channel) = -		    pProg->ctl.hi; -		if (pRing->pEnd) { -			/* Remember the descriptor to use next */ -			pRing->pProg = (dmacHw_DESC_t *) pRing->pEnd->llp; -		} -		/* Indicate no more pending descriptor  */ -		pRing->pEnd = (dmacHw_DESC_t *) NULL; -	} -	/* Start DMA operation */ -	dmacHw_DMA_START(pCblk->module, pCblk->channel); -} - -/****************************************************************************/ -/** -*  @brief   Initializes DMA -* -*  This function initializes DMA CSP driver -* -*  @note -*     Must be called before using any DMA channel -*/ -/****************************************************************************/ -void dmacHw_initDma(void) -{ - -	uint32_t i = 0; - -	dmaChannelCount_0 = dmacHw_GET_NUM_CHANNEL(0); -	dmaChannelCount_1 = dmacHw_GET_NUM_CHANNEL(1); - -	/* Enable access to the DMA block */ -	chipcHw_busInterfaceClockEnable(chipcHw_REG_BUS_CLOCK_DMAC0); -	chipcHw_busInterfaceClockEnable(chipcHw_REG_BUS_CLOCK_DMAC1); - -	if ((dmaChannelCount_0 + dmaChannelCount_1) > dmacHw_MAX_CHANNEL_COUNT) { -		dmacHw_ASSERT(0); -	} - -	memset((void *)dmacHw_gCblk, 0, -	       sizeof(dmacHw_CBLK_t) * (dmaChannelCount_0 + dmaChannelCount_1)); -	for (i = 0; i < dmaChannelCount_0; i++) { -		dmacHw_gCblk[i].module = 0; -		dmacHw_gCblk[i].channel = i; -	} -	for (i = 0; i < dmaChannelCount_1; i++) { -		dmacHw_gCblk[i + dmaChannelCount_0].module = 1; -		dmacHw_gCblk[i + dmaChannelCount_0].channel = i; -	} -} - -/****************************************************************************/ -/** -*  @brief   Exit function for  DMA -* -*  This function isolates DMA from the system -* -*/ -/****************************************************************************/ -void dmacHw_exitDma(void) -{ -	/* Disable access to the DMA block */ -	chipcHw_busInterfaceClockDisable(chipcHw_REG_BUS_CLOCK_DMAC0); -	chipcHw_busInterfaceClockDisable(chipcHw_REG_BUS_CLOCK_DMAC1); -} - -/****************************************************************************/ -/** -*  @brief   Gets a handle to a DMA channel -* -*  This function returns a handle, representing a control block of a particular DMA channel -* -*  @return  -1       - On Failure -*            handle  - On Success, representing a channel control block -* -*  @note -*     None  Channel ID must be created using "dmacHw_MAKE_CHANNEL_ID" macro -*/ -/****************************************************************************/ -dmacHw_HANDLE_t dmacHw_getChannelHandle(dmacHw_ID_t channelId	/* [ IN ] DMA Channel Id */ -    ) { -	int idx; - -	switch ((channelId >> 8)) { -	case 0: -		dmacHw_ASSERT((channelId & 0xff) < dmaChannelCount_0); -		idx = (channelId & 0xff); -		break; -	case 1: -		dmacHw_ASSERT((channelId & 0xff) < dmaChannelCount_1); -		idx = dmaChannelCount_0 + (channelId & 0xff); -		break; -	default: -		dmacHw_ASSERT(0); -		return (dmacHw_HANDLE_t) -1; -	} - -	return dmacHw_CBLK_TO_HANDLE(&dmacHw_gCblk[idx]); -} - -/****************************************************************************/ -/** -*  @brief   Initializes a DMA channel for use -* -*  This function initializes and resets a DMA channel for use -* -*  @return  -1     - On Failure -*            0     - On Success -* -*  @note -*     None -*/ -/****************************************************************************/ -int dmacHw_initChannel(dmacHw_HANDLE_t handle	/*   [ IN ] DMA Channel handle */ -    ) { -	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); -	int module = pCblk->module; -	int channel = pCblk->channel; - -	/* Reinitialize the control block */ -	memset((void *)pCblk, 0, sizeof(dmacHw_CBLK_t)); -	pCblk->module = module; -	pCblk->channel = channel; - -	/* Enable DMA controller */ -	dmacHw_DMA_ENABLE(pCblk->module); -	/* Reset DMA channel */ -	dmacHw_RESET_CONTROL_LO(pCblk->module, pCblk->channel); -	dmacHw_RESET_CONTROL_HI(pCblk->module, pCblk->channel); -	dmacHw_RESET_CONFIG_LO(pCblk->module, pCblk->channel); -	dmacHw_RESET_CONFIG_HI(pCblk->module, pCblk->channel); - -	/* Clear all raw interrupt status */ -	dmacHw_TRAN_INT_CLEAR(pCblk->module, pCblk->channel); -	dmacHw_BLOCK_INT_CLEAR(pCblk->module, pCblk->channel); -	dmacHw_ERROR_INT_CLEAR(pCblk->module, pCblk->channel); - -	/* Mask event specific interrupts */ -	dmacHw_TRAN_INT_DISABLE(pCblk->module, pCblk->channel); -	dmacHw_BLOCK_INT_DISABLE(pCblk->module, pCblk->channel); -	dmacHw_STRAN_INT_DISABLE(pCblk->module, pCblk->channel); -	dmacHw_DTRAN_INT_DISABLE(pCblk->module, pCblk->channel); -	dmacHw_ERROR_INT_DISABLE(pCblk->module, pCblk->channel); - -	return 0; -} - -/****************************************************************************/ -/** -*  @brief  Finds amount of memory required to form a descriptor ring -* -* -*  @return   Number of bytes required to form a descriptor ring -* -* -*/ -/****************************************************************************/ -uint32_t dmacHw_descriptorLen(uint32_t descCnt	/* [ IN ] Number of descriptor in the ring */ -    ) { -	/* Need extra 4 byte to ensure 32 bit alignment  */ -	return (descCnt * sizeof(dmacHw_DESC_t)) + sizeof(dmacHw_DESC_RING_t) + -		sizeof(uint32_t); -} - -/****************************************************************************/ -/** -*  @brief   Initializes descriptor ring -* -*  This function will initializes the descriptor ring of a DMA channel -* -* -*  @return   -1 - On failure -*             0 - On success -*  @note -*     - "len" parameter should be obtained from "dmacHw_descriptorLen" -*     - Descriptor buffer MUST be 32 bit aligned and uncached as it is -*       accessed by ARM and DMA -*/ -/****************************************************************************/ -int dmacHw_initDescriptor(void *pDescriptorVirt,	/*  [ IN ] Virtual address of uncahced buffer allocated to form descriptor ring */ -			  uint32_t descriptorPhyAddr,	/*  [ IN ] Physical address of pDescriptorVirt (descriptor buffer) */ -			  uint32_t len,	/*  [ IN ] Size of the pBuf */ -			  uint32_t num	/*  [ IN ] Number of descriptor in the ring */ -    ) { -	uint32_t i; -	dmacHw_DESC_RING_t *pRing; -	dmacHw_DESC_t *pDesc; - -	/* Check the alignment of the descriptor */ -	if ((uint32_t) pDescriptorVirt & 0x00000003) { -		dmacHw_ASSERT(0); -		return -1; -	} - -	/* Check if enough space has been allocated for descriptor ring */ -	if (len < dmacHw_descriptorLen(num)) { -		return -1; -	} - -	pRing = dmacHw_GET_DESC_RING(pDescriptorVirt); -	pRing->pHead = -	    (dmacHw_DESC_t *) ((uint32_t) pRing + sizeof(dmacHw_DESC_RING_t)); -	pRing->pFree = pRing->pTail = pRing->pEnd = pRing->pHead; -	pRing->pProg = dmacHw_DESC_INIT; -	/* Initialize link item chain, starting from the head */ -	pDesc = pRing->pHead; -	/* Find the offset between virtual to physical address */ -	pRing->virt2PhyOffset = (uint32_t) pDescriptorVirt - descriptorPhyAddr; - -	/* Form the descriptor ring */ -	for (i = 0; i < num - 1; i++) { -		/* Clear link list item */ -		memset((void *)pDesc, 0, sizeof(dmacHw_DESC_t)); -		/* Point to the next item in the physical address */ -		pDesc->llpPhy = (uint32_t) (pDesc + 1) - pRing->virt2PhyOffset; -		/* Point to the next item in the virtual address */ -		pDesc->llp = (uint32_t) (pDesc + 1); -		/* Mark descriptor is ready to use */ -		pDesc->ctl.hi = dmacHw_DESC_FREE; -		/* Look into next link list item */ -		pDesc++; -	} - -	/* Clear last link list item */ -	memset((void *)pDesc, 0, sizeof(dmacHw_DESC_t)); -	/* Last item pointing to the first item in the -	   physical address to complete the ring */ -	pDesc->llpPhy = (uint32_t) pRing->pHead - pRing->virt2PhyOffset; -	/* Last item pointing to the first item in the -	   virtual address to complete the ring -	 */ -	pDesc->llp = (uint32_t) pRing->pHead; -	/* Mark descriptor is ready to use */ -	pDesc->ctl.hi = dmacHw_DESC_FREE; -	/* Set the number of descriptors in the ring */ -	pRing->num = num; -	return 0; -} - -/****************************************************************************/ -/** -*  @brief   Configure DMA channel -* -*  @return  0  : On success -*           -1 : On failure -*/ -/****************************************************************************/ -int dmacHw_configChannel(dmacHw_HANDLE_t handle,	/*   [ IN ] DMA Channel handle */ -			 dmacHw_CONFIG_t *pConfig	/*   [ IN ] Configuration settings */ -    ) { -	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); -	uint32_t cfgHigh = 0; -	int srcTrSize; -	int dstTrSize; - -	pCblk->varDataStarted = 0; -	pCblk->userData = NULL; - -	/* Configure -	   - Burst transaction when enough data in available in FIFO -	   - AHB Access protection 1 -	   - Source and destination peripheral ports -	 */ -	cfgHigh = -	    dmacHw_REG_CFG_HI_FIFO_ENOUGH | dmacHw_REG_CFG_HI_AHB_HPROT_1 | -	    dmacHw_SRC_PERI_INTF(pConfig-> -				 srcPeripheralPort) | -	    dmacHw_DST_PERI_INTF(pConfig->dstPeripheralPort); -	/* Set priority */ -	dmacHw_SET_CHANNEL_PRIORITY(pCblk->module, pCblk->channel, -				    pConfig->channelPriority); - -	if (pConfig->dstStatusRegisterAddress != 0) { -		/* Destination status update enable */ -		cfgHigh |= dmacHw_REG_CFG_HI_UPDATE_DST_STAT; -		/* Configure status registers */ -		dmacHw_SET_DSTATAR(pCblk->module, pCblk->channel, -				   pConfig->dstStatusRegisterAddress); -	} - -	if (pConfig->srcStatusRegisterAddress != 0) { -		/* Source status update enable */ -		cfgHigh |= dmacHw_REG_CFG_HI_UPDATE_SRC_STAT; -		/* Source status update enable */ -		dmacHw_SET_SSTATAR(pCblk->module, pCblk->channel, -				   pConfig->srcStatusRegisterAddress); -	} -	/* Configure the config high register */ -	dmacHw_GET_CONFIG_HI(pCblk->module, pCblk->channel) = cfgHigh; - -	/* Clear all raw interrupt status */ -	dmacHw_TRAN_INT_CLEAR(pCblk->module, pCblk->channel); -	dmacHw_BLOCK_INT_CLEAR(pCblk->module, pCblk->channel); -	dmacHw_ERROR_INT_CLEAR(pCblk->module, pCblk->channel); - -	/* Configure block interrupt */ -	if (pConfig->blockTransferInterrupt == dmacHw_INTERRUPT_ENABLE) { -		dmacHw_BLOCK_INT_ENABLE(pCblk->module, pCblk->channel); -	} else { -		dmacHw_BLOCK_INT_DISABLE(pCblk->module, pCblk->channel); -	} -	/* Configure complete transfer interrupt */ -	if (pConfig->completeTransferInterrupt == dmacHw_INTERRUPT_ENABLE) { -		dmacHw_TRAN_INT_ENABLE(pCblk->module, pCblk->channel); -	} else { -		dmacHw_TRAN_INT_DISABLE(pCblk->module, pCblk->channel); -	} -	/* Configure error interrupt */ -	if (pConfig->errorInterrupt == dmacHw_INTERRUPT_ENABLE) { -		dmacHw_ERROR_INT_ENABLE(pCblk->module, pCblk->channel); -	} else { -		dmacHw_ERROR_INT_DISABLE(pCblk->module, pCblk->channel); -	} -	/* Configure gather register */ -	if (pConfig->srcGatherWidth) { -		srcTrSize = -		    dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth); -		if (! -		    ((pConfig->srcGatherWidth % srcTrSize) -		     && (pConfig->srcGatherJump % srcTrSize))) { -			dmacHw_REG_SGR_LO(pCblk->module, pCblk->channel) = -			    ((pConfig->srcGatherWidth / -			      srcTrSize) << 20) | (pConfig->srcGatherJump / -						   srcTrSize); -		} else { -			return -1; -		} -	} -	/* Configure scatter register */ -	if (pConfig->dstScatterWidth) { -		dstTrSize = -		    dmacHw_GetTrWidthInBytes(pConfig->dstMaxTransactionWidth); -		if (! -		    ((pConfig->dstScatterWidth % dstTrSize) -		     && (pConfig->dstScatterJump % dstTrSize))) { -			dmacHw_REG_DSR_LO(pCblk->module, pCblk->channel) = -			    ((pConfig->dstScatterWidth / -			      dstTrSize) << 20) | (pConfig->dstScatterJump / -						   dstTrSize); -		} else { -			return -1; -		} -	} -	return 0; -} - -/****************************************************************************/ -/** -*  @brief   Indicates whether DMA transfer is in progress or completed -* -*  @return   DMA transfer status -*          dmacHw_TRANSFER_STATUS_BUSY:         DMA Transfer ongoing -*          dmacHw_TRANSFER_STATUS_DONE:         DMA Transfer completed -*          dmacHw_TRANSFER_STATUS_ERROR:        DMA Transfer error -* -*/ -/****************************************************************************/ -dmacHw_TRANSFER_STATUS_e dmacHw_transferCompleted(dmacHw_HANDLE_t handle	/*   [ IN ] DMA Channel handle */ -    ) { -	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); - -	if (CHANNEL_BUSY(pCblk->module, pCblk->channel)) { -		return dmacHw_TRANSFER_STATUS_BUSY; -	} else if (dmacHw_REG_INT_RAW_ERROR(pCblk->module) & -		   (0x00000001 << pCblk->channel)) { -		return dmacHw_TRANSFER_STATUS_ERROR; -	} - -	return dmacHw_TRANSFER_STATUS_DONE; -} - -/****************************************************************************/ -/** -*  @brief   Set descriptors for known data length -* -*  When DMA has to work as a flow controller, this function prepares the -*  descriptor chain to transfer data -* -*  from: -*          - Memory to memory -*          - Peripheral to memory -*          - Memory to Peripheral -*          - Peripheral to Peripheral -* -*  @return   -1 - On failure -*             0 - On success -* -*/ -/****************************************************************************/ -int dmacHw_setDataDescriptor(dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */ -			     void *pDescriptor,	/*   [ IN ] Descriptor buffer */ -			     void *pSrcAddr,	/*   [ IN ] Source (Peripheral/Memory) address */ -			     void *pDstAddr,	/*   [ IN ] Destination (Peripheral/Memory) address */ -			     size_t dataLen	/*   [ IN ] Data length in bytes */ -    ) { -	dmacHw_TRANSACTION_WIDTH_e dstTrWidth; -	dmacHw_TRANSACTION_WIDTH_e srcTrWidth; -	dmacHw_DESC_RING_t *pRing = dmacHw_GET_DESC_RING(pDescriptor); -	dmacHw_DESC_t *pStart; -	dmacHw_DESC_t *pProg; -	int srcTs = 0; -	int blkTs = 0; -	int oddSize = 0; -	int descCount = 0; -	int count = 0; -	int dstTrSize = 0; -	int srcTrSize = 0; -	uint32_t maxBlockSize = dmacHw_MAX_BLOCKSIZE; - -	dstTrSize = dmacHw_GetTrWidthInBytes(pConfig->dstMaxTransactionWidth); -	srcTrSize = dmacHw_GetTrWidthInBytes(pConfig->srcMaxTransactionWidth); - -	/* Skip Tx if buffer is NULL  or length is unknown */ -	if ((pSrcAddr == NULL) || (pDstAddr == NULL) || (dataLen == 0)) { -		/* Do not initiate transfer */ -		return -1; -	} - -	/* Ensure scatter and gather are transaction aligned */ -	if ((pConfig->srcGatherWidth % srcTrSize) -	    || (pConfig->dstScatterWidth % dstTrSize)) { -		return -2; -	} - -	/* -	   Background 1: DMAC can not perform DMA if source and destination addresses are -	   not properly aligned with the channel's transaction width. So, for successful -	   DMA transfer, transaction width must be set according to the alignment of the -	   source and destination address. -	 */ - -	/* Adjust destination transaction width if destination address is not aligned properly */ -	dstTrWidth = pConfig->dstMaxTransactionWidth; -	while (dmacHw_ADDRESS_MASK(dstTrSize) & (uint32_t) pDstAddr) { -		dstTrWidth = dmacHw_GetNextTrWidth(dstTrWidth); -		dstTrSize = dmacHw_GetTrWidthInBytes(dstTrWidth); -	} - -	/* Adjust source transaction width if source address is not aligned properly */ -	srcTrWidth = pConfig->srcMaxTransactionWidth; -	while (dmacHw_ADDRESS_MASK(srcTrSize) & (uint32_t) pSrcAddr) { -		srcTrWidth = dmacHw_GetNextTrWidth(srcTrWidth); -		srcTrSize = dmacHw_GetTrWidthInBytes(srcTrWidth); -	} - -	/* Find the maximum transaction per descriptor */ -	if (pConfig->maxDataPerBlock -	    && ((pConfig->maxDataPerBlock / srcTrSize) < -		dmacHw_MAX_BLOCKSIZE)) { -		maxBlockSize = pConfig->maxDataPerBlock / srcTrSize; -	} - -	/* Find number of source transactions needed to complete the DMA transfer */ -	srcTs = dataLen / srcTrSize; -	/* Find the odd number of bytes that need to be transferred as single byte transaction width */ -	if (srcTs && (dstTrSize > srcTrSize)) { -		oddSize = dataLen % dstTrSize; -		/* Adjust source transaction count due to "oddSize" */ -		srcTs = srcTs - (oddSize / srcTrSize); -	} else { -		oddSize = dataLen % srcTrSize; -	} -	/* Adjust "descCount" due to "oddSize" */ -	if (oddSize) { -		descCount++; -	} -	/* Find the number of descriptor needed for total "srcTs" */ -	if (srcTs) { -		descCount += ((srcTs - 1) / maxBlockSize) + 1; -	} - -	/* Check the availability of "descCount" discriptors in the ring */ -	pProg = pRing->pHead; -	for (count = 0; (descCount <= pRing->num) && (count < descCount); -	     count++) { -		if ((pProg->ctl.hi & dmacHw_DESC_FREE) == 0) { -			/* Sufficient descriptors are not available */ -			return -3; -		} -		pProg = (dmacHw_DESC_t *) pProg->llp; -	} - -	/* Remember the link list item to program the channel registers */ -	pStart = pProg = pRing->pHead; -	/* Make a link list with "descCount(=count)" number of descriptors */ -	while (count) { -		/* Reset channel control information */ -		pProg->ctl.lo = 0; -		/* Enable source gather if configured */ -		if (pConfig->srcGatherWidth) { -			pProg->ctl.lo |= dmacHw_REG_CTL_SG_ENABLE; -		} -		/* Enable destination scatter if configured */ -		if (pConfig->dstScatterWidth) { -			pProg->ctl.lo |= dmacHw_REG_CTL_DS_ENABLE; -		} -		/* Set source and destination address */ -		pProg->sar = (uint32_t) pSrcAddr; -		pProg->dar = (uint32_t) pDstAddr; -		/* Use "devCtl" to mark that user memory need to be freed later if needed */ -		if (pProg == pRing->pHead) { -			pProg->devCtl = dmacHw_FREE_USER_MEMORY; -		} else { -			pProg->devCtl = 0; -		} - -		blkTs = srcTs; - -		/* Special treatmeant for last descriptor */ -		if (count == 1) { -			/* Mark the last descriptor */ -			pProg->ctl.lo &= -			    ~(dmacHw_REG_CTL_LLP_DST_EN | -			      dmacHw_REG_CTL_LLP_SRC_EN); -			/* Treatment for odd data bytes */ -			if (oddSize) { -				/* Adjust for single byte transaction width */ -				switch (pConfig->transferType) { -				case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM: -					dstTrWidth = -					    dmacHw_DST_TRANSACTION_WIDTH_8; -					blkTs = -					    (oddSize / srcTrSize) + -					    ((oddSize % srcTrSize) ? 1 : 0); -					break; -				case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL: -					srcTrWidth = -					    dmacHw_SRC_TRANSACTION_WIDTH_8; -					blkTs = oddSize; -					break; -				case dmacHw_TRANSFER_TYPE_MEM_TO_MEM: -					srcTrWidth = -					    dmacHw_SRC_TRANSACTION_WIDTH_8; -					dstTrWidth = -					    dmacHw_DST_TRANSACTION_WIDTH_8; -					blkTs = oddSize; -					break; -				case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_PERIPHERAL: -					/* Do not adjust the transaction width  */ -					break; -				} -			} else { -				srcTs -= blkTs; -			} -		} else { -			if (srcTs / maxBlockSize) { -				blkTs = maxBlockSize; -			} -			/* Remaining source transactions for next iteration */ -			srcTs -= blkTs; -		} -		/* Must have a valid source transactions */ -		dmacHw_ASSERT(blkTs > 0); -		/* Set control information */ -		if (pConfig->flowControler == dmacHw_FLOW_CONTROL_DMA) { -			pProg->ctl.lo |= pConfig->transferType | -			    pConfig->srcUpdate | -			    pConfig->dstUpdate | -			    srcTrWidth | -			    dstTrWidth | -			    pConfig->srcMaxBurstWidth | -			    pConfig->dstMaxBurstWidth | -			    pConfig->srcMasterInterface | -			    pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN; -		} else { -			uint32_t transferType = 0; -			switch (pConfig->transferType) { -			case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM: -				transferType = dmacHw_REG_CTL_TTFC_PM_PERI; -				break; -			case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL: -				transferType = dmacHw_REG_CTL_TTFC_MP_PERI; -				break; -			default: -				dmacHw_ASSERT(0); -			} -			pProg->ctl.lo |= transferType | -			    pConfig->srcUpdate | -			    pConfig->dstUpdate | -			    srcTrWidth | -			    dstTrWidth | -			    pConfig->srcMaxBurstWidth | -			    pConfig->dstMaxBurstWidth | -			    pConfig->srcMasterInterface | -			    pConfig->dstMasterInterface | dmacHw_REG_CTL_INT_EN; -		} - -		/* Set block transaction size */ -		pProg->ctl.hi = blkTs & dmacHw_REG_CTL_BLOCK_TS_MASK; -		/* Look for next descriptor */ -		if (count > 1) { -			/* Point to the next descriptor */ -			pProg = (dmacHw_DESC_t *) pProg->llp; - -			/* Update source and destination address for next iteration */ -			switch (pConfig->transferType) { -			case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM: -				if (pConfig->dstScatterWidth) { -					pDstAddr = -					    (char *)pDstAddr + -					    blkTs * srcTrSize + -					    (((blkTs * srcTrSize) / -					      pConfig->dstScatterWidth) * -					     pConfig->dstScatterJump); -				} else { -					pDstAddr = -					    (char *)pDstAddr + -					    blkTs * srcTrSize; -				} -				break; -			case dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL: -				if (pConfig->srcGatherWidth) { -					pSrcAddr = -					    (char *)pDstAddr + -					    blkTs * srcTrSize + -					    (((blkTs * srcTrSize) / -					      pConfig->srcGatherWidth) * -					     pConfig->srcGatherJump); -				} else { -					pSrcAddr = -					    (char *)pSrcAddr + -					    blkTs * srcTrSize; -				} -				break; -			case dmacHw_TRANSFER_TYPE_MEM_TO_MEM: -				if (pConfig->dstScatterWidth) { -					pDstAddr = -					    (char *)pDstAddr + -					    blkTs * srcTrSize + -					    (((blkTs * srcTrSize) / -					      pConfig->dstScatterWidth) * -					     pConfig->dstScatterJump); -				} else { -					pDstAddr = -					    (char *)pDstAddr + -					    blkTs * srcTrSize; -				} - -				if (pConfig->srcGatherWidth) { -					pSrcAddr = -					    (char *)pDstAddr + -					    blkTs * srcTrSize + -					    (((blkTs * srcTrSize) / -					      pConfig->srcGatherWidth) * -					     pConfig->srcGatherJump); -				} else { -					pSrcAddr = -					    (char *)pSrcAddr + -					    blkTs * srcTrSize; -				} -				break; -			case dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_PERIPHERAL: -				/* Do not adjust the address */ -				break; -			default: -				dmacHw_ASSERT(0); -			} -		} else { -			/* At the end of transfer "srcTs" must be zero */ -			dmacHw_ASSERT(srcTs == 0); -		} -		count--; -	} - -	/* Remember the descriptor to initialize the registers */ -	if (pRing->pProg == dmacHw_DESC_INIT) { -		pRing->pProg = pStart; -	} -	/* Indicate that the descriptor is updated */ -	pRing->pEnd = pProg; -	/* Head pointing to the next descriptor */ -	pRing->pHead = (dmacHw_DESC_t *) pProg->llp; -	/* Update Tail pointer if destination is a peripheral, -	   because no one is going to read from the pTail -	 */ -	if (!dmacHw_DST_IS_MEMORY(pConfig->transferType)) { -		pRing->pTail = pRing->pHead; -	} -	return 0; -} - -/****************************************************************************/ -/** -*  @brief   Provides DMA controller attributes -* -* -*  @return  DMA controller attributes -* -*  @note -*     None -*/ -/****************************************************************************/ -uint32_t dmacHw_getDmaControllerAttribute(dmacHw_HANDLE_t handle,	/*  [ IN ]  DMA Channel handle */ -					  dmacHw_CONTROLLER_ATTRIB_e attr	/*  [ IN ]  DMA Controller attribute of type  dmacHw_CONTROLLER_ATTRIB_e */ -    ) { -	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle); - -	switch (attr) { -	case dmacHw_CONTROLLER_ATTRIB_CHANNEL_NUM: -		return dmacHw_GET_NUM_CHANNEL(pCblk->module); -	case dmacHw_CONTROLLER_ATTRIB_CHANNEL_MAX_BLOCK_SIZE: -		return (1 << -			 (dmacHw_GET_MAX_BLOCK_SIZE -			  (pCblk->module, pCblk->module) + 2)) - 8; -	case dmacHw_CONTROLLER_ATTRIB_MASTER_INTF_NUM: -		return dmacHw_GET_NUM_INTERFACE(pCblk->module); -	case dmacHw_CONTROLLER_ATTRIB_CHANNEL_BUS_WIDTH: -		return 32 << dmacHw_GET_CHANNEL_DATA_WIDTH(pCblk->module, -							   pCblk->channel); -	case dmacHw_CONTROLLER_ATTRIB_CHANNEL_FIFO_SIZE: -		return GetFifoSize(handle); -	} -	dmacHw_ASSERT(0); -	return 0; -}  |