/*******************************************************************************
*
* pl330DmaChanMicroCodeCreate - create micro code for dma transfer
*
* This routine create micro code for dma transfer
*
* RETURNS: OK or ERROR if there is an error.
*
* ERRNO: N/A
*/
LOCAL STATUS pl330DmaChanMicroCodeCreate
(
VXB_DEVICE_ID pDev,
PL330_DMA_CHAN * pChan
)
{
UINT32 chan;
UINT32 ccr;
UINT32 loop0;
UINT32 loop1;
UINT32 rest;
UINT8 * pBuf;
UINT32 loop0Start;
UINT32 loop1Start;
UINT32 burstSize;
PL330_DMA_CHAN_PARAM * pChanParam;
chan = pChan->chanNum;
pChanParam = pChan->pChanParam;
pBuf = pChan->pMicroCodeBuf;
bzero ((char *)pChan->pMicroCodeBuf, PL330_MICROCODE_SIZE);
/* switch to 1 byte mode if address not align with burst size */
if ((pChanParam->srcBurstSize == 1) ||
(!ALIGNED (pChanParam->srcAddr, pChanParam->srcBurstSize)) ||
(!ALIGNED (pChanParam->dstAddr, pChanParam->srcBurstSize)))
{
burstSize = CCR_BURST_SIZE_1;
pChanParam->srcBurstSize = 1;
}
else if (pChanParam->srcBurstSize == 2)
{
burstSize = CCR_BURST_SIZE_2;
}
else if (pChanParam->srcBurstSize == 4)
{
burstSize = CCR_BURST_SIZE_4;
}
else if (pChanParam->srcBurstSize == 8)
{
burstSize = CCR_BURST_SIZE_8;
}
else if (pChanParam->srcBurstSize == 16)
{
burstSize = CCR_BURST_SIZE_16;
}
else
{
return ERROR;
}
ccr = (pChanParam->endianSwapSize |
CCR_DST_CACHE_CTRL |
CCR_SRC_CACHE_CTRL |
CCR_DST_PROT_CTRL |
CCR_SRC_PROT_CTRL |
pChanParam->dstInc |
pChanParam->srcInc |
CCR_DST_BURST_LEN |
CCR_SRC_BURST_LEN |
(burstSize << 15) |
(burstSize << 1));
DMAMOV (pBuf, CCR, ccr); /* DMAMOV CCR, ccr */
DMAMOV (pBuf, SAR, pChanParam->srcAddr); /* DMAMOV SAR, src */
DMAMOV (pBuf, DAR, pChanParam->dstAddr); /* DMAMOV DAR, dst */
loop0 = pChanParam->transferSize / pChanParam->srcBurstSize;
if (loop0 > MAXLOOP)
{
PL330_DMA_DBG_MSG (10, "Too big size! 0x%x\r\n", pChanParam->srcAddr,
1, 2, 3, 4, 5);
return ERROR;
}
else
{
loop1 = loop0 / 256;
}
rest = pChanParam->transferSize % pChanParam->srcBurstSize;
if (loop1 > 0)
{
DMALP (pBuf, 1, loop1); /* DMALP loop1 */
loop1Start = (UINT32)pBuf;
DMALP (pBuf, 0, 256); /* DMALP loop0 */
loop0Start = (UINT32)pBuf;
if (pChanParam->tansferType != MEM_TO_MEM)
{
DMAWFP (pBuf, pChanParam->peripheral);
}
DMALD (pBuf); /* DMALD */
DMARMB (pBuf); /* DMARMB */
DMAST (pBuf); /* DMAST */
DMAWMB (pBuf); /* DMAWMB */
DMALPEND (pBuf, 0, loop0Start); /* DMALPEND loop0 */
DMALPEND (pBuf, 1, loop1Start); /* DMALPEND loop1 */
}
loop0 = loop0 % 256;
if (loop0 > 0)
{
DMALP (pBuf, 0, loop0); /* DMALP loop0 */
loop0Start = (UINT32)pBuf;
if (pChanParam->tansferType != MEM_TO_MEM)
{
DMAWFP (pBuf, pChanParam->peripheral);
}
DMALD (pBuf); /* DMALD */
DMARMB (pBuf); /* DMARMB */
DMAST (pBuf); /* DMAST */
DMAWMB (pBuf); /* DMAWMB */
DMALPEND (pBuf, 0, loop0Start); /* DMALPEND */
}
if (rest > 0)
{
/* switch to 1 byte mode if transfer size not align with burst size */
ccr = (pChanParam->endianSwapSize |
CCR_DST_CACHE_CTRL |
CCR_SRC_CACHE_CTRL |
CCR_DST_PROT_CTRL |
CCR_SRC_PROT_CTRL |
pChanParam->dstInc |
pChanParam->srcInc |
CCR_DST_BURST_LEN |
CCR_SRC_BURST_LEN |
(CCR_BURST_SIZE_1 << 15) |
(CCR_BURST_SIZE_1 << 1));
DMAMOV (pBuf, CCR, ccr); /* DMAMOV CCR ccr */
DMALP (pBuf, 0, rest); /* DMALP loop0 */
loop0Start = (UINT32)pBuf;
if (pChanParam->tansferType != MEM_TO_MEM)
{
DMAWFP (pBuf, pChanParam->peripheral);
}
DMALD (pBuf); /* DMALD */
DMARMB (pBuf); /* DMARMB */
DMAST (pBuf); /* DMAST */
DMAWMB (pBuf); /* DMAWMB */
DMALPEND (pBuf, 0, loop0Start); /* DMALPEND */
}
DMASEV (pBuf, chan); /* DMASEV */
DMAEND (pBuf); /* DMAEND */
return OK;
}