c54xx_dma_mcbsp.c
上传用户:dahaojd
上传日期:2008-01-29
资源大小:14357k
文件大小:12k
源码类别:

DSP编程

开发平台:

C/C++

  1. /*
  2.  *  Copyright 2003 by Texas Instruments Incorporated.
  3.  *  All rights reserved. Property of Texas Instruments Incorporated.
  4.  *  Restricted rights to use, duplicate or disclose this code are
  5.  *  granted through contract.
  6.  *  
  7.  */
  8. /* "@(#) DDK 1.10.00.23 07-02-03 (ddk-b12)" */
  9. /*
  10.  *  ======== c54xx_dma_mcbsp.c ========
  11.  */
  12. #include <std.h>
  13. #include <atm.h>
  14. #include <hwi.h>
  15. #include <que.h>
  16. #include <csl.h>
  17. #include <csl_dma.h>
  18. #include <csl_irq.h>
  19. #include <csl_mcbsp.h>
  20. #include <iom.h>
  21. #include <c54xx_dma_mcbsp.h>
  22. #define NUMPORTS        MCBSP_PORT_CNT
  23. #define DELAY 10000
  24. /* Channel Object -- intialized by mdCreateChan() */
  25. typedef struct ChanObj {
  26.     Uns         inUse;          /* TRUE => channel has been opened */
  27.     Uns         dmaId;          /* channel id */
  28.     void        *devp;          /* needed for McBSP access */
  29.     DMA_Handle  hDma;           /* DMA handle */
  30.     IOM_Packet  *flushPacket;   /* used for submit/IOM_FLUSH/output */
  31.     IOM_Packet  *dataPacket;    /* current active I/O packet */
  32.     QUE_Obj     pendList;       /* list of packets for I/O */
  33.     IOM_TiomCallback cbFxn;     /* used to notify client when I/O complete */
  34.     Ptr         cbArg;
  35. } ChanObj, *ChanHandle;
  36. #define CHANOBJINIT { 
  37.     FALSE,              /* inUse */             
  38.     0,                  /* dmaId */             
  39.     NULL,               /* devp */              
  40.     NULL,               /* hDma */              
  41.     NULL,               /* flushPacket */       
  42.     NULL,               /* dataPacket */        
  43.     { NULL, NULL },     /* pendList */          
  44.     NULL,               /* cbFxn */             
  45.     NULL                /* cbArg */             
  46. }
  47. /* Device Object -- intialized by mdBindDev() */
  48. typedef struct PortObj {
  49.     Uns         inUse;
  50.     MCBSP_Handle hMcbsp;        /* McBSP handle */
  51.     ChanObj     chans[NUMCHANS];
  52.     Uns         rxIntrMask;
  53.     Uns         txIntrMask;
  54. } PortObj, *PortHandle;
  55. #define PORTOBJINIT { 
  56.     FALSE,              /* inUse */             
  57.     NULL,               /* hMcbsp */            
  58.     {                   /* chans */             
  59.         CHANOBJINIT,                            
  60.         CHANOBJINIT                             
  61.     },                                          
  62.     NULL,                                       
  63.     NULL                                        
  64. }
  65. #if NUMPORTS == 2
  66. static PortObj ports[NUMPORTS] = {              
  67.     PORTOBJINIT,                                
  68.     PORTOBJINIT                                 
  69. };
  70. #elif NUMPORTS == 3
  71. PortObj ports[NUMPORTS] = {                     
  72.     PORTOBJINIT,                                
  73.     PORTOBJINIT,                                
  74.     PORTOBJINIT                                 
  75. };
  76. #else
  77. #error Number of serials ports undefined!!
  78. #endif
  79. /*
  80.  * Forward declaration of IOM interface functions.
  81.  */
  82. static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams);
  83. static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args);
  84. static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
  85.         Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg);
  86. static Int mdDeleteChan(Ptr chanp);
  87. static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet);
  88. /*
  89.  * Public IOM interface table.
  90.  */
  91. IOM_Fxns C54XX_DMA_MCBSP_FXNS = {
  92.     mdBindDev,
  93.     IOM_UNBINDDEVNOTIMPL,
  94.     mdControlChan,
  95.     mdCreateChan,
  96.     mdDeleteChan,
  97.     mdSubmitChan,
  98. };
  99. /*
  100.  * local functions
  101.  */
  102. static Void startDma(ChanHandle chan, IOM_Packet *packet);
  103. static Void dmaIsr(ChanHandle chan);
  104. static Void abortio(ChanHandle chan);
  105. static Void mcbspStartDelay(Void);
  106. /*
  107.  *  ======== mdBindDev ========
  108.  */
  109. #pragma CODE_SECTION(mdBindDev, ".text:init")
  110. static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams)
  111. {
  112.     C54XX_DMA_MCBSP_DevParams *params = 
  113.         (C54XX_DMA_MCBSP_DevParams *)devParams;
  114.     PortHandle port = (PortHandle)&ports[devid];
  115.     if (ATM_setu(&port->inUse, TRUE)) {
  116.         return (IOM_EBADIO);
  117.     }
  118.     /* this driver requires parameters, there are no valid defaults */
  119.     if (params == NULL) {
  120.         return (IOM_EBADARGS);
  121.     }
  122.     /* Check the version number */
  123.     if (params->versionId != C54XX_DMA_MCBSP_VERSION_1){
  124.         return (IOM_EBADARGS);
  125.     }
  126.     /* open the McBSP */
  127.     port->hMcbsp = MCBSP_open(devid, MCBSP_OPEN_RESET);
  128.     
  129.     if (port->hMcbsp == INV) {
  130.         return (IOM_EBADIO);
  131.     }
  132.     
  133.     MCBSP_config(port->hMcbsp, params->mcbspCfg);
  134.     port->chans[INPUT].dmaId = params->rxDmaId;
  135.     port->chans[OUTPUT].dmaId = params->txDmaId;
  136.     /*store the interrupt masks */
  137.     port->rxIntrMask = params->rxIntrMask;
  138.     port->txIntrMask = params->txIntrMask;
  139.     *devp = port;
  140.     return (IOM_COMPLETED);
  141. }
  142. /*
  143.  *  ======== mdControlChan ========
  144.  */
  145. static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args)
  146. {
  147.     /*
  148.      * If a channel timeouts(in IOM class driver) a calldown is made to
  149.      * mdControlChan w/ cmd = IOM_CHAN_TIMED out. Timeout processing is
  150.      * optionally implemented here. If not performed return status of
  151.      * IOM_ENOTIMPL.
  152.      */
  153.     /*
  154.      *  Channel timed out. Perform needed channel cleanup.
  155.      */
  156.     if (cmd == IOM_CHAN_TIMEDOUT) {
  157.         abortio(chanp);
  158.     }
  159.     else {
  160.         return (IOM_ENOTIMPL); /* return IOM_ENOTIMPL for codes not handled */
  161.     }
  162.     return (IOM_COMPLETED);
  163. }
  164. /*
  165.  *  ======== mdCreateChan ========
  166.  */
  167. static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
  168.                 Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg)
  169. {
  170.     PortHandle                  port = (PortHandle)devp;
  171.     C54XX_DMA_MCBSP_ChanParams  *params =
  172.         (C54XX_DMA_MCBSP_ChanParams *)chanParams;
  173.     HWI_Attrs                   attrs;
  174.     ChanHandle                  chan;
  175.     Int                         event;
  176.     chan = (mode == IOM_INPUT) ? &port->chans[INPUT] : &port->chans[OUTPUT];
  177.     /* this driver requires channel parameters, no reasonable default */
  178.     if (params == NULL) {
  179.         return (IOM_EBADARGS);
  180.     }
  181.     /*
  182.      * Check check if channel is already in use.
  183.      * Use ATM_setu() for atomic test-and-set.
  184.      */
  185.     if (ATM_setu((Uns *)&chan->inUse, TRUE)) {
  186.         return (IOM_EBADIO);    /* ERROR! channel is already open! */
  187.     }
  188.     QUE_new(&chan->pendList);
  189.     chan->devp = devp;
  190.     chan->cbFxn = cbFxn;
  191.     chan->cbArg = cbArg;
  192.     
  193.     /* open and configure DMA */
  194.     chan->hDma = DMA_open(chan->dmaId, DMA_OPEN_RESET);
  195.     if (chan->hDma == INV) {
  196.         return (IOM_EBADIO);
  197.     }
  198.     DMA_config(chan->hDma, params->dmaCfg);
  199.     event = DMA_getEventId(chan->hDma);
  200.     /* plug interrupt vector */
  201.     attrs.intrMask =  (mode == IOM_INPUT) ? port->rxIntrMask : port->txIntrMask;
  202.     attrs.arg = (Arg)chan;
  203.     HWI_dispatchPlug(event, (Fxn)dmaIsr, &attrs);
  204.     /* enable DMA interrupt */
  205.     IRQ_enable(event);
  206.     *chanp = chan;
  207.     return (IOM_COMPLETED);             /* success */
  208. }
  209. /*
  210.  *  ======== mdDeleteChan ========
  211.  *  Mark the channel available and disable the appropriate interrupt.
  212.  */
  213. static Int mdDeleteChan(Ptr chanp)
  214. {
  215.     ChanHandle chan = (ChanHandle)chanp;
  216.     /* disable DMA interrupt */
  217.     IRQ_disable(DMA_getEventId(chan->hDma));
  218.     /* close the DMA channel */
  219.     DMA_close(chan->hDma);
  220.     chan->inUse = FALSE;
  221.     return (IOM_COMPLETED);
  222. }
  223. /*
  224.  *  ======== mdSubmitChan ========
  225.  */
  226. static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet)
  227. {
  228.     ChanHandle  chan = (ChanHandle)chanp;
  229.     PortHandle  port = (PortHandle)chan->devp;
  230.     Uns         imask;
  231.     if (packet->cmd == IOM_FLUSH || packet->cmd == IOM_ABORT) {
  232.         abortio(chan);
  233.         packet->status = IOM_COMPLETED; /* flush/abort pkt completed */
  234.         return (IOM_COMPLETED);
  235.     }
  236.     imask = HWI_disable();
  237.     if (chan->dataPacket != NULL) {
  238.         QUE_enqueue(&chan->pendList, packet);
  239.     }
  240.     else {
  241.         chan->dataPacket = packet;
  242.         startDma(chan, packet);
  243.         if (packet->cmd == IOM_READ) {
  244.                 /* start the McBSP */
  245.                 MCBSP_start(port->hMcbsp, MCBSP_RCV_START, 0x0);
  246.         }
  247.         else {
  248.                 /* start the McBSP */
  249.                 MCBSP_start(port->hMcbsp, MCBSP_XMIT_START, 0x0);
  250.         }
  251.     }
  252.     HWI_restore(imask);
  253.     return (IOM_PENDING);
  254. }
  255. /*
  256.  *  ======== C54XX_DMA_MCBSP_init ========
  257.  */
  258. #pragma CODE_SECTION(C54XX_DMA_MCBSP_init, ".text:init")
  259. Void C54XX_DMA_MCBSP_init(Void)
  260. {
  261.     /* beware ... this is a global register! */
  262.     DMA_FSET(DMPREC, FREE, 1);
  263. }
  264. /*
  265.  *  ======== startDma ========
  266.  */
  267. static Void startDma(ChanHandle chan, IOM_Packet *packet)
  268. {
  269.     /* Program address in appropriate DMA channel and start transfer. */
  270.     if (packet->cmd == IOM_READ) {
  271.         DMA_RSETH(chan->hDma, DMDST, packet->addr);
  272.         DMA_RSETH(chan->hDma, DMCTR, packet->size - 1);
  273.         DMA_start(chan->hDma);
  274.     }
  275.     else {      
  276.         DMA_RSETH(chan->hDma, DMSRC, packet->addr);
  277.         DMA_RSETH(chan->hDma, DMCTR, packet->size - 1);
  278.         DMA_start(chan->hDma);
  279.     }
  280. }
  281. /*
  282.  *  ======== dmaIsr ========
  283.  */
  284. Void dmaIsr(ChanHandle chan)
  285. {
  286.     PortHandle  port = (PortHandle)chan->devp;
  287.     IOM_Packet *packet = chan->dataPacket;
  288.     if (packet == NULL) {
  289.         /* return if spurious interrupt */
  290.         return;
  291.     }
  292.     packet->status = IOM_COMPLETED;
  293.     chan->dataPacket = QUE_get(&chan->pendList);
  294.     if (chan->dataPacket == (IOM_Packet *)&chan->pendList) {
  295.         chan->dataPacket = NULL;
  296.                 if (packet->cmd == IOM_READ) {
  297.                 MCBSP_FSETH (port->hMcbsp, SPCR1, RRST, 0);
  298.                         mcbspStartDelay();
  299.         }
  300.         else {
  301.                 MCBSP_FSETH (port->hMcbsp, SPCR2, XRST, 0);
  302.                         mcbspStartDelay();
  303.         }
  304.     }
  305.     else {
  306.                 if (packet->cmd == IOM_READ) {
  307.                 if ( MCBSP_rrdy(port->hMcbsp) ) {
  308.                                 /* reset the McBSP */
  309.                     MCBSP_FSETH (port->hMcbsp, SPCR1, RRST, 0);
  310.                                 mcbspStartDelay();
  311.                     startDma(chan, chan->dataPacket);
  312.                     /* restart the McBSP */
  313.                     MCBSP_start(port->hMcbsp, MCBSP_RCV_START, 0x0);
  314.             }
  315.             else {
  316.                 startDma(chan, chan->dataPacket);
  317.             }
  318.         }
  319.         else {
  320.                 if ( MCBSP_xrdy(port->hMcbsp) ) {
  321.                                 /* reset the McBSP */
  322.                     MCBSP_FSETH (port->hMcbsp, SPCR2, XRST, 0);
  323.                                 mcbspStartDelay();
  324.                     startDma(chan, chan->dataPacket);
  325.                     /* restart the McBSP */
  326.                     MCBSP_start(port->hMcbsp, MCBSP_XMIT_START, 0x0);
  327.             }
  328.                         else {
  329.                                 startDma(chan, chan->dataPacket);
  330.                         }  
  331.                 }
  332.         }
  333.         (*chan->cbFxn)(chan->cbArg, packet);
  334. }
  335. /*
  336.  *  ======== abortio ========
  337.  *  Aborts uncompleted i/o packet requests.
  338.  */
  339. static Void abortio(ChanHandle chan)
  340. {
  341.     IOM_Packet *tmpPacket;
  342.     DMA_stop(chan->hDma);
  343.     HWI_disable();
  344.     tmpPacket = chan->dataPacket;
  345.     chan->dataPacket = NULL;
  346.     HWI_enable();
  347.     if (tmpPacket) {
  348.         tmpPacket->status = IOM_ABORTED;   /* abort current request */
  349.         (*chan->cbFxn)(chan->cbArg, tmpPacket);
  350.         tmpPacket = QUE_get(&chan->pendList);
  351.         while (tmpPacket != (IOM_Packet *)&chan->pendList) {
  352.             tmpPacket->status = IOM_ABORTED;   /* abort queued requests */
  353.             (*chan->cbFxn)(chan->cbArg, tmpPacket);
  354.             tmpPacket = QUE_get(&chan->pendList);
  355.         }
  356.     }
  357. }
  358. static Void mcbspStartDelay(Void)
  359. {
  360.         volatile int i;
  361.         /* This delay is mainly for allowing
  362.          * two mcbsp external clocks to happen from
  363.          * the time Mcbsp is put in reset to the time
  364.          * Mcbsp is taken out of reset. */
  365.         for(i=0; i<DELAY; i++) {
  366.         }
  367. }