📄 c6x1x_edma_mcasp.c
字号:
/* Open theEDMA Channel */
#if (CHIP_DM642)
edmaChanEvent = eventIds[port->devId][chan->mode];
#else
edmaChanEvent = EDMA_map(eventIds[port->devId][chan->mode],
params->edmaChan);
#endif
chan->xferPram = EDMA_open(edmaChanEvent, EDMA_OPEN_RESET);
if (chan->xferPram == EDMA_HINV) {
chanCleanUp(chan, FREETABLEEX);
return (IOM_EALLOC);
}
/* Program the data EDMA job with the TCC */
EDMA_FSETA(¶ms->edmaCfgPtr->opt, OPT, TCC, chan->tcc);
#if ENABLELOOPINTR
EDMA_intHook(loopTcc, &isrLoop);
EDMA_FSETA(&loopEdmaCfg.opt, OPT, TCINT, EDMA_OPT_TCINT_YES);
EDMA_FSETA(&loopEdmaCfg.opt, OPT, TCC, loopTcc);
#endif
/* Program the link PaRAMs with the config struct */
for (i=0; i < MAXLINKCNT; i++) {
EDMA_config(chan->pramTbl[i], params->edmaCfgPtr);
}
/* Program the Loop EDMA job with its config struct */
EDMA_config(chan->loophEdma, &loopEdmaCfg);
/*
* Link the Loop EDMA job to itself to make it run
* continuously when there is no data to transmit.
*/
EDMA_link(chan->loophEdma, chan->loophEdma);
/* Configure the EDMA channel to start with the Loop EDMA job */
EDMA_config(chan->xferPram, &loopEdmaCfg);
EDMA_link(chan->xferPram, chan->loophEdma);
/* Transfer complete is edge triggered, so clear before enabling */
EDMA_intClear(chan->tcc);
EDMA_intEnable(chan->tcc);
#if ENABLELOOPINTR
EDMA_intClear(loopTcc);
EDMA_intEnable(loopTcc);
#endif
/* Enable the EDMA interrupt */
IRQ_enable(IRQ_EVT_EDMAINT);
EDMA_enableChannel(chan->xferPram);
/* Start the McASP */
if (chan->mode == INPUT) {
old = ATM_setu(&(port->chanCreated), TRUE);
/*
* clock generator is divided from high frequency clock, so start high
* freq clock generator first
*/
if (port->enableHclkg == C6X1X_EDMA_MCASP_RCV) {
MCASP_enableHclk(port->hMcasp, MCASP_RCV);
while(!MCASP_FGETH(port->hMcasp, GBLCTL, RHCLKRST));
}
else if ((port->enableHclkg == C6X1X_EDMA_MCASP_RCVXMT) && (old)) {
MCASP_enableHclk(port->hMcasp, MCASP_RCVXMT);
while(!(MCASP_FGETH(port->hMcasp, GBLCTL, RHCLKRST) &
MCASP_FGETH(port->hMcasp, GBLCTL, XHCLKRST)));
}
if (port->enableClkg == C6X1X_EDMA_MCASP_RCV) {
MCASP_enableClk(port->hMcasp, MCASP_RCV);
while(!MCASP_FGETH(port->hMcasp, GBLCTL, RCLKRST));
}
else if ((port->enableClkg == C6X1X_EDMA_MCASP_RCVXMT) && (old)) {
MCASP_enableClk(port->hMcasp, MCASP_RCVXMT);
while(!( MCASP_FGETH(port->hMcasp, GBLCTL, RCLKRST) &
MCASP_FGETH(port->hMcasp, GBLCTL, XCLKRST)));
}
#if STARTSERIALIZERSYNC
if (old) {
MCASP_enableSers(port->hMcasp, MCASP_RCVXMT);
while (!(MCASP_FGETH(port->hMcasp, GBLCTL, RSRCLR) &
MCASP_FGETH(port->hMcasp, GBLCTL, XSRCLR)));
while (MCASP_xdata(port->hMcasp));
MCASP_enableSm(port->hMcasp, MCASP_RCVXMT);
while (!(MCASP_FGETH(port->hMcasp, GBLCTL, RSMRST) &
MCASP_FGETH(port->hMcasp, GBLCTL, XSMRST)));
}
#else
MCASP_enableSers(port->hMcasp, MCASP_RCV);
while (!MCASP_FGETH(port->hMcasp, GBLCTL, RSRCLR));
MCASP_enableSm(port->hMcasp, MCASP_RCV);
while (!MCASP_FGETH(port->hMcasp, GBLCTL, RSMRST));
#endif
if (port->enableFsyncg == C6X1X_EDMA_MCASP_RCV) {
MCASP_enableFsync(port->hMcasp, MCASP_RCV);
while(!MCASP_FGETH(port->hMcasp, GBLCTL, RFRST));
}
else if ((port->enableFsyncg == C6X1X_EDMA_MCASP_RCVXMT) && (old)) {
MCASP_enableFsync(port->hMcasp, MCASP_RCVXMT);
while(!(MCASP_FGETH(port->hMcasp, GBLCTL, RFRST) &
MCASP_FGETH(port->hMcasp, GBLCTL, XFRST)) );
}
}
else {
old = ATM_setu(&(port->chanCreated), TRUE);
/*
* clock generator is divided from high frequency clock, so start high
* freq clock generator first
*/
if (port->enableHclkg == C6X1X_EDMA_MCASP_XMT) {
MCASP_enableHclk(port->hMcasp, MCASP_XMT);
while(!MCASP_FGETH(port->hMcasp, GBLCTL, XHCLKRST));
}
else if ((port->enableHclkg == C6X1X_EDMA_MCASP_RCVXMT) && (old)) {
MCASP_enableHclk(port->hMcasp, MCASP_RCVXMT);
while(!( MCASP_FGETH(port->hMcasp, GBLCTL, RHCLKRST) &
MCASP_FGETH(port->hMcasp, GBLCTL, XHCLKRST)));
}
if (port->enableClkg == C6X1X_EDMA_MCASP_XMT) {
MCASP_enableClk(port->hMcasp, MCASP_XMT);
while(!MCASP_FGETH(port->hMcasp, GBLCTL, XCLKRST));
}
else if ((port->enableClkg == C6X1X_EDMA_MCASP_RCVXMT) && (old)) {
MCASP_enableClk(port->hMcasp, MCASP_RCVXMT);
while(!( MCASP_FGETH(port->hMcasp, GBLCTL, RCLKRST) &
MCASP_FGETH(port->hMcasp, GBLCTL, XCLKRST)));
}
#if STARTSERIALIZERSYNC
if (old) {
MCASP_enableSers(port->hMcasp, MCASP_RCVXMT);
while (!(MCASP_FGETH(port->hMcasp, GBLCTL, XSRCLR) &
MCASP_FGETH(port->hMcasp, GBLCTL, RSRCLR)));
while (MCASP_xdata(port->hMcasp));
MCASP_enableSm(port->hMcasp, MCASP_RCVXMT);
while (!(MCASP_FGETH(port->hMcasp, GBLCTL, XSMRST) &
MCASP_FGETH(port->hMcasp, GBLCTL, RSMRST)));
}
#else
MCASP_enableSers(port->hMcasp, MCASP_XMT);
while (!(MCASP_FGETH(port->hMcasp, GBLCTL, XSRCLR)));
while (MCASP_xdata(port->hMcasp));
MCASP_enableSm(port->hMcasp, MCASP_XMT);
while (!(MCASP_FGETH(port->hMcasp, GBLCTL, XSMRST)));
#endif
if (port->enableFsyncg == C6X1X_EDMA_MCASP_XMT) {
MCASP_enableFsync(port->hMcasp, MCASP_XMT);
while(!MCASP_FGETH(port->hMcasp,GBLCTL, XFRST));
}
else if ((port->enableFsyncg == C6X1X_EDMA_MCASP_RCVXMT) && (old)) {
MCASP_enableFsync(port->hMcasp, MCASP_RCVXMT);
while(!(MCASP_FGETH(port->hMcasp,GBLCTL, RFRST) &
MCASP_FGETH(port->hMcasp,GBLCTL, XFRST)) );
}
}
/* enable McASP event interrupt if registered */
/* Clear CKFAIL error before enable interrupt */
if (chan->mode == INPUT) {
if (port->evtCallback != NULL) {
if (port->evtMask & C6X1X_EDMA_MCASP_EVT_RCKFAIL) {
MCASP_FSETSH(port->hMcasp, RINTCTL, RCKFAIL, DISABLE);
while (MCASP_FGETH(port->hMcasp, RSTAT, RCKFAIL)) {
MCASP_FSETSH(port->hMcasp, RSTAT, RCKFAIL, YES);
}
MCASP_FSETSH(port->hMcasp, RINTCTL, RCKFAIL, ENABLE);
}
IRQ_enable(MCASP_getRcvEventId(port->hMcasp));
}
}
else {
if (port->evtCallback != NULL) {
if (port->evtMask & C6X1X_EDMA_MCASP_EVT_XCKFAIL) {
MCASP_FSETSH(port->hMcasp, XINTCTL, XCKFAIL, DISABLE);
while (MCASP_FGETH(port->hMcasp, XSTAT, XCKFAIL)) {
MCASP_FSETSH(port->hMcasp, XSTAT, XCKFAIL, YES);
}
MCASP_FSETSH(port->hMcasp, XINTCTL, XCKFAIL, ENABLE);
}
IRQ_enable(MCASP_getXmtEventId(port->hMcasp));
}
}
*chanp = (Ptr) chan;
return (IOM_COMPLETED);
}
/*
* ======== mdDeleteChan ========
* This function frees a channel and all it's associated resources.
*/
static Int mdDeleteChan(Ptr chanp)
{
ChanHandle chan = (ChanHandle) chanp;
PortHandle port = chan->port;
/* Clean up the channel resources */
chanCleanUp(chan, DELCHAN);
/*
* Reset the McASP transmitter or receiver. If the channel is
* recreated, mdCreateChan() will reenable the transmitter/receiver
* and by pulling it out of reset it will also restart the EDMA channel.
*/
if (chan->mode == INPUT) {
MCASP_resetRcv(port->hMcasp);
}
else {
MCASP_resetXmt(port->hMcasp);
}
return (IOM_COMPLETED);
}
/*
* ======== mdSubmitChan ========
* This function transmits a buffer to or from the McASP using the EDMA.
*/
static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet)
{
ChanHandle chan = (ChanHandle) chanp;
PortHandle port = chan->port;
Uns imask;
/* No packets can be submitted while abort or flush is active */
if (chan->flushPacket || chan->abortPacket) {
return (IOM_EBADIO);
}
/*
* Check to see if an abort command has been issued. Note that
* flushing the input channel is handled the same as abort.
*/
if ((packet->cmd == IOM_FLUSH && chan->mode == INPUT) ||
packet->cmd == IOM_ABORT) {
/* Disable interrupts to protect submitCount */
imask = HWI_disable();
/* Store the abort packet for the ISR to check */
if (chan->submitCount > 0) {
chan->abortPacket = packet;
/*
* Disable the EDMA channel while linking the currently
* executing job while linking it with the Loop job to make
* sure the currently executing job doesn't complete before
* the link is complete.
*/
EDMA_disableChannel(chan->xferPram);
EDMA_link(chan->xferPram, chan->loophEdma);
EDMA_enableChannel(chan->xferPram);
}
/* Reenable interrupts */
HWI_restore(imask);
if (chan->abortPacket) {
return(IOM_PENDING);
}
/* If there were no buffers in the channel, return synchronously */
packet->status = IOM_COMPLETED;
return (IOM_COMPLETED);
}
/* Check to see if the submitted packet is an output flush packet */
if (packet->cmd == IOM_FLUSH && chan->mode == OUTPUT) {
/* Disable interrupts to protect submitCount */
imask = HWI_disable();
/* Store the flush packet for the ISR to check */
if (chan->submitCount > 0) {
chan->flushPacket = packet;
}
/* Reenable interrupts */
HWI_restore(imask);
if (chan->flushPacket) {
return(IOM_PENDING);
}
/* If there were no buffers in the channel, return synchronously */
packet->status = IOM_COMPLETED;
return (IOM_COMPLETED);
}
if (packet->cmd != IOM_READ && packet->cmd != IOM_WRITE) {
/* Unsupported command passed */
return (IOM_ENOTIMPL);
}
/* maintain cache coherency */
if (chan->mode == INPUT) {
/* CACHE uses words, and packet->size is in nmaus (bytes on c6x) */
if (port->cacheCalls) {
CACHE_clean(CACHE_L2, packet->addr, packet->size >> 2);
}
}
else {
/* CACHE uses words, and packet->size is in nmaus (bytes on c6x) */
if (port->cacheCalls) {
CACHE_flush(CACHE_L2, packet->addr, packet->size >> 2);
}
}
/* Disable interrupts to protect submitCount */
imask = HWI_disable();
/*
* If there is no space available for the new packet, put it on a
* queue to be linked in when space is available. Otherwise link it in.
*/
if (chan->submitCount >= MAXLINKCNT) {
QUE_enqueue(&chan->packetQueue, packet);
}
else {
linkPacket(chan, packet);
}
chan->submitCount++;
HWI_restore(imask);
return (IOM_PENDING);
}
/*
* ======== mdUnBindDev ========
* This function frees a port and all it's associated resources.
*/
static Int mdUnBindDev(Ptr devp)
{
PortHandle port = (PortHandle) devp;
port->inUse = FALSE;
/* Close the McASP */
MCASP_close(port->hMcasp);
return (IOM_COMPLETED);
}
/*
* ======== C6X1X_EDMA_MCASP_init ========
* This function initializes the driver's data structures.
*/
#pragma CODE_SECTION(C6X1X_EDMA_MCASP_init, ".text:init");
Void C6X1X_EDMA_MCASP_init()
{
PortHandle port;
ChanHandle chan;
Int i, j;
/* Make sure the initialization only happens once for thid driver */
static Bool curInit = FALSE;
if (curInit) {
return;
}
curInit = TRUE;
for (i=0; i<NUMPORTS; i++) {
port = &ports[i];
port->inUse = FALSE;
for (j=0; j<NUMCHANS; j++) {
chan = &port->chans[j];
chan->inUse = FALSE;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -