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

cmicm_dma.c (42912B)


      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:     CMICM 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 #include <soc/iproc.h>
     22 
     23 #ifdef INCLUDE_KNET
     24 #include <soc/knet.h>
     25 #endif
     26 
     27 #ifdef BCM_CMICM_SUPPORT
     28 
     29 /* Static Driver Functions */
     30 
     31 /*!
     32  * Dump registers for a channel
     33  */
     34 static void
     35 cmicm_pdma_chan_reg_dump(int unit, int vchan)
     36 {
     37     uint32 val = 0, val2 = 0;
     38     int cmc, chan;
     39 
     40     cmc = vchan / N_DMA_CHAN;
     41     chan = vchan % N_DMA_CHAN;
     42 
     43     val = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan));
     44     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
     45                 (BSL_META_U(unit,
     46                             "CMIC_CMC%d_CH%d_DMA_CTRL: 0x%08x\n"),
     47                  cmc, chan, val));
     48 
     49     val = soc_pci_read(unit, CMIC_CMCx_DMA_DESCy_OFFSET(cmc, chan));
     50     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
     51                 (BSL_META_U(unit,
     52                             "CMIC_CMC%d_DMA_DESC%d: 0x%08x\n"),
     53                  cmc, chan, val));
     54 
     55     val = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CURR_DESC_OFFSET(cmc, chan));
     56     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
     57                 (BSL_META_U(unit,
     58                             "CMIC_CMC%d_CH%d_DMA_CURR_DESC: 0x%08x\n"),
     59                  cmc, chan, val));
     60 
     61     val = soc_pci_read(unit,
     62                        CMIC_CMCx_DMA_CHy_DESC_HALT_ADDR_OFFSET(cmc, chan));
     63     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
     64                 (BSL_META_U(unit,
     65                             "CMIC_CMC%d_DMA_CH%d_DESC_HALT_ADDR: 0x%08x\n"),
     66                  cmc, chan, val));
     67 
     68     val = soc_pci_read(unit, CMIC_CMCx_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan));
     69     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
     70                 (BSL_META_U(unit,
     71                             "CMIC_CMC%d_CH%d_COS_CTRL_RX_0: 0x%08x\n"),
     72                  cmc, chan, val));
     73 
     74     val = soc_pci_read(unit, CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan));
     75     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
     76                 (BSL_META_U(unit,
     77                             "CMIC_CMC%d_CH%d_COS_CTRL_RX_1: 0x%08x\n"),
     78                  cmc, chan, val));
     79 
     80     val = soc_pci_read(unit, CMIC_CMCx_PROGRAMMABLE_COS_MASK0_OFFSET(cmc));
     81     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
     82                 (BSL_META_U(unit,
     83                             "CMIC_CMC%d_PROGRAMMABLE_COS_MASK0: 0x%08x\n"),
     84                  cmc, val));
     85 
     86     val = soc_pci_read(unit, CMIC_CMCx_PROGRAMMABLE_COS_MASK1_OFFSET(cmc));
     87     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
     88                 (BSL_META_U(unit,
     89                             "CMIC_CMC%d_PROGRAMMABLE_COS_MASK1: 0x%08x\n"),
     90                  cmc, val));
     91 
     92     val = soc_pci_read(unit, CMIC_CMCx_DMA_CHy_INTR_COAL_OFFSET(cmc, chan));
     93     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
     94                 (BSL_META_U(unit,
     95                             "CMIC_CMC%d_DMA_CH%d_INTR_COAL: 0x%08x\n"),
     96                  cmc, chan, val));
     97     switch (chan) {
     98     case 0:
     99         val = soc_pci_read(unit,
    100                            CMIC_CMCx_CH0_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc));
    101         break;
    102     case 1:
    103         val = soc_pci_read(unit,
    104                            CMIC_CMCx_CH1_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc));
    105         break;
    106     case 2:
    107         val = soc_pci_read(unit,
    108                            CMIC_CMCx_CH2_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc));
    109         break;
    110     case 3:
    111         val = soc_pci_read(unit,
    112                            CMIC_CMCx_CH3_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc));
    113         break;
    114     default:
    115         break;
    116     }
    117     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    118                 (BSL_META_U(unit,
    119                             "CMIC_CMC%d_CH%d_RXBUF_THRESHOLD_CONFIG:"
    120                             " 0x%08x\n"),
    121                  cmc, chan, val));
    122 
    123     val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc));
    124     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    125                 (BSL_META_U(unit,
    126                             "CMIC_CMC%d_DMA_STAT: 0x%08x\n"),
    127                  cmc, val));
    128 
    129     val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_HI_OFFSET(cmc));
    130     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    131                 (BSL_META_U(unit,
    132                             "CMIC_CMC%d_DMA_STAT_HI: 0x%08x\n"),
    133                  cmc, val));
    134 
    135     val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc));
    136     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    137                 (BSL_META_U(unit,
    138                             "CMIC_CMC%d_DMA_STAT_CLR: 0x%08x\n"),
    139                  cmc, val));
    140     switch (chan) {
    141     case 0:
    142         val = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH0_RXPKT_OFFSET(cmc));
    143         val2 = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH0_TXPKT_OFFSET(cmc));
    144         break;
    145     case 1:
    146         val = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH1_RXPKT_OFFSET(cmc));
    147         val2 = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH1_TXPKT_OFFSET(cmc));
    148         break;
    149     case 2:
    150         val = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH2_RXPKT_OFFSET(cmc));
    151         val2 = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH2_TXPKT_OFFSET(cmc));
    152         break;
    153     case 3:
    154         val = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH3_RXPKT_OFFSET(cmc));
    155         val2 = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH3_TXPKT_OFFSET(cmc));
    156         break;
    157     default:
    158         break;
    159     }
    160     if (chan < N_DMA_CHAN) {
    161         LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    162                     (BSL_META_U(unit,
    163                                 "CMIC_CMC%d_PKT_COUNT_CH%d_RXPKT: 0x%08x\n"),
    164                      cmc, chan, val));
    165         LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    166                     (BSL_META_U(unit,
    167                                 "CMIC_CMC%d_PKT_COUNT_CH%d_TXPKT: 0x%08x\n"),
    168                      cmc, chan, val2));
    169     }
    170 
    171     val = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc));
    172     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    173                 (BSL_META_U(unit,
    174                             "CMIC_CMC%d_IRQ_STAT0: 0x%08x\n"),
    175                  cmc, val));
    176 
    177     val = soc_pci_read(unit, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc));
    178     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    179                 (BSL_META_U(unit,
    180                             "CMIC_CMC%d_PCIE_IRQ_MASK0: 0x%08x\n"),
    181                  cmc, val));
    182 }
    183 
    184 /*
    185  * Function:
    186  *      cmicm_dma_chan_config
    187  * Purpose:
    188  *      Initialize the CMICM DMA channel for the specified SOC unit.
    189  * Parameters:
    190  *      unit - SOC unit #
    191  *      chan - channel #
    192  *      type - tx or rx
    193  *      f_intr - interrupt flags
    194  * Returns:
    195  *      SOC_E_NONE - success
    196  *      SOC_E_XXXX - error code
    197  * Notes:
    198  */
    199 static int
    200 cmicm_dma_chan_config(int unit, int vchan, dvt_t type, uint32 flags)
    201 {
    202     int             rv = SOC_E_NONE;
    203     soc_control_t   *soc = SOC_CONTROL(unit);
    204     sdc_t           *sc = &soc->soc_channels[vchan];
    205     uint32          bits;
    206     int             cmc = vchan / N_DMA_CHAN;
    207     int             chan = vchan % N_DMA_CHAN;
    208     uint32          cr;
    209 
    210     /* Define locals and turn flags into easy to use things */
    211     /*int f_mbm = (flags & SOC_DMA_F_MBM) != 0; */
    212     int f_interrupt = (flags & SOC_DMA_F_POLL) == 0;
    213     /*int f_drop = (flags & SOC_DMA_F_TX_DROP) != 0; */
    214     int f_default = (flags & SOC_DMA_F_DEFAULT) != 0;
    215     int f_desc_intr = (flags & SOC_DMA_F_INTR_ON_DESC) != 0;
    216     int init_hw = TRUE;
    217 
    218     /* Initial state of channel */
    219     sc->sc_flags = 0;                   /* Clear flags to start */
    220 
    221 #ifdef INCLUDE_KNET
    222     if (SOC_KNET_MODE(unit) && SOC_WARM_BOOT(unit) &&
    223         soc_property_get(unit, spn_WARMBOOT_KNET_SHUTDOWN_MODE, 0)) {
    224         init_hw = FALSE;
    225     }
    226 #endif
    227 
    228     if (init_hw) {
    229         (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_DESC_DONE(chan) |
    230                                             IRQ_CMCx_CHAIN_DONE(chan));
    231 
    232         cr = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan));
    233         cr &= ~PKTDMA_ENABLE; /* clearing enable will also clear CHAIN_DONE */
    234         soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan), cr);
    235 
    236         cr = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc));
    237         soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc),
    238                       (cr | DS_DESCRD_CMPLT_CLR(chan)));
    239         soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), cr);
    240     }
    241     /* Setup new mode */
    242     /* MBM Deprecated in CMICm */
    243     /* DROP_TX Deprecated in CMICm */
    244     bits = f_desc_intr ? PKTDMA_SEL_INTR_ON_DESC_OR_PKT : 0;
    245 
    246     if (type == DV_TX) {
    247         bits |= PKTDMA_DIRECTION;
    248         if (f_default) {
    249             soc->soc_dma_default_tx = sc;
    250         }
    251     } else if (type == DV_RX) {
    252         bits &= ~PKTDMA_DIRECTION;
    253         if (f_default) {
    254             soc->soc_dma_default_rx = sc;
    255         }
    256     } else if (type == DV_NONE) {
    257         f_interrupt = FALSE;            /* Force off */
    258     } else {
    259         assert(0);
    260     }
    261 
    262 #ifdef INCLUDE_KNET
    263     if (SOC_KNET_MODE(unit)) {
    264         /* Interrupt are handled by kernel */
    265         f_interrupt = FALSE;
    266     }
    267 #endif
    268 
    269     if (f_interrupt) {
    270         (void)soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_DESC_DONE(chan)
    271                                      | IRQ_CMCx_CHAIN_DONE(chan));
    272     }
    273 
    274     sc->sc_type = type;
    275     if (init_hw) {
    276         cr = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan));
    277         /* clear everything except Endianess */
    278         cr &= (PKTDMA_BIG_ENDIAN | PKTDMA_DESC_BIG_ENDIAN);
    279         cr |= bits;
    280         soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), cr);
    281     }
    282 
    283     return rv;
    284 }
    285 
    286 /*
    287  * Function:
    288  *      cmicm_dma_chan_start
    289  * Purpose:
    290  *      Start the CMICM DMA channel for the specified SOC unit.
    291  * Parameters:
    292  *      unit - SOC unit #
    293  *      sc   - SOC channel data structure pointer
    294  * Returns:
    295  *      SOC_E_NONE - success
    296  *      SOC_E_XXXX - error code
    297  * Notes:
    298  */
    299 static int
    300 cmicm_dma_chan_start(int unit, sdc_t *sc)
    301 {
    302     int             rv = SOC_E_NONE;
    303     dv_t            *dv;
    304     int             cmc = sc->sc_channel / N_DMA_CHAN;
    305     int             chan = sc->sc_channel % N_DMA_CHAN;
    306     uint32          val;
    307 
    308     if ((dv = sc->sc_dv_active = sc->sc_q) == NULL) {
    309         sc->sc_q_tail = NULL;
    310         return rv;
    311     }
    312 
    313 #ifdef INCLUDE_KNET
    314     if (SOC_KNET_MODE(unit)) {
    315         return rv;
    316     }
    317 #endif
    318 
    319     /* Set up DMA descriptor address */
    320     soc_pci_write(unit, CMIC_CMCx_DMA_DESCy_OFFSET(cmc, chan),
    321                   soc_cm_l2p(unit, sc->sc_q->dv_dcb));
    322 
    323     if (sc->sc_flags & SOC_DMA_F_CLR_CHN_DONE) {
    324         /* Clearing CMIC_CMC(0..2)_CH(0..3)_DMA_CTRL.ENABLE will
    325          * clear CMIC_CMC(0..2)_DMA_STAT.CHAIN_DONE bit.
    326          */
    327         val = soc_pci_read(unit,
    328                            CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan));
    329         val &= ~PKTDMA_ENABLE;
    330         soc_pci_write(unit,
    331                       CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan),
    332                       val);
    333     } else {
    334         sc->sc_flags |= SOC_DMA_F_CLR_CHN_DONE;
    335     }
    336 
    337     /* Start DMA */
    338     if (bsl_check(bslLayerSoc, bslSourcePacketdma, bslSeverityNormal, unit)) {
    339         cmicm_pdma_chan_reg_dump(unit ,sc->sc_channel);
    340     }
    341     val = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan));
    342     val |= PKTDMA_ENABLE;
    343 
    344     soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), val);
    345 
    346     SDK_CONFIG_MEMORY_BARRIER;
    347 
    348     if (!(sc->sc_flags & SOC_DMA_F_POLL)) {
    349         (void)soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_CHAIN_DONE(chan));
    350     }
    351 
    352     return rv;
    353 }
    354 
    355 /*
    356  * Function:
    357  *      cmicm_dma_chan_dv_start
    358  * Purpose:
    359  *      Adds DV to the ready queue for CMICM DMA for the specified SOC unit.
    360  * Parameters:
    361  *      unit - SOC unit #
    362  *      chan - channel #
    363  * Returns:
    364  *      SOC_E_NONE - success
    365  *      SOC_E_XXXX - error code
    366  * Notes:
    367  *      Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation.
    368  */
    369 static int
    370 cmicm_dma_chan_dv_start(int unit, sdc_t *sc, dv_t *dv_chain)
    371 {
    372     int rv = SOC_E_NONE;
    373 #define DV_CHAINS_MAX   9
    374     static dv_t *dcs[N_DMA_CHAN][DV_CHAINS_MAX];
    375     static int di[N_DMA_CHAN] = {0};
    376     int ch;
    377 
    378     dv_chain->dv_next = NULL;
    379     if (sc->sc_q_cnt != 0) {
    380         sc->sc_q_tail->dv_next = dv_chain;
    381     } else {
    382         sc->sc_q = dv_chain;
    383     }
    384     sc->sc_q_tail = dv_chain;
    385     sc->sc_q_cnt++;
    386 
    387     /* WAR: fix chain done interrupt lost issue caused by BCMSIM */
    388     if (SAL_BOOT_BCMSIM) {
    389         ch = sc->sc_channel % N_DMA_CHAN;
    390         dcs[ch][di[ch]] = dv_chain;
    391         di[ch] = (di[ch] + 1) % DV_CHAINS_MAX;
    392         if (sc->sc_dv_active == NULL && sc->sc_q_cnt > 1) {
    393             sc->sc_q = dcs[ch][(di[ch] - sc->sc_q_cnt + 1 + DV_CHAINS_MAX) % DV_CHAINS_MAX];
    394             sc->sc_q_cnt--;
    395             return cmicm_dma_chan_start(unit, sc);
    396         }
    397     }
    398 
    399     if (sc->sc_q_cnt == 1) {    /* Start DMA if channel not active */
    400         rv = cmicm_dma_chan_start(unit, sc);
    401     }
    402 
    403     return rv;
    404 }
    405 
    406 /*
    407  * Function:
    408  *      cmicm_dma_chan_poll
    409  * Purpose:
    410  *      Poll the CMICM DMA channel for the specified SOC unit.
    411  * Parameters:
    412  *      unit - SOC unit #
    413  *      chan - channel #
    414  *      type - poll type (chain done or desc done)
    415  *      detected - poll result pointer to be updated
    416  * Returns:
    417  *      SOC_E_NONE - success
    418  *      SOC_E_XXXX - error code
    419  * Notes:
    420  *      Assumes that SOC_DMA_LOCK is held when called.
    421  */
    422 int
    423 cmicm_dma_chan_poll(int unit,
    424                     int vchan,
    425                     soc_dma_poll_type_t type,
    426                     int * detected)
    427 {
    428     int            rv = SOC_E_NONE;
    429     int            cmc = vchan / N_DMA_CHAN;
    430     int            chan = vchan % N_DMA_CHAN;
    431 
    432     switch (type) {
    433     case SOC_DMA_POLL_DESC_DONE:
    434         *detected = ( soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc))
    435                      & DS_CMCx_DMA_DESC_DONE(chan) );
    436         break;
    437     case SOC_DMA_POLL_CHAIN_DONE:
    438         *detected = ( soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc))
    439                      & DS_CMCx_DMA_CHAIN_DONE(chan) );
    440         break;
    441     default:
    442         break;
    443     }
    444 
    445     return rv;
    446 }
    447 
    448 /*
    449  * Function:
    450  *      cmicm_dma_chan_abort
    451  * Purpose:
    452  *      Initialize the CMICM DMA channel for the specified SOC unit.
    453  * Parameters:
    454  *      unit - SOC unit #
    455  *      chan - channel #
    456  *      type - tx or rx
    457  *      f_intr - interrupt flags
    458  * Returns:
    459  *      SOC_E_NONE   - Success
    460  *      SOC_E_TIMEOUT - failed (Timeout)
    461  * Notes:
    462  *      Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation.
    463  */
    464 static int
    465 cmicm_dma_chan_abort(int unit, int vchan)
    466 {
    467     int             rv = SOC_E_NONE;
    468 
    469     int             cmc = vchan / N_DMA_CHAN;
    470     int             chan = vchan % N_DMA_CHAN;
    471     int		        to;
    472     uint32          ctrl;
    473     uint32          val;
    474 
    475     if ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc))
    476          & DS_CMCx_DMA_ACTIVE(chan)) != 0) {
    477         ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan));
    478         ctrl |= PKTDMA_ENABLE;
    479         soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), ctrl);
    480         soc_pci_write(unit,
    481                       CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan),
    482                       ctrl | PKTDMA_ABORT);
    483         SDK_CONFIG_MEMORY_BARRIER;
    484 
    485         to = soc_property_get(unit, spn_PDMA_TIMEOUT_USEC, 500000);
    486         while ((to >= 0) &&
    487                ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc))
    488                  & DS_CMCx_DMA_ACTIVE(chan)) != 0)) {
    489             sal_udelay(1000);
    490             to -= 1000;
    491         }
    492         if ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc))
    493              & DS_CMCx_DMA_ACTIVE(chan)) != 0) {
    494             LOG_ERROR(BSL_LS_SOC_PACKETDMA,
    495                       (BSL_META_U(unit,
    496                                   "soc_dma_abort_channel unit %d: "
    497                                   "channel %d abort timeout\n"),
    498                        unit, chan));
    499             rv = SOC_E_TIMEOUT;
    500             if (SOC_WARM_BOOT(unit)) {
    501                 return rv;
    502             }
    503         }
    504     }
    505     ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan));
    506     /* Clearing enable will also clear CHAIN_DONE */
    507     ctrl &= ~(PKTDMA_ENABLE|PKTDMA_ABORT);
    508     soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), ctrl);
    509 
    510     val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc));
    511     soc_pci_write(unit,
    512                   CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc),
    513                   (val | DS_DESCRD_CMPLT_CLR(chan)));
    514     soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), val);
    515     SDK_CONFIG_MEMORY_BARRIER;
    516 
    517     return rv;
    518 }
    519 
    520 /*
    521  * Function:
    522  *      cmicm_dma_chan_desc_done
    523  * Purpose:
    524  *      Clears desc done on the CMICM DMA channel for the specified SOC unit.
    525  * Parameters:
    526  *      unit - SOC unit #
    527  *      chan - channel #
    528  * Returns:
    529  *      SOC_E_NONE - success
    530  *      SOC_E_XXXX - error code
    531  * Notes:
    532  *      INTERRUPT LEVEL ROUTINE.
    533  */
    534 static int
    535 cmicm_dma_chan_desc_done(int unit, int vchan)
    536 {
    537     int             rv = SOC_E_NONE;
    538     int             cmc = vchan / N_DMA_CHAN;
    539     int             chan = vchan % N_DMA_CHAN;
    540     uint32          val;
    541 
    542     /* Do we still need to generate an edge for CMICm and newer devices? */
    543     val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc));
    544     soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc),
    545                   (val | DS_DESCRD_CMPLT_CLR(chan)));
    546     soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), val);
    547 
    548     /* Flush posted writes from PCI bridge */
    549     (void)soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc));
    550 
    551     return rv;
    552 }
    553 
    554 /*
    555  * Function:
    556  *      cmicm_dma_ctrl_init
    557  * Purpose:
    558  *      Initialize the CMICM DMA Control to a known good state for
    559  *      the specified SOC unit.
    560  * Parameters:
    561  *      unit - SOC unit #
    562  * Returns:
    563  *      SOC_E_NONE - success
    564  *      SOC_E_XXXX - error code
    565  * Notes:
    566  */
    567 
    568 static int
    569 cmicm_dma_ctrl_init(int unit)
    570 {
    571     int             rv = SOC_E_NONE;
    572     int             cmc;
    573     uint32          val, chan, vchan;
    574 
    575     for(vchan=0; vchan < SOC_DCHAN_NUM(unit); vchan++) {
    576 	cmc = vchan / N_DMA_CHAN;
    577 	chan = vchan % N_DMA_CHAN;
    578         val = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan));
    579         val &= (PKTDMA_BIG_ENDIAN | PKTDMA_DESC_BIG_ENDIAN);
    580         soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), val);
    581     }
    582 
    583     /* Set to Legacy Mode */
    584     SOC_DMA_MODE(unit) = SOC_DMA_MODE_CHAINED;
    585 
    586     /* 
    587      * This has to be done only once after both CMIC and EP blocks
    588      * are out of reset.
    589      */
    590     soc_pci_write(unit, CMIC_RXBUF_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 0);
    591     soc_pci_write(unit, CMIC_RXBUF_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 1);
    592 
    593     return rv;
    594 }
    595 
    596 /*
    597  * Function:
    598  *      cmicm_dma_init
    599  * Purpose:
    600  *      Initialize the CMICM DMA for the specified SOC unit.
    601  * Parameters:
    602  *      unit - SOC unit #
    603  * Returns:
    604  *      SOC_E_NONE - success
    605  *      SOC_E_XXXX - error code
    606  * Notes:
    607  */
    608 
    609 static int
    610 cmicm_dma_init(int unit)
    611 {
    612     int rv = SOC_E_NONE;
    613 #ifdef BCM_TOMAHAWK_SUPPORT
    614 
    615     int cmc = 0;
    616     uint32 mask;
    617 
    618     /* Enable PCI completion time out recovery only for Tomahawk */
    619     if (SOC_IS_TOMAHAWK(unit)) {
    620         /*Clear all PAXB interrupts */
    621         (void)READ_PAXB_0_PAXB_INTR_CLEARr(unit, &mask);
    622         mask = ~(uint32)0x0;
    623         (void)WRITE_PAXB_0_PAXB_INTR_CLEARr(unit, mask);
    624 
    625         /* Only enable PCIE_CMPL_TIMEOUT_INTR */
    626         mask = PCIE_CMPL_TIMEOUT_INTR_MASK;
    627         (void)WRITE_PAXB_0_PAXB_INTR_ENr(unit, mask);
    628 
    629         /* Enabling PCIe completion timeout interrupt */
    630         for(cmc = 0; cmc < SOC_PCI_CMCS_NUM(unit); cmc++) {
    631             soc_cmicm_cmcx_intr2_enable(unit, cmc, IRQ_CMCx_PCI_CMPL_MASK);
    632         }
    633     }
    634 #endif
    635     return rv;
    636 }
    637 
    638 /*
    639  * Function:
    640  *      cmicd_dma_pci_timeout_handle
    641  * Purpose:
    642  *      Handle the PCI timeout error.
    643  * Parameters:
    644  *      unit - SOC unit #
    645  *      sc   - SOC channel data structure pointer
    646  * Returns:
    647  *      SOC_E_NONE - success
    648  *      SOC_E_XXXX - error code
    649  * Notes:
    650  */
    651 static int
    652 cmicm_dma_pci_timeout_handle(int unit)
    653 {
    654     int rv = SOC_E_NONE;
    655 #ifdef BCM_TOMAHAWK_SUPPORT
    656     int cmc = 0;
    657     int chan;
    658     uint32 stat, stat_paxb, clr_pxab;
    659     uint32 val;
    660     soc_control_t *soc = SOC_CONTROL(unit);
    661     sdc_t *sc;
    662     dcb_t *dcb;
    663     int intr_clr = 0;
    664 
    665     if (SOC_IS_TOMAHAWK(unit)) {
    666         (void)READ_PAXB_0_PAXB_INTR_STATUSr(unit, &stat_paxb);
    667         /* Check CMIC_CMC0_IRQ_STAT2.bit[19] is set */
    668         for (cmc = 0; cmc < SOC_PCI_CMCS_NUM(unit); cmc++) {
    669             stat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc));
    670             if (stat & IRQ_CMCx_PCI_CMPL_MASK) {
    671                 /* Check if PAXB PCI complete timeout bit is set */
    672                 if (stat_paxb & PCIE_CMPL_TIMEOUT_INTR_MASK) {
    673                     /* Check if address decode err is set. */
    674                     stat = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc));
    675                     for (chan = 0; chan < N_DMA_CHAN; chan++) {
    676                         /* If set, issue s/w abort to that channel */
    677                         if (DS_CMCx_DMA_ADDR_DECODE_ERR(chan) & stat) {
    678                             int vchan = cmc * N_DMA_CHAN + chan;
    679                             rv = cmicm_dma_chan_abort(unit, vchan);
    680                             /*Clear PCIe completion timeout interrupt, before starting DMA */
    681                             (void)READ_PAXB_0_PAXB_INTR_CLEARr(unit, &clr_pxab);
    682                             clr_pxab |= PCIE_CMPL_TIMEOUT_INTR_MASK;
    683                             (void)WRITE_PAXB_0_PAXB_INTR_CLEARr(unit, clr_pxab);
    684                             soc->stat.pci_cmpl_timeout++;
    685                             intr_clr = 1;
    686                             sc = &soc->soc_channels[vchan];
    687                             if (sc->sc_dv_active->dv_op == DV_RX) {
    688                                 dcb = SOC_DCB_IDX2PTR(unit, sc->sc_dv_active->dv_dcb,
    689                                           sc->sc_dv_active->dv_dcnt);
    690                                 soc_pci_write(unit,
    691                                     CMIC_CMCx_DMA_DESCy_OFFSET(cmc, chan),
    692                                     soc_cm_l2p(unit, dcb));
    693                             }
    694                             val = soc_pci_read(unit,
    695                                       CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan));
    696                             val |= PKTDMA_ENABLE;
    697                             soc_pci_write(unit,
    698                                 CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), val);
    699                         }
    700                     }
    701                 }
    702             }
    703         }
    704         /* In case interrupt is not handled print status registers , clear PCI timeout interrupt*/
    705         if (!intr_clr) {
    706             LOG_ERROR(BSL_LS_SOC_PACKETDMA,
    707                           (BSL_META_U(unit, "Unhandled interrupt\n")));
    708             (void)READ_PAXB_0_PAXB_INTR_STATUSr(unit, &stat);
    709             LOG_ERROR(BSL_LS_SOC_PACKETDMA,
    710                           (BSL_META_U(unit, "PAXB_0_PAXB_INTR_STATUS = 0x%x\n"), stat));
    711             for (cmc = 0; cmc < SOC_PCI_CMCS_NUM(unit); cmc++) {
    712                 stat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc));
    713                 LOG_ERROR(BSL_LS_SOC_PACKETDMA,
    714                           (BSL_META_U(unit, "CMIC_CMCx_IRQ_STAT2_OFFSET[%d] = 0x%x\n"),
    715                                cmc, stat));
    716                 stat = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc));
    717                 LOG_ERROR(BSL_LS_SOC_PACKETDMA,
    718                           (BSL_META_U(unit, "CMIC_CMCx_DMA_STAT_OFFSET[%d] = 0x%x\n"),
    719                                cmc, stat));
    720             }
    721             /* Clear PCIe completion timeout interrupt */
    722             (void)READ_PAXB_0_PAXB_INTR_CLEARr(unit, &clr_pxab);
    723             clr_pxab |= PCIE_CMPL_TIMEOUT_INTR_MASK;
    724             (void)WRITE_PAXB_0_PAXB_INTR_CLEARr(unit, clr_pxab);
    725             soc->stat.pci_cmpl_timeout++;
    726         }
    727     }
    728 #endif
    729     return rv;
    730 }
    731 
    732 /*
    733  * Function:
    734  *      cmicm_dma_chan_chain_done
    735  * Purpose:
    736  *      on the CMICM DMA channel for the specified SOC unit.
    737  * Parameters:
    738  *      unit - SOC unit #
    739  *      chan - channel #
    740  *      mitigation - >0 = interrupt mitigation on
    741  * Returns:
    742  *      SOC_E_NONE - success
    743  *      SOC_E_XXXX - error code
    744  * Notes:
    745  *      INTERRUPT LEVEL ROUTINE.
    746  */
    747 static int
    748 cmicm_dma_chan_chain_done(int unit, int vchan, int mitigation)
    749 {
    750     int             rv = SOC_E_NONE;
    751     int             cmc = vchan / N_DMA_CHAN;
    752     int             chan = vchan % N_DMA_CHAN;
    753     uint32          val;
    754 
    755     if (mitigation) {
    756         (void)soc_cmicm_cmcx_intr0_disable(unit, cmc,
    757                                       IRQ_CMCx_DESC_DONE(chan)
    758                                       | IRQ_CMCx_CHAIN_DONE(chan));
    759     } else {
    760         (void)soc_cmicm_cmcx_intr0_disable(unit,
    761                                            cmc, IRQ_CMCx_CHAIN_DONE(chan));
    762     }
    763     /* Enable DMA */
    764     val = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan));
    765     val &= ~PKTDMA_ENABLE;
    766     soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan), val);
    767 
    768     /* Clear the descriptor read complete stat bit */
    769     val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc));
    770     soc_pci_write(unit,
    771                   CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc),
    772                   (val | DS_DESCRD_CMPLT_CLR(chan)));
    773     soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), val);
    774 
    775     /* Flush posted writes from PCI bridge */
    776     (void)soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc));
    777 
    778     return rv;
    779 }
    780 
    781 /*
    782  * Function:
    783  *      cmicm_dma_chan_counter_get
    784  * Purpose:
    785  *      Obtain tx and rx counter values
    786  * Parameters:
    787  *      unit    - SOC unit #
    788  *      vchan   - SOC virtual channel number
    789  * Returns:
    790  *      SOC_E_NONE - success
    791  * Notes:
    792  */
    793 static int
    794 cmicm_dma_chan_counter_get(int unit, int vchan, uint32 *tx_pkt, uint32 *rx_pkt)
    795 {
    796     int rv   = SOC_E_NONE;
    797     int cmc  = vchan / N_DMA_CHAN;
    798     int chan = vchan % N_DMA_CHAN;
    799 
    800     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    801                       (BSL_META_U(unit,
    802                                   "channel counter get\n")));
    803 
    804     *tx_pkt = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CHy_TXPKT_OFFSET(cmc, chan));
    805     *rx_pkt = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CHy_RXPKT_OFFSET(cmc, chan));
    806 
    807     return rv;
    808 }
    809 
    810 /*
    811  * Function:
    812  *      cmicm_dma_chan_counter_clear
    813  * Purpose:
    814  *      clear tx and rx counter values
    815  * Parameters:
    816  *      unit    - SOC unit #
    817  *      vchan   - SOC virtual channel number
    818  *      mask    - to clear the appopriate counter
    819  * Returns:
    820  *      SOC_E_NONE - success
    821  * Notes:
    822  */
    823 static int
    824 cmicm_dma_chan_counter_clear(int unit, int vchan, uint32 mask)
    825 {
    826     int rv   = SOC_E_NONE;
    827     int cmc  = vchan / N_DMA_CHAN;
    828     int chan = vchan % N_DMA_CHAN;
    829 
    830     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    831                       (BSL_META_U(unit,
    832                                   "channel counter clear\n")));
    833 
    834     if (mask & 0x1) {
    835         soc_pci_write(unit, CMIC_CMCx_PKT_COUNT_CHy_TXPKT_OFFSET(cmc, chan), 0);
    836     }
    837 
    838     if (mask & 0x2) {
    839         soc_pci_write(unit, CMIC_CMCx_PKT_COUNT_CHy_RXPKT_OFFSET(cmc, chan), 0);
    840     }
    841 
    842     return rv;
    843 }
    844 
    845 /*
    846  * Function:
    847  *      cmicm_dma_cmc_counter_get
    848  * Purpose:
    849  *      Obtain tx and rx counter values
    850  * Parameters:
    851  *      unit    - SOC unit #
    852  *      cmc     - cmc number
    853  * Returns:
    854  *      SOC_E_NONE - success
    855  * Notes:
    856  */
    857 static int
    858 cmicm_dma_cmc_counter_get(int unit, int cmc, uint32 *tx_pkt, uint32 *rx_pkt)
    859 {
    860     int rv   = SOC_E_NONE;
    861 
    862     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    863                       (BSL_META_U(unit,
    864                                   "cmc counter get\n")));
    865 
    866     *tx_pkt = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_TXPKT_OFFSET(cmc));
    867     *rx_pkt = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_RXPKT_OFFSET(cmc));
    868 
    869     return rv;
    870 }
    871 
    872 /*
    873  * Function:
    874  *      cmicm_dma_cmc_counter_clear
    875  * Purpose:
    876  *      clear tx and rx counter values
    877  * Parameters:
    878  *      unit    - SOC unit #
    879  *      cmc     - cmc number
    880  *      mask    - to clear the appopriate counter
    881  * Returns:
    882  *      SOC_E_NONE - success
    883  * Notes:
    884  */
    885 static int
    886 cmicm_dma_cmc_counter_clear(int unit, int cmc, uint32 mask)
    887 {
    888     int rv   = SOC_E_NONE;
    889 
    890     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    891                       (BSL_META_U(unit,
    892                                   "cmc counter clear\n")));
    893 
    894     if (mask & 0x1) {
    895         soc_pci_write(unit, CMIC_CMCx_PKT_COUNT_TXPKT_OFFSET(cmc), 0);
    896     }
    897 
    898     if (mask & 0x2) {
    899         soc_pci_write(unit, CMIC_CMCx_PKT_COUNT_RXPKT_OFFSET(cmc), 0);
    900     }
    901 
    902     return rv;
    903 }
    904 
    905 /*
    906  * Function:
    907  *      cmicm_dma_chan_cos_ctrl_get
    908  * Purpose:
    909  *      get cos ctrl for a channel
    910  * Parameters:
    911  *      unit - SOC unit #
    912  *      cfg  - to choose appropriate register
    913  * Returns:
    914  *      SOC_E_NONE - success
    915  *      SOC_E_XXXX - error code
    916  * Notes:
    917  */
    918 
    919 int
    920 cmicm_dma_chan_cos_ctrl_get(int unit, int vchan, uint32 cfg, uint32 *cos_ctrl)
    921 {
    922     int    rv  = SOC_E_NONE;
    923     int cmc  = vchan / N_DMA_CHAN;
    924     int chan = vchan % N_DMA_CHAN;
    925 
    926     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    927                       (BSL_META_U(unit,
    928                                   "channel cos ctrl get\n")));
    929 
    930     if (cfg & 0x1) {
    931         *cos_ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan));
    932     } else if (cfg & 0x2) {
    933         *cos_ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan));
    934     }
    935 
    936     return rv;
    937 }
    938 
    939 /*
    940  * Function:
    941  *      cmicm_dma_chan_cos_ctrl_set
    942  * Purpose:
    943  *      get cos ctrl for a channel
    944  * Parameters:
    945  *      unit - SOC unit #
    946  *      cfg  - to choose appropriate register
    947  * Returns:
    948  *      SOC_E_NONE - success
    949  *      SOC_E_XXXX - error code
    950  * Notes:
    951  */
    952 
    953 int
    954 cmicm_dma_chan_cos_ctrl_set(int unit, int vchan, uint32 cfg, uint32 cos_ctrl)
    955 {
    956     int    rv  = SOC_E_NONE;
    957     int cmc  = vchan / N_DMA_CHAN;
    958     int chan = vchan % N_DMA_CHAN;
    959 
    960     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    961                       (BSL_META_U(unit,
    962                                   "channel cos ctrl set\n")));
    963 
    964     if (cfg & 0x1) {
    965         soc_pci_write(unit,
    966                       CMIC_CMCx_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan),
    967                       cos_ctrl);
    968     } else if (cfg & 0x2) {
    969         soc_pci_write(unit,
    970                       CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan),
    971                       cos_ctrl);
    972     }
    973 
    974     return rv;
    975 }
    976 
    977 /*
    978  * Function:
    979  *      cmicm_dma_chan_cos_ctrl_queue_get
    980  * Purpose:
    981  *      get cos ctrl for a channel based on queue
    982  * Parameters:
    983  *      unit     - SOC unit #
    984  *      cmc      - CMC #
    985  *      chan     - chan #
    986  *      queue    - cos queue
    987  *      cos_ctrl - cos ctrl val
    988  * Returns:
    989  *      SOC_E_NONE - success
    990  *      SOC_E_XXXX - error code
    991  * Notes:
    992  */
    993 
    994 int
    995 cmicm_dma_chan_cos_ctrl_queue_get(int unit, int cmc, int chan,
    996                                   int queue, uint32 *cos_ctrl)
    997 {
    998     int rv   = SOC_E_NONE;
    999     uint32 reg_addr;
   1000 
   1001     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1002                       (BSL_META_U(unit,
   1003                                   "channel cos ctrl queue get\n")));
   1004 
   1005     reg_addr = (queue < 32) ?
   1006                     CMIC_CMCx_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan) :
   1007                     CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan);
   1008 
   1009     *cos_ctrl = soc_pci_read(unit, reg_addr);
   1010 
   1011     return rv;
   1012 }
   1013 
   1014 /*
   1015  * Function:
   1016  *      cmicm_dma_chan_cos_ctrl_reg_addr_get
   1017  * Purpose:
   1018  *      get cos ctrl reg addr for a channel based on queue
   1019  * Parameters:
   1020  *      unit     - SOC unit #
   1021  *      cmc      - CMC #
   1022  *      chan     - chan #
   1023  *      queue    - cos queue
   1024  *      reg addr - reg addr val
   1025  * Returns:
   1026  *      SOC_E_NONE - success
   1027  *      SOC_E_XXXX - error code
   1028  * Notes:
   1029  */
   1030 
   1031 int
   1032 cmicm_dma_chan_cos_ctrl_reg_addr_get(int unit, int cmc, int chan,
   1033                                   int queue, uint32 *reg_addr)
   1034 {
   1035     int rv   = SOC_E_NONE;
   1036 
   1037     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1038                       (BSL_META_U(unit,
   1039                                   "channel cos ctrl reg addr get\n")));
   1040 
   1041     *reg_addr = (queue < 32) ?
   1042                     CMIC_CMCx_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan) :
   1043                     CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan);
   1044 
   1045     return rv;
   1046 }
   1047 
   1048 /*
   1049  * Function:
   1050  *      cmicm_dma_chan_status_get
   1051  * Purpose:
   1052  *      get channel status
   1053  * Parameters:
   1054  *      unit - SOC unit #
   1055  *      vchan - channel #
   1056  *      status - channel status
   1057  *
   1058  * Returns:
   1059  *      SOC_E_NONE - success
   1060  *      SOC_E_XXXX - error code
   1061  * Notes:
   1062  */
   1063 
   1064 int
   1065 cmicm_dma_chan_status_get(int unit, int vchan, uint32 mask, int *status)
   1066 {
   1067     int    rv  = SOC_E_NONE;
   1068     int cmc  = vchan / N_DMA_CHAN;
   1069 
   1070     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1071                       (BSL_META_U(unit,
   1072                                   "channel status get\n")));
   1073 
   1074     *status = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc));
   1075 
   1076     return rv;
   1077 }
   1078 
   1079 /*
   1080  * Function:
   1081  *      cmicm_dma_chan_status_clear
   1082  * Purpose:
   1083  *      clear channel status
   1084  * Parameters:
   1085  *      unit - SOC unit #
   1086  *      vchan - channel #
   1087  *
   1088  * Returns:
   1089  *      SOC_E_NONE - success
   1090  *      SOC_E_XXXX - error code
   1091  * Notes:
   1092  */
   1093 
   1094 int
   1095 cmicm_dma_chan_status_clear(int unit, int vchan)
   1096 {
   1097     int    rv  = SOC_E_NONE;
   1098     int cmc  = vchan / N_DMA_CHAN;
   1099 
   1100     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1101                       (BSL_META_U(unit,
   1102                                   "channel status clear\n")));
   1103 
   1104     soc_pci_write(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc), 0x0);
   1105 
   1106     return rv;
   1107 }
   1108 
   1109 /*
   1110  * Function:
   1111  *      cmicm_dma_chan_ctrl_reg_get
   1112  * Purpose:
   1113  *      get channel ctrl reg value
   1114  * Parameters:
   1115  *      unit - SOC unit #
   1116  *      vchan - channel #
   1117  *      value - channel ctrl reg value
   1118  *
   1119  * Returns:
   1120  *      SOC_E_NONE - success
   1121  *      SOC_E_XXXX - error code
   1122  * Notes:
   1123  */
   1124 
   1125 int
   1126 cmicm_dma_chan_ctrl_reg_get(int unit, int vchan, uint32 *val)
   1127 {
   1128     int    rv  = SOC_E_NONE;
   1129     int cmc  = vchan / N_DMA_CHAN;
   1130     int chan = vchan % N_DMA_CHAN;
   1131 
   1132     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1133                       (BSL_META_U(unit,
   1134                                   "channel ctrl reg get\n")));
   1135 
   1136     *val = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan));
   1137 
   1138     return rv;
   1139 }
   1140 
   1141 /*
   1142  * Function:
   1143  *      cmicm_dma_chan_ctrl_reg_set
   1144  * Purpose:
   1145  *      set channel ctrl reg
   1146  * Parameters:
   1147  *      unit - SOC unit #
   1148  *      vchan - channel #
   1149  *      value - channel ctrl reg value to set
   1150  *
   1151  * Returns:
   1152  *      SOC_E_NONE - success
   1153  *      SOC_E_XXXX - error code
   1154  * Notes:
   1155  */
   1156 
   1157 int
   1158 cmicm_dma_chan_ctrl_reg_set(int unit, int vchan, uint32 val)
   1159 {
   1160     int    rv  = SOC_E_NONE;
   1161     int cmc  = vchan / N_DMA_CHAN;
   1162     int chan = vchan % N_DMA_CHAN;
   1163 
   1164     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1165                       (BSL_META_U(unit,
   1166                                   "channel ctrl reg get\n")));
   1167 
   1168     soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), val);
   1169 
   1170     return rv;
   1171 }
   1172 
   1173 /*
   1174  * Function:
   1175  *      cmicm_dma_chan_rxbuf_threshold_config
   1176  * Purpose:
   1177  *      appropriately set mmu back pressure
   1178  * Parameters:
   1179  *      unit - SOC unit #
   1180  *      vchan - channel #
   1181  *      value - mmu backpressure settings
   1182  *
   1183  * Returns:
   1184  *      SOC_E_NONE - success
   1185  *      SOC_E_XXXX - error code
   1186  * Notes:
   1187  */
   1188 
   1189 int
   1190 cmicm_dma_chan_rxbuf_threshold_config(int unit, int vchan, uint32 val)
   1191 {
   1192     int    rv  = SOC_E_NONE;
   1193     int cmc  = vchan / N_DMA_CHAN;
   1194     int chan = vchan % N_DMA_CHAN;
   1195 
   1196     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1197                       (BSL_META_U(unit,
   1198                                   "channel rxbuf threshold config\n")));
   1199 
   1200     soc_pci_write(unit, CMIC_CMCx_CHy_RXBUF_THRESHOLD_CONFIG(cmc, chan), val);
   1201 
   1202     return rv;
   1203 }
   1204 
   1205 /*
   1206  * Function:
   1207  *      cmicm_dma_chan_tx_purge
   1208  * Purpose:
   1209  *      Purge partial pkt left in the pipeline from TX DMA abort.
   1210  * Parameters:
   1211  *      unit - SOC unit #
   1212  *      chan - channel #
   1213  * Returns:
   1214  *      SOC_E_NONE   - Success
   1215  *      SOC_E_TIMEOUT - failed (Timeout)
   1216  * Notes:
   1217  *      Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation.
   1218  */
   1219 static int
   1220 cmicm_dma_chan_tx_purge(int unit, int vchan, dv_t *dv)
   1221 {
   1222     int             rv = SOC_E_NONE;
   1223     int             cmc = vchan / N_DMA_CHAN;
   1224     int             chan = vchan % N_DMA_CHAN;
   1225     sal_usecs_t     start_time;
   1226     int             diff_time;
   1227     uint32          dma_stat;
   1228     uint32          dma_state;
   1229 
   1230     soc_pci_write(unit,
   1231                   CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan),
   1232                   soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan))
   1233                   | PKTDMA_DIRECTION);
   1234     soc_pci_write(unit,
   1235                   CMIC_CMCx_DMA_DESCy_OFFSET(cmc, chan),
   1236                   soc_cm_l2p(unit, dv->dv_dcb));
   1237     /* Start DMA */
   1238     soc_pci_write(unit,
   1239                   CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan),
   1240                   soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc ,chan))
   1241                   | PKTDMA_ENABLE);
   1242 
   1243     start_time = sal_time_usecs();
   1244     diff_time = 0;
   1245     dma_state = (DS_CMCx_DMA_DESC_DONE(chan) | DS_CMCx_DMA_CHAIN_DONE(chan));
   1246     do {
   1247         sal_udelay(SAL_BOOT_SIMULATION ? 1000 : 10);
   1248         dma_stat = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)) &
   1249             (DS_CMCx_DMA_DESC_DONE(chan) | DS_CMCx_DMA_CHAIN_DONE(chan));
   1250         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
   1251         if (diff_time > DMA_ABORT_TIMEOUT) { /* 10 Sec(QT)/10 msec */
   1252             rv = SOC_E_TIMEOUT;
   1253             break;
   1254         } else if (diff_time < 0) {
   1255             /* Restart in case system time changed */
   1256             start_time = sal_time_usecs();
   1257         }
   1258     } while (dma_stat != dma_state);
   1259     /* Clear CHAIN_DONE and DESC_DONE */
   1260     soc_pci_write(unit,
   1261                   CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan),
   1262                   soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan))
   1263                   & ~PKTDMA_ENABLE);
   1264 
   1265     dma_stat = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc));
   1266     soc_pci_write(unit,
   1267                   CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc),
   1268                   (dma_stat | DS_DESCRD_CMPLT_CLR(chan)));
   1269     soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), dma_stat);
   1270     return rv;
   1271 }
   1272 
   1273 /*
   1274  * Function:
   1275  *      cmicm_dma_chan_desc_done_intr_enable
   1276  * Purpose:
   1277  *      Clears desc done on the CMICM DMA channel for the specified SOC unit.
   1278  * Parameters:
   1279  *      unit - SOC unit #
   1280  *      chan - channel #
   1281  * Returns:
   1282  *      SOC_E_NONE - success
   1283  *      SOC_E_XXXX - error code
   1284  * Notes:
   1285  *      INTERRUPT LEVEL ROUTINE.
   1286  */
   1287 static int
   1288 cmicm_dma_chan_desc_done_intr_enable(int unit, int vchan)
   1289 {
   1290     int rv = SOC_E_NONE;
   1291     int cmc = vchan / N_DMA_CHAN;
   1292     int chan = vchan % N_DMA_CHAN;
   1293 
   1294     (void)soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_DESC_DONE(chan));
   1295     return rv;
   1296 }
   1297 
   1298 /*
   1299  * Function:
   1300  *      cmicm_dma_masks_get
   1301  * Purpose:
   1302  *      obtain the individual big endian masks
   1303  * Parameters:
   1304  *      unit          - SOC unit #
   1305  *      pkt_endian    - pkt endian mask
   1306  *      desc_endian   - desc endian mask
   1307  *      header_endian - header endian mask
   1308  *
   1309  * Returns:
   1310  *      SOC_E_NONE - success
   1311  *      SOC_E_XXXX - error code
   1312  * Notes:
   1313  */
   1314 
   1315 int
   1316 cmicm_dma_masks_get(int unit, uint32 *pkt_endian, uint32 *desc_endian, uint32 *header_endian)
   1317 {
   1318     int rv = SOC_E_NONE;
   1319 
   1320     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1321                       (BSL_META_U(unit,
   1322                                   "cmicm dma get masks\n")));
   1323 
   1324     *pkt_endian    = PKTDMA_BIG_ENDIAN;
   1325     *desc_endian   = PKTDMA_DESC_BIG_ENDIAN;
   1326 
   1327     return rv;	
   1328 }
   1329 
   1330 /*
   1331  * Function:
   1332  *      cmicm_dma_header_size_get
   1333  * Purpose:
   1334  *      obtain the ep to cpu header size
   1335  * Parameters:
   1336  *      unit     - SOC unit #
   1337  *      hdr_size - return value of the ep to cpu header size
   1338  *
   1339  * Returns:
   1340  *      SOC_E_NONE - success
   1341  *      SOC_E_XXXX - error code
   1342  * Notes:
   1343  */
   1344 
   1345 int
   1346 cmicm_dma_header_size_get(int unit, uint32 *hdr_size)
   1347 {
   1348     int rv = SOC_E_NONE;
   1349 
   1350     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1351                       (BSL_META_U(unit,
   1352                                   "cmicm dma get header size\n")));
   1353 
   1354     *hdr_size = 0;
   1355 
   1356     return rv;
   1357 }
   1358 
   1359 /*
   1360  * Function:
   1361  *      cmicm_dma_max_rx_channels_get
   1362  * Purpose:
   1363  *      obtain maximum number of dma channels that can be used for BCM RX
   1364  * Parameters:
   1365  *      unit - SOC unit #
   1366  *      max_rx_channels - maximum rx channels that can be used
   1367  * Returns:
   1368  *      SOC_E_NONE - success
   1369  *      SOC_E_XXXX - error
   1370  */
   1371 
   1372 static int
   1373 cmicm_dma_max_rx_channels_get(int unit, uint32 *max_rx_channels)
   1374 {
   1375     int rv = SOC_E_NONE;
   1376 
   1377     /*
   1378      * Only CMC0 is used for BCM RX hence we can have
   1379      * N_DMA_CHAN number of maximum rx channels
   1380      */
   1381 
   1382     *max_rx_channels = N_DMA_CHAN;
   1383 
   1384     return rv;
   1385 }
   1386 
   1387 /* Public Functions */
   1388 
   1389 /*
   1390  * Function:
   1391  *      soc_cmicm_dma_drv_init
   1392  * Purpose:
   1393  *      Initialize the CMICM DMA driver for the specified SOC unit.
   1394  *      Assign function pointers for SOC DMA driver interface.
   1395  * Parameters:
   1396  *      unit - SOC unit #
   1397  *      drv  - pointer to the function vector list
   1398  * Returns:
   1399  *      SOC_E_NONE - success
   1400  *      SOC_E_XXXX - error code
   1401  * Notes:
   1402  */
   1403 int
   1404 soc_cmicm_dma_drv_init(int unit, soc_cmic_dma_drv_t *drv)
   1405 {
   1406     int rv = SOC_E_NONE;
   1407 
   1408     drv->init                       = cmicm_dma_init;
   1409     drv->ctrl_init                  = cmicm_dma_ctrl_init;
   1410     drv->chan_config                = cmicm_dma_chan_config;
   1411     drv->chan_dv_start              = cmicm_dma_chan_dv_start;
   1412     drv->chan_start                 = cmicm_dma_chan_start;
   1413     drv->chan_poll                  = cmicm_dma_chan_poll;
   1414     drv->chan_abort                 = cmicm_dma_chan_abort;
   1415     drv->chan_tx_purge              = cmicm_dma_chan_tx_purge;
   1416     drv->chan_desc_done_intr_enable = cmicm_dma_chan_desc_done_intr_enable;
   1417     drv->chan_desc_done             = cmicm_dma_chan_desc_done;
   1418     drv->chan_chain_done            = cmicm_dma_chan_chain_done;
   1419     drv->chan_reload_done           = NULL;
   1420     drv->chan_counter_get           = cmicm_dma_chan_counter_get;
   1421     drv->chan_counter_clear         = cmicm_dma_chan_counter_clear;
   1422     drv->chan_cos_ctrl_get          = cmicm_dma_chan_cos_ctrl_get;
   1423     drv->chan_cos_ctrl_set          = cmicm_dma_chan_cos_ctrl_set;
   1424     drv->chan_cos_ctrl_queue_get    = cmicm_dma_chan_cos_ctrl_queue_get;
   1425     drv->chan_cos_ctrl_reg_addr_get = cmicm_dma_chan_cos_ctrl_reg_addr_get;
   1426     drv->chan_status_get            = cmicm_dma_chan_status_get;
   1427     drv->chan_status_clear          = cmicm_dma_chan_status_clear;
   1428     drv->chan_halt_get              = NULL;
   1429     drv->chan_ctrl_reg_get          = cmicm_dma_chan_ctrl_reg_get;
   1430     drv->chan_ctrl_reg_set          = cmicm_dma_chan_ctrl_reg_set;
   1431     drv->chan_rxbuf_threshold_cfg   = cmicm_dma_chan_rxbuf_threshold_config;
   1432     drv->cmc_rxbuf_threshold_cfg    = NULL;
   1433     drv->cmc_counter_get            = cmicm_dma_cmc_counter_get;
   1434     drv->cmc_counter_clear          = cmicm_dma_cmc_counter_clear;
   1435     drv->loopback_config            = NULL;
   1436     drv->masks_get                  = cmicm_dma_masks_get;
   1437     drv->header_size_get            = cmicm_dma_header_size_get;
   1438     drv->max_rx_channels_get        = cmicm_dma_max_rx_channels_get;
   1439     drv->pci_timeout_handle         = cmicm_dma_pci_timeout_handle;
   1440 
   1441     return rv;
   1442 }
   1443 
   1444 #endif /* BCM_CMICM_SUPPORT */