openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

cmicd_dma.c (27609B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * Purpose:     CMICDV2 interface drvier for SOC DMA
      8  */
      9 
     10 #include <sal/core/boot.h>
     11 #include <sal/core/libc.h>
     12 #include <shared/alloc.h>
     13 #include <shared/bsl.h>
     14 
     15 #include <soc/debug.h>
     16 #include <soc/cm.h>
     17 #include <soc/dma.h>
     18 #include <soc/drv.h>
     19 #include <soc/dcb.h>
     20 #include <soc/cmicm.h>
     21 
     22 #ifdef INCLUDE_KNET
     23 #include <soc/knet.h>
     24 #endif
     25 
     26 #ifdef BCM_CMICDV2_SUPPORT
     27 
     28 #define DCB_LAST_DWORD 0xF
     29 #define DCB_DONE_BIT   0x80000000
     30 
     31 /* CMICD needs access to CMICM driver functions */
     32 soc_cmic_dma_drv_t soc_cmicm_dma_drv[SOC_MAX_NUM_DEVICES];
     33 
     34 /* Static Driver Functions */
     35 
     36 /*
     37  * Function:
     38  *      cmicd_dma_ctrl_reset
     39  * Purpose:
     40  *      Reset the CMICD DMA Control to a known good state for
     41  *      the specified SOC unit.
     42  * Parameters:
     43  *      unit - SOC unit #
     44  * Returns:
     45  *      SOC_E_NONE - success
     46  *      SOC_E_XXXX - error code
     47  * Notes:
     48  */
     49 
     50 int
     51 cmicd_dma_ctrl_init(int unit)
     52 {
     53     return(soc_cmicm_dma_drv[unit].ctrl_init(unit));
     54 }
     55 
     56 
     57 /*
     58  * Function:
     59  *      cmicd_dma_chan_config
     60  * Purpose:
     61  *      Initialize the CMICD DMA channel for the specified SOC unit.
     62  * Parameters:
     63  *      unit - SOC unit #
     64  *      chan - channel #
     65  *      type - tx or rx
     66  *      f_intr - interrupt flags
     67  * Returns:
     68  *      SOC_E_NONE - success
     69  *      SOC_E_XXXX - error code
     70  * Notes:
     71  */
     72 static int
     73 cmicd_dma_chan_config(int unit, int vchan, dvt_t type, uint32 flags)
     74 {
     75     int             rv = SOC_E_NONE;
     76     soc_control_t   *soc = SOC_CONTROL(unit);
     77     sdc_t           *sc = &soc->soc_channels[vchan];
     78     uint32          bits;
     79     int             cmc = vchan / N_DMA_CHAN;
     80     int             chan = vchan % N_DMA_CHAN;
     81     uint32          cr;
     82 
     83     /* Define locals and turn flags into easy to use things */
     84     /*int f_mbm = (flags & SOC_DMA_F_MBM) != 0; */
     85     int f_interrupt = (flags & SOC_DMA_F_POLL) == 0;
     86     /*int f_drop = (flags & SOC_DMA_F_TX_DROP) != 0; */
     87     int f_default = (flags & SOC_DMA_F_DEFAULT) != 0;
     88     int f_desc_intr = (flags & SOC_DMA_F_INTR_ON_DESC) != 0;
     89     int init_hw = TRUE;
     90 
     91     /* Set channel to Continuous Mode */
     92     SOC_DMA_MODE(unit) = SOC_DMA_MODE_CONTINUOUS;
     93 
     94     /* Initial state of channel */
     95     sc->sc_flags = 0;                   /* Clear flags to start */
     96 
     97 #ifdef INCLUDE_KNET
     98     if (SOC_KNET_MODE(unit) && SOC_WARM_BOOT(unit) &&
     99         soc_property_get(unit, spn_WARMBOOT_KNET_SHUTDOWN_MODE, 0)) {
    100         init_hw = FALSE;
    101     }
    102 #endif
    103 
    104     if (init_hw) {
    105         (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_DESC_DONE(chan) |
    106                                             IRQ_CMCx_CNTLD_DESC_DONE(chan) |
    107                                             IRQ_CMCx_CHAIN_DONE(chan));
    108 
    109         cr = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan));
    110         cr &= ~PKTDMA_ENABLE; /* clearing enable will also clear CHAIN_DONE */
    111         soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), cr);
    112 
    113         cr = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc));
    114         soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc),
    115                       DS_CNTLD_DESC_CLR(chan));
    116         soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), cr);
    117     }
    118 
    119     /* Setup new mode */
    120     /* MBM Deprecated in CMICm */
    121     /* DROP_TX Deprecated in CMICm */
    122     bits = f_desc_intr ? PKTDMA_SEL_INTR_ON_DESC_OR_PKT : 0;
    123 
    124     if (type == DV_TX) {
    125         bits |= PKTDMA_DIRECTION;
    126         if (f_default) {
    127             soc->soc_dma_default_tx = sc;
    128         }
    129     } else if (type == DV_RX) {
    130         bits &= ~PKTDMA_DIRECTION;
    131         if (f_default) {
    132             soc->soc_dma_default_rx = sc;
    133         }
    134     } else if (type == DV_NONE) {
    135         f_interrupt = FALSE;            /* Force off */
    136     } else {
    137         assert(0);
    138     }
    139 
    140 #ifdef INCLUDE_KNET
    141     if (SOC_KNET_MODE(unit)) {
    142         /* Interrupt are handled by kernel */
    143         f_interrupt = FALSE;
    144     }
    145 #endif
    146 
    147     /* Only enable controlled descriptor
    148        done interrupt for TX AND RX Continuous Mode */
    149     if (f_interrupt) {
    150         (void)soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_CNTLD_DESC_DONE(chan));
    151     }
    152 
    153     sc->sc_type = type;
    154     if (init_hw) {
    155         cr = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan));
    156 
    157         /* Clear everything except Endianess */
    158         cr &= (PKTDMA_BIG_ENDIAN | PKTDMA_DESC_BIG_ENDIAN);
    159         cr |= bits;
    160 
    161         /* Use Controlled Descriptor Interrupt Mode */
    162         cr |= PKTDMA_CNTLD_DESC_INTR_MODE;
    163 
    164         soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), cr);
    165     }
    166 
    167     return rv;
    168 }
    169 
    170 /*
    171  * Function:
    172  *      cmicd_dma_chan_start
    173  * Purpose:
    174  *      Start the CMICd DMA channel for the specified SOC unit.
    175  * Parameters:
    176  *      unit - SOC unit #
    177  *      sc   - SOC channel data structure pointer
    178  * Returns:
    179  *      SOC_E_NONE - success
    180  *      SOC_E_XXXX - error code
    181  * Notes:
    182  */
    183 static int
    184 cmicd_dma_chan_start(int unit, sdc_t *sc)
    185 {
    186     int             rv = SOC_E_NONE;
    187     dv_t            *dv;
    188     int             cmc = sc->sc_channel / N_DMA_CHAN;
    189     int             chan = sc->sc_channel % N_DMA_CHAN;
    190     uint32          val;
    191 
    192     if ((dv = sc->sc_dv_active = sc->sc_q) == NULL) {
    193         sc->sc_q_tail = NULL;
    194         return rv;
    195     }
    196 
    197 #ifdef INCLUDE_KNET
    198     if (SOC_KNET_MODE(unit)) {
    199         return rv;
    200     }
    201 #endif
    202 
    203     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    204                       (BSL_META_U(unit,
    205                                   "Starting channel %d\n"),
    206                        sc->sc_channel));
    207 
    208     /* Set up DMA descriptor address */
    209     soc_pci_write(unit, CMIC_CMCx_DMA_DESCy_OFFSET(cmc, chan),
    210                   soc_cm_l2p(unit, sc->sc_q->dv_dcb));
    211 
    212     /* Start DMA - Enable Continuous Mode for this channel */
    213     val = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan));
    214     val |= (PKTDMA_ENABLE | PKTDMA_CONTINUOUS_ENABLE);
    215     soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), val);
    216 
    217     SDK_CONFIG_MEMORY_BARRIER;
    218 
    219     if (!(sc->sc_flags & SOC_DMA_F_POLL)) {
    220         (void)soc_cmicm_cmcx_intr0_enable(unit, cmc,
    221                                      IRQ_CMCx_CNTLD_DESC_DONE(chan));
    222     }
    223 
    224     return rv;
    225 }
    226 
    227 /*
    228  * Function:
    229  *      cmicd_dma_chan_poll
    230  * Purpose:
    231  *      Poll the CMICD DMA channel for the specified SOC unit.
    232  * Parameters:
    233  *      unit - SOC unit #
    234  *      chan - channel #
    235  *      type - poll type (chain done or desc done)
    236  *      detected - poll result pointer to be updated
    237  * Returns:
    238  *      SOC_E_NONE - success
    239  *      SOC_E_XXXX - error code
    240  * Notes:
    241  *      Assumes that SOC_DMA_LOCK is held when called.
    242  */
    243 static int
    244 cmicd_dma_chan_poll(int unit,
    245                     int vchan,
    246                     soc_dma_poll_type_t type,
    247                     int * detected)
    248 {
    249     return (soc_cmicm_dma_drv[unit].chan_poll(unit, vchan, type, detected));
    250 }
    251 
    252 /*
    253  * Function:
    254  *      cmicd_dma_chan_abort
    255  * Purpose:
    256  *      Initialize the CMICD DMA channel for the specified SOC unit.
    257  * Parameters:
    258  *      unit - SOC unit #
    259  *      chan - channel #
    260  *      type - tx or rx
    261  *      f_intr - interrupt flags
    262  * Returns:
    263  *      SOC_E_NONE   - Success
    264  *      SOC_E_TIMEOUT - failed (Timeout)
    265  * Notes:
    266  *      Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation.
    267  */
    268 static int
    269 cmicd_dma_chan_abort(int unit, int vchan)
    270 {
    271     int             rv = SOC_E_NONE;
    272     int             cmc = vchan / N_DMA_CHAN;
    273     int             chan = vchan % N_DMA_CHAN;
    274     int		        to;
    275     uint32          ctrl;
    276     soc_control_t  *soc = SOC_CONTROL(unit);
    277     sdc_t          *sc = &soc->soc_channels[chan];
    278 
    279     if ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc))
    280          & DS_CMCx_DMA_ACTIVE(chan)) != 0) {
    281         ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan));
    282         ctrl |= PKTDMA_ENABLE;
    283         soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), ctrl);
    284         soc_pci_write(unit,
    285                       CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan),
    286                       ctrl | PKTDMA_ABORT);
    287         SDK_CONFIG_MEMORY_BARRIER;
    288 
    289         to = soc_property_get(unit, spn_PDMA_TIMEOUT_USEC, 500000);
    290         while ((to >= 0) &&
    291                ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc))
    292                  & DS_CMCx_DMA_ACTIVE(chan)) != 0)) {
    293             sal_udelay(1000);
    294             to -= 1000;
    295         }
    296         if ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc))
    297              & DS_CMCx_DMA_ACTIVE(chan)) != 0) {
    298             LOG_ERROR(BSL_LS_SOC_PACKETDMA,
    299                       (BSL_META_U(unit,
    300                                   "soc_dma_abort_channel unit %d: "
    301                                   "channel %d abort timeout\n"),
    302                        unit, chan));
    303             rv = SOC_E_TIMEOUT;
    304             if (SOC_WARM_BOOT(unit)) {
    305                 return rv;
    306             }
    307         }
    308     }
    309     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    310                 (BSL_META_U(unit,
    311                             "soc_dma_abort_channel unit %d: "
    312                             "channel %d\n"),
    313                  unit, chan));
    314 
    315     ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan));
    316     /* Clearing enable will also clear CHAIN_DONE */
    317     ctrl &= ~(PKTDMA_ENABLE|PKTDMA_ABORT);
    318     soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), ctrl);
    319 
    320     soc_pci_write(unit,
    321                   CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc),
    322                   (DS_DESCRD_CMPLT_CLR(chan) | DS_CNTLD_DESC_CLR(chan)));
    323     SDK_CONFIG_MEMORY_BARRIER;
    324 
    325     /* Mark channel as not started */
    326     sc->sc_dma_started = 0;
    327 
    328     return rv;
    329 }
    330 
    331 /*
    332  * Function:
    333  *      cmicd_dma_chan_dv_start
    334  * Purpose:
    335  *      Adds DV to the ready queue for CMICD DMA for the specified SOC unit.
    336  * Parameters:
    337  *      unit - SOC unit #
    338  *      chan - channel #
    339  * Returns:
    340  *      SOC_E_NONE - success
    341  *      SOC_E_XXXX - error code
    342  * Notes:
    343  *      Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation.
    344  */
    345 static int
    346 cmicd_dma_chan_dv_start(int unit, sdc_t *sc, dv_t *dv_chain)
    347 {
    348     int             rv = SOC_E_NONE;
    349     int             cmc = sc->sc_channel / N_DMA_CHAN;
    350     int             chan = sc->sc_channel % N_DMA_CHAN;
    351     dcb_t           *dcb;
    352     sal_paddr_t     reg_addr = 0;
    353     sal_paddr_t     reg_val = 0;
    354 
    355     dv_chain->dv_next = NULL;
    356 
    357 #ifdef INCLUDE_KNET
    358     if (SOC_KNET_MODE(unit)) {
    359         /* KNET handling of DV start */
    360         if (sc->sc_q_cnt != 0) {
    361             sc->sc_q_tail->dv_next = dv_chain;
    362         } else {
    363             sc->sc_q = dv_chain;
    364         }
    365         sc->sc_q_tail = dv_chain;
    366         sc->sc_q_cnt++;
    367         if (sc->sc_dv_active == NULL) {
    368             if (sc->sc_dma_started) {
    369                 sc->sc_dv_active = sc->sc_q;
    370             } else {
    371                 /* Start DMA if channel not active */
    372                 rv = cmicd_dma_chan_start(unit, sc);
    373                 sc->sc_dma_started = 1;
    374             }
    375         }
    376         return rv;
    377     }
    378 #endif
    379 
    380     if (sc->sc_q_cnt != 0) {
    381         sc->sc_q_tail->dv_next = dv_chain;
    382         /* Set the reload addr of tail to the address of the appended chain */
    383         dcb = SOC_DCB_IDX2PTR(unit, sc->sc_q_tail->dv_dcb,
    384                               sc->sc_q_tail->dv_vcnt - 1);
    385         SOC_DCB_ADDR_SET(dv_chain->dv_unit, dcb,
    386                          (sal_vaddr_t)dv_chain->dv_dcb);
    387     } else {
    388         sc->sc_q = dv_chain;
    389     }
    390     sc->sc_q_tail = dv_chain;
    391     sc->sc_q_cnt++;
    392 
    393     /* Set the HW register for the new DESC_HALT_ADDR- new for CMICDV2 */
    394     /* Need logical to physical mapping for addr */
    395     /* If DMA is currently halted, writing the new rld addr starts it again */
    396     reg_addr = (sal_paddr_t)CMIC_CMCx_DMA_CHy_DESC_HALT_ADDR_OFFSET(cmc, chan);
    397 
    398     reg_val = soc_cm_l2p(unit,
    399                          (void*)SOC_DCB_IDX2PTR(unit, dv_chain->dv_dcb,
    400                                                 (dv_chain->dv_vcnt - 1)));
    401     soc_pci_write(unit, reg_addr, reg_val);
    402     SDK_CONFIG_MEMORY_BARRIER;
    403 
    404     /* Start DMA if channel not active */
    405     if ((sc->sc_dv_active == NULL) && (!sc->sc_dma_started)) {
    406         rv = cmicd_dma_chan_start(unit, sc);
    407         sc->sc_dma_started = 1;
    408     }
    409 
    410     return rv;
    411 }
    412 
    413 /*
    414  * Function:
    415  *      cmicd_dma_chan_chain_done
    416  * Purpose:
    417  *      on the CMICD DMA channel for the specified SOC unit.
    418  * Parameters:
    419  *      unit - SOC unit #
    420  *      chan - channel #
    421  *      mitigation - >0 = interrupt mitigation on
    422  * Returns:
    423  *      SOC_E_NONE - success
    424  *      SOC_E_XXXX - error code
    425  * Notes:
    426  *      INTERRUPT LEVEL ROUTINE.
    427  */
    428 static int
    429 cmicd_dma_chan_chain_done(int unit, int vchan, int mitigation)
    430 {
    431     return (soc_cmicm_dma_drv[unit].chan_chain_done(unit, vchan, mitigation));
    432 }
    433 
    434 /*
    435  * Function:
    436  *      cmicd_dma_chan_desc_done
    437  * Purpose:
    438  *      Clears desc done on the CMICD DMA channel for the specified SOC unit.
    439  * Parameters:
    440  *      unit - SOC unit #
    441  *      chan - channel #
    442  * Returns:
    443  *      SOC_E_NONE - success
    444  *      SOC_E_XXXX - error code
    445  * Notes:
    446  *      INTERRUPT LEVEL ROUTINE.
    447  */
    448 static int
    449 cmicd_dma_chan_desc_done(int unit, int vchan)
    450 {
    451     int             rv = SOC_E_NONE;
    452     int             cmc = vchan / N_DMA_CHAN;
    453     int             chan = vchan % N_DMA_CHAN;
    454 
    455     /*
    456      * Older CMIC devices required a read/write/modify to clear done
    457      * interrupts. That does not work here for continuous DMA.  Need only
    458      * to set the bit for the corresponding interrupt to clear.
    459      */
    460     soc_pci_write(unit,
    461                   CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc),
    462                   DS_CNTLD_DESC_CLR(chan));
    463 
    464     /* Flush posted writes from PCI bridge */
    465     (void)soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc));
    466 
    467     return rv;
    468 }
    469 
    470 /*
    471  * Function:
    472  *      cmicd_dma_chan_desc_done_intr_enable
    473  * Purpose:
    474  *      Clears desc done on the CMICD DMA channel for the specified SOC unit.
    475  * Parameters:
    476  *      unit - SOC unit #
    477  *      chan - channel #
    478  * Returns:
    479  *      SOC_E_NONE - success
    480  *      SOC_E_XXXX - error code
    481  * Notes:
    482  *      INTERRUPT LEVEL ROUTINE.
    483  */
    484 static int
    485 cmicd_dma_chan_desc_done_intr_enable(int unit, int vchan)
    486 {
    487     return (soc_cmicm_dma_drv[unit].chan_desc_done_intr_enable(unit, vchan));
    488 }
    489 
    490 /*
    491  * Function:
    492  *      cmicd_dma_chan_reload_done
    493  * Purpose:
    494  *      Detect for reload descriptor completed
    495  * Parameters:
    496  *      unit - SOC unit #
    497  *      sc   - SOC channel data structure pointer
    498  * Returns:
    499  *      SOC_E_NONE - success
    500  *      SOC_E_XXXX - error code
    501  * Notes:
    502  */
    503 static int
    504 cmicd_dma_chan_reload_done(int unit, int vchan, dcb_t * dcb, int *rld_done)
    505 {
    506     int             rv = SOC_E_NONE;
    507     uint32          *rld_dcb;
    508 
    509     *rld_done = 0; /* Default to not reload */
    510 
    511     /* There is no pkt data to process for a reload descriptor */
    512     if(SOC_DCB_RELOAD_GET(unit, dcb)) {
    513         /* HW sets bit 31 in the dcb's last dword to indicate done */
    514         rld_dcb = (uint32 *)dcb;
    515         if (rld_dcb[DCB_LAST_DWORD] & DCB_DONE_BIT) {
    516             *rld_done = 1;
    517         }
    518     }
    519 
    520     return rv;
    521 }
    522 
    523 /*
    524  * Function:
    525  *      cmicd_dma_chan_tx_purge
    526  * Purpose:
    527  *      Purge partial pkt left in the pipeline from TX DMA abort.
    528  * Parameters:
    529  *      unit - SOC unit #
    530  *      chan - channel #
    531  * Returns:
    532  *      SOC_E_NONE   - Success
    533  *      SOC_E_TIMEOUT - failed (Timeout)
    534  * Notes:
    535  *      Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation.
    536  */
    537 static int
    538 cmicd_dma_chan_tx_purge(int unit, int vchan, dv_t *dv)
    539 {
    540     return (soc_cmicm_dma_drv[unit].chan_tx_purge(unit, vchan, dv));
    541 }
    542 
    543 /*
    544  * Function:
    545  *      cmicd_dma_chan_counter_get
    546  * Purpose:
    547  *      Obtain tx and rx counter values
    548  * Parameters:
    549  *      unit    - SOC unit #
    550  *      vchan   - SOC virtual channel number
    551  * Returns:
    552  *      SOC_E_NONE - success
    553  * Notes:
    554  */
    555 static int
    556 cmicd_dma_chan_counter_get(int unit, int vchan, uint32 *tx_pkt, uint32 *rx_pkt)
    557 {
    558     return (soc_cmicm_dma_drv[unit].chan_counter_get(unit, vchan, tx_pkt, rx_pkt));
    559 }
    560 
    561 /*
    562  * Function:
    563  *      cmicd_dma_chan_counter_clear
    564  * Purpose:
    565  *      clear tx and rx counter values
    566  * Parameters:
    567  *      unit    - SOC unit #
    568  *      vchan   - SOC virtual channel number
    569  *      mask    - to clear the appopriate counter
    570  * Returns:
    571  *      SOC_E_NONE - success
    572  * Notes:
    573  */
    574 static int
    575 cmicd_dma_chan_counter_clear(int unit, int vchan, uint32 mask)
    576 {
    577     return (soc_cmicm_dma_drv[unit].chan_counter_clear(unit, vchan, mask));
    578 }
    579 
    580 /*
    581  * Function:
    582  *      cmicd_dma_cmc_counter_get
    583  * Purpose:
    584  *      Obtain tx and rx counter values
    585  * Parameters:
    586  *      unit    - SOC unit #
    587  *      cmc     - cmc number
    588  * Returns:
    589  *      SOC_E_NONE - success
    590  * Notes:
    591  */
    592 static int
    593 cmicd_dma_cmc_counter_get(int unit, int cmc, uint32 *tx_pkt, uint32 *rx_pkt)
    594 {
    595     return (soc_cmicm_dma_drv[unit].cmc_counter_get(unit, cmc, tx_pkt, rx_pkt));
    596 }
    597 
    598 /*
    599  * Function:
    600  *      cmicd_dma_cmc_counter_clear
    601  * Purpose:
    602  *      clear tx and rx counter values
    603  * Parameters:
    604  *      unit    - SOC unit #
    605  *      cmc     - cmc number
    606  *      mask    - to clear the appopriate counter
    607  * Returns:
    608  *      SOC_E_NONE - success
    609  * Notes:
    610  */
    611 static int
    612 cmicd_dma_cmc_counter_clear(int unit, int cmc, uint32 mask)
    613 {
    614     return (soc_cmicm_dma_drv[unit].cmc_counter_clear(unit, cmc, mask));
    615 }
    616 
    617 /*
    618  * Function:
    619  *      cmicd_dma_chan_status_get
    620  * Purpose:
    621  *      get channel status
    622  * Parameters:
    623  *      unit   - SOC unit #
    624  *      vchan  - channel #
    625  *      status - channel status
    626  *
    627  * Returns:
    628  *      SOC_E_NONE - success
    629  *      SOC_E_XXXX - error code
    630  * Notes:
    631  */
    632 
    633 int
    634 cmicd_dma_chan_status_get(int unit, int vchan, uint32 mask, int *status)
    635 {
    636     int    rv  = SOC_E_NONE;
    637     int cmc  = vchan / N_DMA_CHAN;
    638 
    639     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    640                       (BSL_META_U(unit,
    641                                   "channel status get\n")));
    642 
    643     if (mask & 0x1) {
    644         *status = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc));
    645     } else if (mask & 0x2) {
    646         *status = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_HI_OFFSET(cmc));
    647     }
    648 
    649     return rv;
    650 }
    651 
    652 /*
    653  * Function:
    654  *      cmicd_dma_chan_status_clear
    655  * Purpose:
    656  *      clear channel status
    657  * Parameters:
    658  *      unit  - SOC unit #
    659  *      vchan - channel #
    660  *
    661  * Returns:
    662  *      SOC_E_NONE - success
    663  *      SOC_E_XXXX - error code
    664  * Notes:
    665  */
    666 
    667 int
    668 cmicd_dma_chan_status_clear(int unit, int vchan)
    669 {
    670     int    rv  = SOC_E_NONE;
    671     int cmc  = vchan / N_DMA_CHAN;
    672 
    673     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    674                       (BSL_META_U(unit,
    675                                   "channel status clear\n")));
    676 
    677     soc_pci_write(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc), 0x0);
    678     soc_pci_write(unit, CMIC_CMCx_DMA_STAT_HI_OFFSET(cmc), 0x0);
    679 
    680     return rv;
    681 }
    682 
    683 /*
    684  * Function:
    685  *      cmicd_dma_chan_halt_get
    686  * Purpose:
    687  *      get channel halt status
    688  * Parameters:
    689  *      unit   - SOC unit #
    690  *      vchan  - channel #
    691  *      halt   - channel halt status
    692  *
    693  * Returns:
    694  *      SOC_E_NONE - success
    695  *      SOC_E_XXXX - error code
    696  * Notes:
    697  */
    698 
    699 int
    700 cmicd_dma_chan_halt_get(int unit, int vchan, uint32 mask, int *halt)
    701 {
    702     int rv   = SOC_E_NONE;
    703     int cmc  = vchan / N_DMA_CHAN;
    704     int chan = vchan % N_DMA_CHAN;
    705 
    706     *halt = (soc_pci_read(unit, CMIC_CMCx_DMA_STAT_HI_OFFSET(cmc))
    707                          & DS_CMCx_DMA_IN_HALT(chan));
    708 
    709     return rv;
    710 }
    711 
    712 /*
    713  * Function:
    714  *      cmicd_dma_chan_ctrl_reg_get
    715  * Purpose:
    716  *      get channel ctrl reg value
    717  * Parameters:
    718  *      unit  - SOC unit #
    719  *      vchan - channel #
    720  *      value - channel ctrl reg value
    721  *
    722  * Returns:
    723  *      SOC_E_NONE - success
    724  *      SOC_E_XXXX - error code
    725  * Notes:
    726  */
    727 
    728 int
    729 cmicd_dma_chan_ctrl_reg_get(int unit, int vchan, uint32 *val)
    730 {
    731     return (soc_cmicm_dma_drv[unit].chan_ctrl_reg_get(unit, vchan, val));
    732 }
    733 
    734 /*
    735  * Function:
    736  *      cmicd_dma_chan_ctrl_reg_set
    737  * Purpose:
    738  *      set channel ctrl reg
    739  * Parameters:
    740  *      unit  - SOC unit #
    741  *      vchan - channel #
    742  *      value - channel ctrl reg value to set
    743  *
    744  * Returns:
    745  *      SOC_E_NONE - success
    746  *      SOC_E_XXXX - error code
    747  * Notes:
    748  */
    749 
    750 int
    751 cmicd_dma_chan_ctrl_reg_set(int unit, int vchan, uint32 val)
    752 {
    753     return (soc_cmicm_dma_drv[unit].chan_ctrl_reg_set(unit, vchan, val));
    754 }
    755 
    756 /*
    757  * Function:
    758  *      cmicd_dma_chan_cos_ctrl_get
    759  * Purpose:
    760  *      get cos ctrl for a channel
    761  * Parameters:
    762  *      unit - SOC unit #
    763  *      cfg  - to choose appropriate register
    764  * Returns:
    765  *      SOC_E_NONE - success
    766  *      SOC_E_XXXX - error code
    767  * Notes:
    768  */
    769 
    770 int
    771 cmicd_dma_chan_cos_ctrl_get(int unit, int vchan, uint32 cfg, uint32 *cos_ctrl)
    772 {
    773      return (soc_cmicm_dma_drv[unit].chan_cos_ctrl_get(unit, vchan, cfg, cos_ctrl));
    774 }
    775 
    776 /*
    777  * Function:
    778  *      cmicd_dma_chan_cos_ctrl_set
    779  * Purpose:
    780  *      get cos ctrl for a channel
    781  * Parameters:
    782  *      unit - SOC unit #
    783  *      cfg  - to choose appropriate register
    784  * Returns:
    785  *      SOC_E_NONE - success
    786  *      SOC_E_XXXX - error code
    787  * Notes:
    788  */
    789 
    790 int
    791 cmicd_dma_chan_cos_ctrl_set(int unit, int vchan, uint32 cfg, uint32 cos_ctrl)
    792 {
    793      return (soc_cmicm_dma_drv[unit].chan_cos_ctrl_set(unit, vchan, cfg, cos_ctrl));
    794 }
    795 
    796 /*
    797  * Function:
    798  *      cmicd_dma_chan_cos_ctrl_queue_get
    799  * Purpose:
    800  *      get cos ctrl for a channel based on queue
    801  * Parameters:
    802  *      unit     - SOC unit #
    803  *      cmc      - CMC #
    804  *      chan     - chan #
    805  *      queue    - cos queue
    806  *      cos_ctrl - cos ctrl val
    807  * Returns:
    808  *      SOC_E_NONE - success
    809  *      SOC_E_XXXX - error code
    810  * Notes:
    811  */
    812 
    813 int
    814 cmicd_dma_chan_cos_ctrl_queue_get(int unit, int cmc, int chan,
    815                                   int queue, uint32 *cos_ctrl)
    816 {
    817     return (soc_cmicm_dma_drv[unit].chan_cos_ctrl_queue_get(unit, cmc, chan, queue, cos_ctrl));
    818 }
    819 
    820 /*
    821  * Function:
    822  *      cmicd_dma_chan_cos_ctrl_reg_addr_get
    823  * Purpose:
    824  *      get cos ctrl for a channel based on queue
    825  * Parameters:
    826  *      unit     - SOC unit #
    827  *      cmc      - CMC #
    828  *      chan     - chan #
    829  *      queue    - cos queue
    830  *      reg_addr - reg addr val
    831  * Returns:
    832  *      SOC_E_NONE - success
    833  *      SOC_E_XXXX - error code
    834  * Notes:
    835  */
    836 
    837 int
    838 cmicd_dma_chan_cos_ctrl_reg_addr_get(int unit, int cmc, int chan,
    839                                      int queue, uint32 *reg_addr)
    840 {
    841     return (soc_cmicm_dma_drv[unit].chan_cos_ctrl_reg_addr_get(unit, cmc, chan, queue, reg_addr));
    842 }
    843 
    844 /*
    845  * Function:
    846  *      cmicd_dma_chan_rxbuf_threshold_config
    847  * Purpose:
    848  *      appropriately set mmu back pressure
    849  * Parameters:
    850  *      unit  - SOC unit #
    851  *      vchan - channel #
    852  *      value - mmu backpressure settings
    853  *
    854  * Returns:
    855  *      SOC_E_NONE - success
    856  *      SOC_E_XXXX - error code
    857  * Notes:
    858  */
    859 
    860 int
    861 cmicd_dma_chan_rxbuf_threshold_config(int unit, int vchan, uint32 val)
    862 {
    863      return (soc_cmicm_dma_drv[unit].chan_rxbuf_threshold_cfg(unit, vchan, val));
    864 }
    865 
    866 /*
    867  * Function:
    868  *      cmicd_dma_masks_get
    869  * Purpose:
    870  *      obtain the individual big endian masks
    871  * Parameters:
    872  *      unit          - SOC unit #
    873  *      pkt_endian    - pkt endian mask
    874  *      desc_endian   - desc endian mask
    875  *      header_endian - header endian mask
    876  *
    877  * Returns:
    878  *      SOC_E_NONE - success
    879  *      SOC_E_XXXX - error code
    880  * Notes:
    881  */
    882 
    883 int
    884 cmicd_dma_masks_get(int unit, uint32 *pkt_endian, uint32 *desc_endian, uint32 *header_endian)
    885 {
    886      return (soc_cmicm_dma_drv[unit].masks_get(unit, pkt_endian, desc_endian, header_endian));
    887 }
    888 
    889 /*
    890  * Function:
    891  *      cmicd_dma_header_size_get
    892  * Purpose:
    893  *      obtain the ep to cpu header size
    894  * Parameters:
    895  *      unit     - SOC unit #
    896  *      hdr_size - return value of the ep to cpu header size
    897  *
    898  * Returns:
    899  *      SOC_E_NONE - success
    900  *      SOC_E_XXXX - error code
    901  * Notes:
    902  */
    903 
    904 int
    905 cmicd_dma_header_size_get(int unit, uint32 *hdr_size)
    906 {
    907      return (soc_cmicm_dma_drv[unit].header_size_get(unit, hdr_size));
    908 }
    909 
    910 /*
    911  * Function:
    912  *      cmicd_dma_max_rx_channels_get
    913  * Purpose:
    914  *      obtain maximum number of dma channels that can be used for BCM RX
    915  * Parameters:
    916  *      unit - SOC unit #
    917  *      max_rx_channels - maximum rx channels that can be used
    918  * Returns:
    919  *      SOC_E_NONE - success
    920  *      SOC_E_XXXX - error
    921  */
    922 
    923 static int
    924 cmicd_dma_max_rx_channels_get(int unit, uint32 *max_rx_channels)
    925 {
    926     return (soc_cmicm_dma_drv[unit].max_rx_channels_get(unit, max_rx_channels));
    927 }
    928 
    929 /*
    930  * Function:
    931  *      cmicd_dma_init
    932  * Purpose:
    933  *      Initialize the CMICD DMA for the specified SOC unit.
    934  * Parameters:
    935  *      unit - SOC unit #
    936  * Returns:
    937  *      SOC_E_NONE - success
    938  *      SOC_E_XXXX - error code
    939  * Notes:
    940  */
    941 static int
    942 cmicd_dma_init(int unit)
    943 {
    944     return (soc_cmicm_dma_drv[unit].init(unit));
    945 }
    946 
    947 /*
    948  * Function:
    949  *      cmicd_dma_pci_timeout_handle
    950  * Purpose:
    951  *      Handle the PCI timeout error.
    952  * Parameters:
    953  *      unit - SOC unit #
    954  *      sc   - SOC channel data structure pointer
    955  * Returns:
    956  *      SOC_E_NONE - success
    957  *      SOC_E_XXXX - error code
    958  * Notes:
    959  */
    960 static int
    961 cmicd_dma_pci_timeout_handle(int unit)
    962 {
    963     return (soc_cmicm_dma_drv[unit].pci_timeout_handle(unit));
    964 }
    965 
    966 
    967 
    968 /* Public Assignment Function */
    969 
    970 /*
    971  * Function:
    972  *      soc_cmicd_dma_drv_init
    973  * Purpose:
    974  *      Initialize the CMICD DMA driver for the specified SOC unit.
    975  *      Assign function pointers for SOC DMA driver interface.
    976  * Parameters:
    977  *      unit - SOC unit #
    978  *      drv  - pointer to the function vector list
    979  * Returns:
    980  *      SOC_E_NONE - success
    981  *      SOC_E_XXXX - error code
    982  * Notes:
    983  */
    984 int
    985 soc_cmicd_dma_drv_init(int unit, soc_cmic_dma_drv_t *drv)
    986 {
    987     int rv = SOC_E_NONE;
    988 
    989     drv->init                       = cmicd_dma_init;
    990     drv->ctrl_init                  = cmicd_dma_ctrl_init;
    991     drv->chan_config                = cmicd_dma_chan_config;
    992     drv->chan_dv_start              = cmicd_dma_chan_dv_start;
    993     drv->chan_start                 = cmicd_dma_chan_start;
    994     drv->chan_poll                  = cmicd_dma_chan_poll;
    995     drv->chan_abort                 = cmicd_dma_chan_abort;
    996     drv->chan_tx_purge              = cmicd_dma_chan_tx_purge;
    997     drv->chan_desc_done_intr_enable = cmicd_dma_chan_desc_done_intr_enable;
    998     drv->chan_desc_done             = cmicd_dma_chan_desc_done;
    999     drv->chan_chain_done            = cmicd_dma_chan_chain_done;
   1000     drv->chan_reload_done           = cmicd_dma_chan_reload_done;
   1001     drv->chan_counter_get           = cmicd_dma_chan_counter_get;
   1002     drv->chan_counter_clear         = cmicd_dma_chan_counter_clear;
   1003     drv->chan_cos_ctrl_get          = cmicd_dma_chan_cos_ctrl_get;
   1004     drv->chan_cos_ctrl_set          = cmicd_dma_chan_cos_ctrl_set;
   1005     drv->chan_cos_ctrl_queue_get    = cmicd_dma_chan_cos_ctrl_queue_get;
   1006     drv->chan_cos_ctrl_reg_addr_get = cmicd_dma_chan_cos_ctrl_reg_addr_get;
   1007     drv->chan_status_get            = cmicd_dma_chan_status_get;
   1008     drv->chan_status_clear          = cmicd_dma_chan_status_clear;
   1009     drv->chan_halt_get              = cmicd_dma_chan_halt_get;
   1010     drv->chan_ctrl_reg_get          = cmicd_dma_chan_ctrl_reg_get;
   1011     drv->chan_ctrl_reg_set          = cmicd_dma_chan_ctrl_reg_set;
   1012     drv->chan_rxbuf_threshold_cfg   = cmicd_dma_chan_rxbuf_threshold_config;
   1013     drv->cmc_rxbuf_threshold_cfg    = NULL;
   1014     drv->cmc_counter_get            = cmicd_dma_cmc_counter_get;
   1015     drv->cmc_counter_clear          = cmicd_dma_cmc_counter_clear;
   1016     drv->loopback_config            = NULL;
   1017     drv->masks_get                  = cmicd_dma_masks_get;
   1018     drv->header_size_get            = cmicd_dma_header_size_get;
   1019     drv->max_rx_channels_get        = cmicd_dma_max_rx_channels_get;
   1020     drv->pci_timeout_handle         = cmicd_dma_pci_timeout_handle;
   1021 
   1022     soc_cmicm_dma_drv_init(unit, &soc_cmicm_dma_drv[unit]);
   1023 
   1024     return rv;
   1025 }
   1026 
   1027 #endif /* BCM_CMICDV2_SUPPORT */