Hi everybody,
I'm currently working with the TCI6487. But I have got a problem when using EDMA3 copys WCDMA data from AIF data buffer to L2M.
The problem is that every 8th chip is in the wrong location, as follows:
Data in DSP memory:
[chip0] [chip1] [chip2] [chip3] [chip4] [chip5] [chip6] [chip7]
[chip8].. [chip15]
[chip16] ... [chip23]
[chip24] ... [chip31]
[chip32] ... [chip39]
With the problem, the [chip7] is moving to the [chip39], [chip15] is appeared at [chip47] ...
The testing result of self adding stream as follows:
When this problem happened:
28443 28444 28445 28446 28447 28448 28449 28418 --
28451 28452 28453 28454 28455 28456 28457 28426 |
28459 28460 28461 28462 28463 28464 28465 28434 | Data wrong here
28467 28468 28469 28470 28471 28472 28473 28442 |
28475 28476 28477 28478 28479 28480 28481 28450 <-
28483 28484 28485 28486 28487 28488 28489 28458
28491 28492 28493 28494 28495 28496 28497 28466 --
28499 28500 28501 28502 28503 28504 28505 28474 |
28507 28508 28509 28510 28511 28512 28513 28482 | Data wrong here
28515 28516 28517 28518 28519 28520 28521 28490 |
28523 28524 28525 28526 28527 28528 28529 28498 <-
28531 28532 28533 28534 28535 28536 28537 28506
The right condition:
28443 28444 28445 28446 28447 28448 28449 28450
28451 28452 28453 28454 28455 28456 28457 28458
28459 28460 28461 28462 28463 28464 28465 28466
28467 28468 28469 28470 28471 28472 28473 28474
28475 28476 28477 28478 28479 28480 28481 28482
28483 28484 28485 28486 28487 28488 28489 28490
28491 28492 28493 28494 28495 28496 28497 28498
28499 28500 28501 28502 28503 28504 28505 28506
28507 28508 28509 28510 28511 28512 28513 28514
28515 28516 28517 28518 28519 28520 28521 28522
28523 28524 28525 28526 28527 28528 28529 28530
28531 28532 28533 28534 28535 28536 28537 28538
The configuration of EDMA3:
Working on AB-Mode
ACNT = 16
BCNT = 8
CNT = 2560/8 = 320
SrcBidx = 16
DstBidx = 2560 * 4
SrcCidx = 4 * 8 * 16
DstCidx = 16
The Option configuration see the annex(aif_edma.c ).
Data in AIF data buf & L2M :
There are four streams in the aif data buf, and every stream has two samples.
/*
Configure EDMA for CS data for an AIF link specified by linkIndex
EDMA for CS data transfer should be triggered by FSync events and
auto-reloaded based on ping-pong mechnism
every link need two working channels for inbound and outbound CS antenna data
//////firstCsEDMAChannel for outbound CS antenna data
//////firstCsEDMAChannel+1 for inbound CS antenna data
every working channel need two reload PaRAM for ping-pong operation
//////firstReloadPaRAM for outbound ping reload for CS antenna data
//////firstReloadPaRAM+1 for outbound pong reload for CS antenna data
//////firstReloadPaRAM+2 for inbound ping reload for CS antenna data
//////firstReloadPaRAM+3 for inbound pong reload for CS antenna data
if CPRI control word transfer is enabled, the CS data EDMA will chain to CPRI control EDMA
firstCpriControlEDMAChannel is the outbound CPRI control channel
firstCpriControlEDMAChannel+1 is the inbound CPRI control channel
*/
void ConfigAifCsEdmaChannel(Uint32 linkIndex, Uint32 firstCsEDMAChannel,
Uint32 firstCpriControlEDMAChannel, Uint32 firstReloadPaRAM)
{
Uint32 uiPaRAMBaseAddr= (Uint32)Edma3CcRegs->PARAMSET;
CSL_Edma3ParamSetup myParamSetup;
Uint32 outboundEDMAChannel= firstCsEDMAChannel;
Uint32 inboundEDMAChannel= firstCsEDMAChannel+1;
/*----inbound EDMA configuration AIF -> DSP ----*/
//Configure option
if (CSL_AIF_CPRI_CTRL_WORD_READ_FROM_RAM==cpriCtrlWordMode&&
CSL_AIF_LINK_PROTOCOL_CPRI==aifProtocol)
{
//ZTEsec using this option ---liwen
myParamSetup.option= CSL_EDMA3_OPT_MAKE(
CSL_EDMA3_ITCCH_DIS, /*Disable intermediate chaining to trigger CPRI control channel*/
CSL_EDMA3_TCCH_DIS, /*Disable final chaining to trigger CPRI control channel*/
CSL_EDMA3_ITCINT_DIS,
CSL_EDMA3_TCINT_EN, /*enable interrupt*/
firstCpriControlEDMAChannel+1, /*set TCC= CPRI control channel for chaining*/
CSL_EDMA3_TCC_NORMAL,
CSL_EDMA3_FIFOWIDTH_NONE,
CSL_EDMA3_STATIC_DIS,
CSL_EDMA3_SYNC_AB,
CSL_EDMA3_ADDRMODE_INCR,
CSL_EDMA3_ADDRMODE_INCR);
}
else
{
myParamSetup.option= CSL_EDMA3_OPT_MAKE(
CSL_EDMA3_ITCCH_DIS,
CSL_EDMA3_TCCH_DIS,
CSL_EDMA3_ITCINT_DIS,
CSL_EDMA3_TCINT_EN, /*enable interrupt*/
inboundEDMAChannel, /*set TCC= own channel number*/
CSL_EDMA3_TCC_NORMAL,
CSL_EDMA3_FIFOWIDTH_NONE,
CSL_EDMA3_STATIC_DIS,
CSL_EDMA3_SYNC_AB,
CSL_EDMA3_ADDRMODE_INCR,
CSL_EDMA3_ADDRMODE_INCR);
}
/*calculate the address in AIF RAM for a link, the AIF RAM is orgonized as following
0xA000_0000 �C 0xA07f_FFFF R/W Inbound Circuit Switched RAM Link 0-1
0xA080_0000 �C 0xA0FF_FFFF R/W Inbound Circuit Switched RAM Link 2-3
0xA100_0000 �C 0xA17F_FFFF R/W Inbound Circuit Switched RAM Link 4-5
0xA180_0000 �C 0xA1FF_FFFF �C Reserved
0xA200_0000 �C 0xA27F_FFFF R/W Outbound Circuit Switched RAM Link 0-1
0xA280_0000 �C 0xA2FF_FFFF R/W Outbound Circuit Switched RAM Link 2-3
0xA300_0000 �C 0xA37F_FFFF R/W Outbound Circuit Switched RAM Link 4-5
*/
myParamSetup.srcAddr= CSL_AIF_0_DATA+
linkIndex*AIF_CS_DATA_BLOCK_SIZE;
//ACNT=16 for 4 chips worth of data, BCNT= (burstchips(equal to 8)/4) * (stream numbers) = 8/4 * 4 = 8
myParamSetup.aCntbCnt= CSL_EDMA3_CNT_MAKE (16,
8);//aifConfig[linkIndex].inBurstSizeInChips/4*aifConfig[linkIndex].streamNumber);
myParamSetup.dstAddr=
GLOBAL_ADDR(antennaAxcData[0].InboundAntennaPingS0);
/*
for DL data type, BINDX should jump to the next stream
for UL_RSA data type, BINDX should jump to the next sample, and then next stream, sample 0
store in the first half of the buffer, second sample is stored in the second half of the buffer
*/
if (CSL_AIF_LINK_DATA_TYPE_DL==aifConfig[linkIndex].inboundDataType)
//Dest BINDX= ANT_BUF_SIZE_IN_CHIPS*4 jump to next stream
myParamSetup.srcDstBidx= CSL_EDMA3_BIDX_MAKE(16, ANT_BUF_SIZE_IN_CHIPS*4);
else
//Dest BINDX= ANT_BUF_SIZE_IN_CHIPS*2 jump to next sample
myParamSetup.srcDstBidx= CSL_EDMA3_BIDX_MAKE(16, (ANT_BUF_SIZE_IN_CHIPS*4));
//Link working PaRAM -> pong PaRAM
myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(
uiPaRAMBaseAddr+((firstReloadPaRAM+3)<<5),
aifConfig[linkIndex].inBurstSizeInChips/4 * 4);//aifConfig[linkIndex].streamNumber);
//CINDX should jump to next burst
myParamSetup.srcDstCidx= CSL_EDMA3_CIDX_MAKE(4* aifConfig[linkIndex].inBurstSizeInChips* 16, 16);
//CCNT= number of burst
myParamSetup.cCnt= ANT_BUF_SIZE_IN_CHIPS/aifConfig[linkIndex].inBurstSizeInChips;
//copy the PaRAM configuration structure to the real PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, inboundEDMAChannel);
//configure inbound reload ping PaRAM, same configuration as working PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, firstReloadPaRAM+2);
//configure inbound reload pong PaRAM
myParamSetup.dstAddr= GLOBAL_ADDR(antennaAxcData[0].InboundAntennaPongS0);
//Link pong PaRAM -> ping PaRAM
myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(
uiPaRAMBaseAddr+((firstReloadPaRAM+2)<<5),
aifConfig[linkIndex].inBurstSizeInChips/4 * 4);//aifConfig[linkIndex].streamNumber);
myParamSetup.option= CSL_EDMA3_OPT_MAKE(
CSL_EDMA3_ITCCH_DIS, /*Disable intermediate chaining to trigger CPRI control channel*/
CSL_EDMA3_TCCH_DIS, /*Disable final chaining to trigger CPRI control channel*/
CSL_EDMA3_ITCINT_DIS,
CSL_EDMA3_TCINT_EN, /*enable interrupt*/
firstCpriControlEDMAChannel+2, /*set TCC= CPRI control channel for chaining*/
CSL_EDMA3_TCC_NORMAL,
CSL_EDMA3_FIFOWIDTH_NONE,
CSL_EDMA3_STATIC_DIS,
CSL_EDMA3_SYNC_AB,
CSL_EDMA3_ADDRMODE_INCR,
CSL_EDMA3_ADDRMODE_INCR);
//copy the PaRAM configuration structure to the real PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, firstReloadPaRAM+3);
//Enable channel event
if (inboundEDMAChannel<32) //Edma channel is 0~31
Edma3CcRegs->EESR= (1<<inboundEDMAChannel);
else //Edma channel is 32~63
Edma3CcRegs->EESRH= (1<<(inboundEDMAChannel-32));
//Enable channel interrupt
if (CSL_AIF_CPRI_CTRL_WORD_READ_FROM_RAM==cpriCtrlWordMode&&
CSL_AIF_LINK_PROTOCOL_CPRI==aifProtocol)
{ /*TCC= CPRI control channel for chaining*/
if ((firstCpriControlEDMAChannel+1)<32)
{ //Edma channel is 0~31
Edma3CcRegs->IESR= (1<<(firstCpriControlEDMAChannel+1));
Edma3CcRegs->IESR= (1<<(firstCpriControlEDMAChannel+2));
}
else //Edma channel is 32~63
{
Edma3CcRegs->IESRH= (1<<((firstCpriControlEDMAChannel+1)-32));
Edma3CcRegs->IESRH= (1<<((firstCpriControlEDMAChannel+2)-32));
}
}
else
{
if (inboundEDMAChannel<32) //Edma channel is 0~31
Edma3CcRegs->IESR= (1<<inboundEDMAChannel);
else //Edma channel is 32~63
Edma3CcRegs->IESRH= (1<<(inboundEDMAChannel-32));
}
}
/*
Configure EDMA for CPRI control words for an AIF link specified by "linkIndex"
EDMA for CPRI control word transfer should be triggered/chained
by the completion event of the EDMA for CS data transfer
every link need two working channels for inbound and outbound CPRI control word
fisrtCpriControlEDMAChannel for outbound CPRI control word
fisrtCpriControlEDMAChannel+1 for inbound CPRI control word
every working channel need 4 reload PaRAM for ping-pong operation for minimum 1x rate
firstReloadPaRAM+0 for outbound ping reload for CPRI control word
firstReloadPaRAM+1 for outbound pong reload for CPRI control word
firstReloadPaRAM+2 for outbound ping reload for CPRI control word
firstReloadPaRAM+3 for outbound pong reload for CPRI control word
firstReloadPaRAM+4 for inbound ping reload for CPRI control word
firstReloadPaRAM+5 for inbound pong reload for CPRI control word
firstReloadPaRAM+6 for inbound ping reload for CPRI control word
firstReloadPaRAM+7 for inbound pong reload for CPRI control word
*/
void ConfigAifCpriControlEdmaChannel(Uint32 linkIndex, Uint32 firstCsEDMAChannel,
Uint32 firstCpriControlEDMAChannel, Uint32 firstReloadPaRAM)
{
Uint32 uiPaRAMBaseAddr= (Uint32)Edma3CcRegs->PARAMSET;
Uint32 outboundEdmaSyncMode, inboundEdmaSyncMode;
Uint16 aCnt, bCnt;
CSL_Edma3ParamSetup myParamSetup;
Uint32 outboundCpriControlEDMAChannel= firstCpriControlEDMAChannel;
Uint32 inboundCpriControlEDMAChannel= firstCpriControlEDMAChannel+1;
/*----outbound EDMA configuration DSP -> AIF ----*/
/*since ACNT<=16 for CPRI control word transfer, if burst=8chips and linkrate=4,
the minimal data unit size is 32 byte, so SYNC_AB should be used under this case*/
if (8==aifConfig[linkIndex].outBurstSizeInChips&&4==aifConfig[linkIndex].linkRate)
outboundEdmaSyncMode= CSL_EDMA3_SYNC_AB;
else
outboundEdmaSyncMode= CSL_EDMA3_SYNC_A;
//Configure option
myParamSetup.option= CSL_EDMA3_OPT_MAKE(
CSL_EDMA3_ITCCH_DIS,
CSL_EDMA3_TCCH_DIS,
CSL_EDMA3_ITCINT_DIS,
CSL_EDMA3_TCINT_EN, /*enable interrupt*/
/*normally, TCC = own channel number, but becasue the TCC number of CS channel= CPRI control channel number
for chaining, so, here set the TCC of the CPRI control channel = CS channel number*/
firstCsEDMAChannel,
CSL_EDMA3_TCC_NORMAL,
CSL_EDMA3_FIFOWIDTH_NONE,
CSL_EDMA3_STATIC_DIS,
outboundEdmaSyncMode,
CSL_EDMA3_ADDRMODE_INCR,
CSL_EDMA3_ADDRMODE_INCR);
myParamSetup.srcAddr= GLOBAL_ADDR(cpriControlBuffer[linkIndex].uiOutboundCPRIControlPingBuf);
if (8==aifConfig[linkIndex].outBurstSizeInChips&&4==aifConfig[linkIndex].linkRate)
{
/*ACNT=16, BCNT=2, because minimal data unit is 32 bytes for burst=8chips and linkrate=4,
SYNC_AB should be used for this case*/
aCnt= 16;
bCnt= 2;
myParamSetup.aCntbCnt= CSL_EDMA3_CNT_MAKE (16, 2);
}
else
{
/*SYNC_A should be used for this case, every trigger transfer control word for burst chips, so
ACNT=burst size * rate; ACNT*BCNT should be 16 bytes*/
aCnt= aifConfig[linkIndex].outBurstSizeInChips*aifConfig[linkIndex].linkRate;
bCnt= 16/aCnt;
}
myParamSetup.aCntbCnt= CSL_EDMA3_CNT_MAKE (aCnt, bCnt);
/*calculate the address in AIF control RAM for a link, the AIF control RAM is orgonized as following
0xA7000000 Outbound CPRI Control Word RAM for link0
0xA7000800 Outbound CPRI Control Word RAM for link1
0xA7001000 Outbound CPRI Control Word RAM for link2
0xA7001800 Outbound CPRI Control Word RAM for link3
0xA7002000 Outbound CPRI Control Word RAM for link4
0xA7002800 Outbound CPRI Control Word RAM for link5 */
myParamSetup.dstAddr= AIF_CPRI_CONTROL_OUT_RAM_ADDR+
linkIndex*AIF_CPRI_CONTROL_RAM_BLOCK_SIZE;
if (8==aifConfig[linkIndex].outBurstSizeInChips&&4==aifConfig[linkIndex].linkRate)
{
//source BINDX= ACNT= 16, because the memory is linearly accessed
//dst BINDX= 32, because the CPRI control RAM has only 16 valid byte in every 32 bytes space
myParamSetup.srcDstBidx= CSL_EDMA3_BIDX_MAKE(16, 32);
}
else
{
//source BINDX= ACNT, because the memory is linearly accessed
//dst BINDX= ACNT, because ACNT<=16 bytes
myParamSetup.srcDstBidx= CSL_EDMA3_BIDX_MAKE(aCnt, aCnt);
}
//Link working PaRAM -> pong PaRAM
myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(
uiPaRAMBaseAddr+((firstReloadPaRAM+1)<<5), bCnt);
if (8==aifConfig[linkIndex].outBurstSizeInChips&&4==aifConfig[linkIndex].linkRate)
{
//source CINDX= ACNT*BNCT=32, because SYNC_AB is used and the memory is linearly accessed
//dst CINDX= 64, because the CPRI control RAM has only 16 valid byte in every 32 bytes space
myParamSetup.srcDstCidx= CSL_EDMA3_CIDX_MAKE(32, 64);
}
else
{
//source CINDX= ACNT, because SYNC_A is used and the memory is linearly accessed
//dst CINDX= ACNT+16, because SYNC_A is used and need to skill 16 unused bytes
myParamSetup.srcDstCidx= CSL_EDMA3_CIDX_MAKE(aCnt, aCnt+16);
}
//ACNT*BCNT*CCNT= bytes for one hyper frame (256 chips * linkRate)
myParamSetup.cCnt= 256*aifConfig[linkIndex].linkRate/(aCnt*bCnt);
/*because of the 16 bytes re-order of the CPRI control word RAM,
outbound EDMA may need be advanceed to make sure 16 byte are ready in the RAM.
Here, make the first DMA transfer less data, thus the following EDMA will be advanceded.
This result in error data in first control hyper frame, which is neglectable */
if (aCnt<16)
myParamSetup.cCnt-=1; /*CCNT-1 to advance following EDMA for 16 bytes*/
//copy the PaRAM configuration structure to the real PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, outboundCpriControlEDMAChannel);
//ACNT*BCNT*CCNT= bytes for one hyper frame (256 chips * linkRate)
myParamSetup.cCnt= 256*aifConfig[linkIndex].linkRate/(aCnt*bCnt);
//configure outbound reload ping PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, firstReloadPaRAM);
//configure outbound reload PaRAM
//the next transfer souce is the pong buffer in the DSP memory
myParamSetup.srcAddr= GLOBAL_ADDR(cpriControlBuffer[linkIndex].uiOutboundCPRIControlPongBuf);
/*the next transfer dst is the next CPRI hyper frame buffer in AIF CPRI control RAM(2KB)
for 1x rate, the CPRI control RAM contains 4 hyper frame
for 2x rate, the CPRI control RAM contains 2 hyper frame
for 4x rate, the CPRI control RAM contains 1 hyper frame
*/
myParamSetup.dstAddr= AIF_CPRI_CONTROL_OUT_RAM_ADDR+
linkIndex*AIF_CPRI_CONTROL_RAM_BLOCK_SIZE+
((256*aifConfig[linkIndex].linkRate*2)&0x7FF);
//Link pong PaRAM -> ping PaRAM
myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(
uiPaRAMBaseAddr+((firstReloadPaRAM+2)<<5), bCnt);
//copy the PaRAM configuration structure to the real PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, firstReloadPaRAM+1);
//configure outbound reload PaRAM
//the next transfer souce is the ping buffer in the DSP memory
myParamSetup.srcAddr= GLOBAL_ADDR(cpriControlBuffer[linkIndex].uiOutboundCPRIControlPingBuf);
/*the next transfer dst is the next CPRI hyper frame buffer in AIF CPRI control RAM(2KB)*/
myParamSetup.dstAddr= AIF_CPRI_CONTROL_OUT_RAM_ADDR+
linkIndex*AIF_CPRI_CONTROL_RAM_BLOCK_SIZE+
((256*aifConfig[linkIndex].linkRate*2*2)&0x7FF);
//Link ping PaRAM -> pong PaRAM
myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(
uiPaRAMBaseAddr+((firstReloadPaRAM+3)<<5), bCnt);
//copy the PaRAM configuration structure to the real PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, firstReloadPaRAM+2);
//configure outbound reload PaRAM
//the next transfer souce is the pong buffer in the DSP memory
myParamSetup.srcAddr= GLOBAL_ADDR(cpriControlBuffer[linkIndex].uiOutboundCPRIControlPongBuf);
/*the next transfer dst is the next CPRI hyper frame buffer in AIF CPRI control RAM(2KB)*/
myParamSetup.dstAddr= AIF_CPRI_CONTROL_OUT_RAM_ADDR+
linkIndex*AIF_CPRI_CONTROL_RAM_BLOCK_SIZE+
((256*aifConfig[linkIndex].linkRate*2*3)&0x7FF);
//Link pong PaRAM -> ping PaRAM
myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(
uiPaRAMBaseAddr+((firstReloadPaRAM)<<5), bCnt);
//copy the PaRAM configuration structure to the real PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, firstReloadPaRAM+3);
//Enable channel event
if (outboundCpriControlEDMAChannel<32) //Edma channel is 0~31
Edma3CcRegs->EESR= (1<<outboundCpriControlEDMAChannel);
else //Edma channel is 32~63
Edma3CcRegs->EESRH= (1<<(outboundCpriControlEDMAChannel-32));
//Enable channel interrupt
/*TCC of the CPRI control channel = CS channel number*/
if (firstCsEDMAChannel<32) //Edma channel is 0~31
Edma3CcRegs->IESR= (1<<firstCsEDMAChannel);
else //Edma channel is 32~63
Edma3CcRegs->IESRH= (1<<(firstCsEDMAChannel-32));
/*----inbound EDMA configuration AIF -> DSP ----*/
/*since ACNT<=16 for CPRI control word transfer, if burst=8chips and linkrate=4,
the minimal data unit size is 32 byte, so SYNC_AB should be used under this case*/
if (8==aifConfig[linkIndex].inBurstSizeInChips&&4==aifConfig[linkIndex].linkRate)
inboundEdmaSyncMode= CSL_EDMA3_SYNC_AB;
else
inboundEdmaSyncMode= CSL_EDMA3_SYNC_A;
//Configure option
myParamSetup.option= CSL_EDMA3_OPT_MAKE(
CSL_EDMA3_ITCCH_DIS,
CSL_EDMA3_TCCH_DIS,
CSL_EDMA3_ITCINT_DIS,
CSL_EDMA3_TCINT_EN, /*enable interrupt*/
/*normally, TCC = own channel number, but becasue the TCC number of CS channel= CPRI control channel number for chaining,
so, here set the TCC of the CPRI control channel = CS channel number*/
firstCsEDMAChannel+1,
CSL_EDMA3_TCC_NORMAL,
CSL_EDMA3_FIFOWIDTH_NONE,
CSL_EDMA3_STATIC_DIS,
inboundEdmaSyncMode,
CSL_EDMA3_ADDRMODE_INCR,
CSL_EDMA3_ADDRMODE_INCR);
myParamSetup.srcAddr= AIF_CPRI_CONTROL_IN_RAM_ADDR+
linkIndex*AIF_CPRI_CONTROL_RAM_BLOCK_SIZE;
if (8==aifConfig[linkIndex].inBurstSizeInChips&&4==aifConfig[linkIndex].linkRate)
{
/*ACNT=16, BCNT=2, because minimal data unit is 32 bytes for burst=8chips and linkrate=4
SYNC_AB should be used for this case*/
aCnt= 16;
bCnt= 2;
myParamSetup.aCntbCnt= CSL_EDMA3_CNT_MAKE (16, 2);
}
else
{
/*SYNC_A should be used for this case, every trigger transfer control word for burst chips, so
ACNT=burst size * rate; ACNT*BCNT should be 16 bytes, so BCNT= 16/(burst size * rate)*/
aCnt= aifConfig[linkIndex].inBurstSizeInChips*aifConfig[linkIndex].linkRate;
bCnt= 16/aCnt;
}
myParamSetup.aCntbCnt= CSL_EDMA3_CNT_MAKE (aCnt, bCnt);
/*calculate the address in CPRI control RAM for a link, the CPRI control RAM is orgonized as following
0xA6000000 Inbound CPRI Control Word RAM for link0
0xA6000800 Inbound CPRI Control Word RAM for link1
0xA6001000 Inbound CPRI Control Word RAM for link2
0xA6001800 Inbound CPRI Control Word RAM for link3
0xA6002000 Inbound CPRI Control Word RAM for link4
0xA6002800 Inbound CPRI Control Word RAM for link5
*/
myParamSetup.dstAddr= GLOBAL_ADDR(cpriControlBuffer[linkIndex].uiInboundCPRIControlPingBuf);
if (8==aifConfig[linkIndex].inBurstSizeInChips&&4==aifConfig[linkIndex].linkRate)
{
//dst BINDX= ACNT= 16, because the memory is linearly accessed
//source BINDX= 32, because the CPRI control RAM has only 16 valid byte in every 32 bytes space
myParamSetup.srcDstBidx= CSL_EDMA3_BIDX_MAKE(32, 16);
}
else
{
//dst BINDX= ACNT, because the memory is linearly accessed
//source BINDX= ACNT, because ACNT<=16 bytes
myParamSetup.srcDstBidx= CSL_EDMA3_BIDX_MAKE(aCnt, aCnt);
}
//Link working PaRAM -> pong PaRAM
myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(
uiPaRAMBaseAddr+((firstReloadPaRAM+5)<<5), bCnt);
if (8==aifConfig[linkIndex].inBurstSizeInChips&&4==aifConfig[linkIndex].linkRate)
{
//dst CINDX= ACNT*BNCT=32, because SYNC_AB is used and the memory is linearly accessed
//source CINDX= 64, because the CPRI control RAM has only 16 valid byte in every 32 bytes space
myParamSetup.srcDstCidx= CSL_EDMA3_CIDX_MAKE(64, 32);
}
else
{
//dst CINDX= ACNT, because SYNC_A is used and the memory is linearly accessed
//source CINDX= ACNT+16, because SYNC_A is used and need to skill 16 unused bytes
myParamSetup.srcDstCidx= CSL_EDMA3_CIDX_MAKE(aCnt+16, aCnt);
}
//ACNT*BCNT*CCNT= bytes for one hyper frame (256 chips * linkRate)
myParamSetup.cCnt= 256*aifConfig[linkIndex].linkRate/(aCnt*bCnt);
/*because of the 16 bytes re-order of the CPRI control word RAM,
inbound EDMA may need be delayed to make sure 16 byte are ready in the RAM.
Here, make the first DMA transfer more dummy data, thus the following EDMA
will be delayed. This result in dummy data to be written into the memory space after
the CPRI control ping buffer, for this test, the memory space after ping buffer is pong
buffer, so it is OK.*/
if (aCnt<16)
myParamSetup.cCnt+=1; /*CCNT+1 to delay the following EDMA for 16 bytes*/
//copy the PaRAM configuration structure to the real PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, inboundCpriControlEDMAChannel);
//ACNT*BCNT*CCNT= bytes for one hyper frame (256 chips * linkRate)
myParamSetup.cCnt= 256*aifConfig[linkIndex].linkRate/(aCnt*bCnt);
//configure inbound reload ping PaRAM, same configuration as working PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, firstReloadPaRAM+4);
//configure inbound reload PaRAM
//the next transfer souce is the pong buffer in the DSP memory
myParamSetup.dstAddr= GLOBAL_ADDR(cpriControlBuffer[linkIndex].uiInboundCPRIControlPongBuf);
/*the next transfer dst is the next CPRI hyper frame buffer in AIF CPRI control RAM(2KB)
for 1x rate, the CPRI control RAM contains 4 hyper frame
for 2x rate, the CPRI control RAM contains 2 hyper frame
for 4x rate, the CPRI control RAM contains 1 hyper frame
*/
myParamSetup.srcAddr= AIF_CPRI_CONTROL_IN_RAM_ADDR+
linkIndex*AIF_CPRI_CONTROL_RAM_BLOCK_SIZE+
((256*aifConfig[linkIndex].linkRate*2)&0x7FF);
//Link pong PaRAM -> ping PaRAM
myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(
uiPaRAMBaseAddr+((firstReloadPaRAM+6)<<5), bCnt);
//copy the PaRAM configuration structure to the real PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, firstReloadPaRAM+5);
//configure inbound reload PaRAM
//the next transfer souce is the ping buffer in the DSP memory
myParamSetup.dstAddr= GLOBAL_ADDR(cpriControlBuffer[linkIndex].uiInboundCPRIControlPingBuf);
/*the next transfer dst is the next CPRI hyper frame buffer in AIF CPRI control RAM(2KB)*/
myParamSetup.srcAddr= AIF_CPRI_CONTROL_IN_RAM_ADDR+
linkIndex*AIF_CPRI_CONTROL_RAM_BLOCK_SIZE+
((256*aifConfig[linkIndex].linkRate*2*2)&0x7FF);
//Link ping PaRAM -> pong PaRAM
myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(
uiPaRAMBaseAddr+((firstReloadPaRAM+7)<<5), bCnt);
//copy the PaRAM configuration structure to the real PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, firstReloadPaRAM+6);
//configure inbound reload PaRAM
//the next transfer souce is the pong buffer in the DSP memory
myParamSetup.dstAddr= GLOBAL_ADDR(cpriControlBuffer[linkIndex].uiInboundCPRIControlPongBuf);
/*the next transfer dst is the next CPRI hyper frame buffer in AIF CPRI control RAM(2KB)*/
myParamSetup.srcAddr= AIF_CPRI_CONTROL_IN_RAM_ADDR+
linkIndex*AIF_CPRI_CONTROL_RAM_BLOCK_SIZE+
((256*aifConfig[linkIndex].linkRate*2*3)&0x7FF);
//Link pong PaRAM -> ping PaRAM
myParamSetup.linkBcntrld= CSL_EDMA3_LINKBCNTRLD_MAKE(
uiPaRAMBaseAddr+((firstReloadPaRAM+4)<<5), bCnt);
//copy the PaRAM configuration structure to the real PaRAM
edmaParamConfig((Uint32 *)&myParamSetup, firstReloadPaRAM+7);
//Enable channel event
if (inboundCpriControlEDMAChannel<32) //Edma channel is 0~31
Edma3CcRegs->EESR= (1<<inboundCpriControlEDMAChannel);
else //Edma channel is 32~63
Edma3CcRegs->EESRH= (1<<(inboundCpriControlEDMAChannel-32));
//Enable channel interrupt
/*TCC of the CPRI control channel = CS channel number*/
if ((firstCsEDMAChannel+1)<32) //Edma channel is 0~31
Edma3CcRegs->IESR= (1<<(firstCsEDMAChannel+1));
else //Edma channel is 32~63
Edma3CcRegs->IESRH= (1<<((firstCsEDMAChannel+1)-32));
}
/*Reset, clear all PaRAM and registers*/
void ResetEDMA(void)
{
Uint32 i;
Uint32 * uiPaRAMBaseAddr= (Uint32 *)Edma3CcRegs->PARAMSET;
//Clear 64 PaRAM entries, every entry has 8 word
for (i=0; i<64*8; i++)
*uiPaRAMBaseAddr++= 0;
//Clear interrupts and events
Edma3CcRegs->ECR= 0xFFFFFFFF;
Edma3CcRegs->ECRH= 0xFFFFFFFF;
Edma3CcRegs->EECR= 0xFFFFFFFF;
Edma3CcRegs->EECRH= 0xFFFFFFFF;
Edma3CcRegs->EMCR = 0xffffffff;
Edma3CcRegs->EMCRH = 0xffffffff;
Edma3CcRegs->SECR = 0xffffffff;
Edma3CcRegs->SECRH = 0xffffffff;
Edma3CcRegs->ICR= 0xFFFFFFFF;
Edma3CcRegs->ICRH= 0xFFFFFFFF;
Edma3CcRegs->IECR= 0xFFFFFFFF;
Edma3CcRegs->IECRH= 0xFFFFFFFF;
//Clear EDMA interrupt counter
for (i=0; i<64; i++)
EdmaIntCount[i]=0;
}
//Set mask of a EDMA region for "channelNumber" channels from "firstChannel"
void maskRegion(CSL_Edma3CmdDrae* regionMask, Uint32 firstChannel, Uint32 channelNumber)
{
if (firstChannel+ channelNumber<32)
{
regionMask->drae = _set(0, firstChannel,
firstChannel+ channelNumber-1) ;
regionMask->draeh = 0;
}
else if (firstChannel>=32)
{
regionMask->drae = 0 ;
regionMask->draeh = _set(0, firstChannel-32,
firstChannel+ channelNumber-32-1) ;
}
else
{
regionMask->drae = _set(0, firstChannel, 31) ;
regionMask->draeh = _set(0, 0, firstChannel+ channelNumber-32-1) ;
}
}
/* Setup the EDMA3 module */
void ConfigAifEdma(AifConfig * aifConfig)
{
int i;
CSL_Status edmaStat;
CSL_Edma3CmdDrae regionMask;
/*Reset, clear all PaRAM and registers*/
//ResetEDMA();
// Module Initialization
CSL_edma3Init(&Edmacontext);
// Module Level Open
hEdmaModule = CSL_edma3Open(&edmaObj,CSL_EDMA3,NULL,&edmaStat);
/* Module Setup */
//balance the load between EDMA TC3 ,TC4 and TC5
for (i= FIRST_EDMA_CHANNEL_FOR_AIF_CS_DATA; i< FIRST_EDMA_CHANNEL_FOR_AIF_CS_DATA+
EDMA_CHANNEL_USED_FOR_AIF_CS_DATA; i++)
dmahwSetup[i].que=(CSL_Edma3Que)(CSL_EDMA3_QUE_0+ i&1); //use TC3/TC4 for all CS AIF transfer
if (CSL_AIF_LINK_PROTOCOL_OBSAI==aifProtocol) //configure EDMA for OBSAI PS data
{
for (i= FIRST_EDMA_CHANNEL_FOR_AIF_PS_OUT_DATA;
i< FIRST_EDMA_CHANNEL_FOR_AIF_PS_OUT_DATA+ CSL_AIF_MAX_NUM_LINKS; i++)
dmahwSetup[i].que= CSL_EDMA3_QUE_5; //use TC5 for all PS AIF transfer
for (i= FIRST_EDMA_CHANNEL_FOR_AIF_PS_IN_DATA;
i< FIRST_EDMA_CHANNEL_FOR_AIF_PS_IN_DATA+ EDMA_CHANNEL_USED_FOR_AIF_PS_IN_DATA; i++)
dmahwSetup[i].que= CSL_EDMA3_QUE_5; //use TC5 for all PS AIF transfer
}
else if (CSL_AIF_CPRI_CTRL_WORD_READ_FROM_RAM==cpriCtrlWordMode)
{ //configure EDMA for CPRI control words
for (i= FIRST_EDMA_CHANNEL_FOR_CPRI_CONTROL;
i< FIRST_EDMA_CHANNEL_FOR_CPRI_CONTROL+ EDMA_CHANNEL_USED_FOR_CPRI_CONTROL; i++)
dmahwSetup[i].que= CSL_EDMA3_QUE_2; //use TC5 for CPRI control words AIF transfer
}
hwSetup.dmaChaSetup = &dmahwSetup[0];
hwSetup.qdmaChaSetup = &qdmahwSetup[0];
CSL_edma3HwSetup(hEdmaModule, &hwSetup);
/*normally, TCC = own channel number, but when CPRI control word transfer is enbaled,
the TCC of CS channel= CPRI control channel number for chaining,
so, this test sets the TCC of the CPRI control channel = CS channel number*/
if (CSL_AIF_LINK_PROTOCOL_CPRI==aifProtocol&&
CSL_AIF_CPRI_CTRL_WORD_READ_FROM_RAM==cpriCtrlWordMode)
{
firstCsTccNumber= FIRST_EDMA_CHANNEL_FOR_CPRI_CONTROL;
firstCpriControlTccNumber= FIRST_EDMA_CHANNEL_FOR_AIF_CS_DATA;
}
else
{
firstCsTccNumber= FIRST_EDMA_CHANNEL_FOR_AIF_CS_DATA;
firstCpriControlTccNumber= FIRST_EDMA_CHANNEL_FOR_CPRI_CONTROL;
}
/* Setup seperated EDMA interrupt region for AIF CS transfer,
thus, isolate the EDMA ISR for CS and PS transfer*/
regionMask.region = CSL_EDMA3_REGION_0 ;
maskRegion(®ionMask, firstCsTccNumber,
EDMA_CHANNEL_USED_FOR_AIF_CS_DATA);
CSL_edma3HwControl(hEdmaModule,CSL_EDMA3_CMD_DMAREGION_ENABLE, ®ionMask);
if (CSL_AIF_LINK_PROTOCOL_OBSAI==aifProtocol) //configure EDMA for OBSAI PS data
{
/* Setup seperated EDMA interrupt region for AIF PS inbound transfer,
thus, isolate the EDMA ISR for CS and PS transfer*/
regionMask.region = CSL_EDMA3_REGION_1 ;
maskRegion(®ionMask, FIRST_EDMA_CHANNEL_FOR_AIF_PS_IN_DATA,
EDMA_CHANNEL_USED_FOR_AIF_PS_IN_DATA);
CSL_edma3HwControl(hEdmaModule,CSL_EDMA3_CMD_DMAREGION_ENABLE, ®ionMask);
}
else if (CSL_AIF_CPRI_CTRL_WORD_READ_FROM_RAM==cpriCtrlWordMode)
{
/* Setup seperated EDMA interrupt region for CPRI control words transfer,
thus, isolate the EDMA ISR for CS,PS and CPRI control words transfer*/
regionMask.region = CSL_EDMA3_REGION_1 ;
maskRegion(®ionMask, firstCpriControlTccNumber,
EDMA_CHANNEL_USED_FOR_CPRI_CONTROL);
CSL_edma3HwControl(hEdmaModule,CSL_EDMA3_CMD_DMAREGION_ENABLE, ®ionMask);
}
//Configure EDMA channel for link 0~5
for (i=0; i<6; i++)
{
if (0==aifConfig[i].linkEnable)
continue;
//CS data transfer for every link need two working channel and 4 reloading PaRAM
ConfigAifCsEdmaChannel(i, FIRST_EDMA_CHANNEL_FOR_AIF_CS_DATA+i*2,
FIRST_EDMA_CHANNEL_FOR_CPRI_CONTROL+i*2 ,FIRST_RELOAD_PaRAM_FOR_AIF+i*4);
if (CSL_AIF_LINK_PROTOCOL_OBSAI==aifProtocol)
{
/*Removed by liwen 2012-05-17*/
#if 0
//PS outbound EDMA configuration for every link
ConfigAifPsOutboundEdmaChannel(i, FIRST_EDMA_CHANNEL_FOR_AIF_PS_OUT_DATA+i);
#endif
}
else if (CSL_AIF_CPRI_CTRL_WORD_READ_FROM_RAM==cpriCtrlWordMode)
{
//CPRI control word transfer for every link need two working channel and maximum 8 reloading PaRAM
ConfigAifCpriControlEdmaChannel(i, FIRST_EDMA_CHANNEL_FOR_AIF_CS_DATA+i*2,
FIRST_EDMA_CHANNEL_FOR_CPRI_CONTROL+i*2 ,FIRST_RELOAD_PaRAM_FOR_AIF+24+i*8);
}
}
if (CSL_AIF_LINK_PROTOCOL_OBSAI==aifProtocol)
{
//Configure EDMA channel for inbound PS (packet-switched) data FIFO 0~2
for (i=0; i<3; i++)
{
/*Removed by liwen 2012-05-17*/
#if 0
//PS inbound EDMA configuration for every FIFO, need one working channel and two reloading PaRAM
ConfigAifPsInboundEdmaChannel(i, FIRST_EDMA_CHANNEL_FOR_AIF_PS_IN_DATA+i,
FIRST_RELOAD_PaRAM_FOR_AIF+24+i*2);
#endif
}
}
}
