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

cmicx_dma.c (56419B)


      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:     CMICX interface driver 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/cmic.h>
     21 
     22 #ifdef INCLUDE_KNET
     23 #include <soc/knet.h>
     24 #endif
     25 
     26 #ifdef BCM_CMICX_SUPPORT
     27 #include <soc/cmicx.h>
     28 #include <soc/intr_cmicx.h>
     29 #include <bcm_int/common/rx.h>
     30 
     31 typedef struct pktdma_intr_data_s {
     32     int cmc;
     33     int ch;
     34 } pktdma_intr_data_t;
     35 
     36 static pktdma_intr_data_t _intr_data[CMIC_CMC_NUM_MAX][CMICX_N_DMA_CHAN];
     37 
     38 #define DCB_LAST_DWORD 3
     39 #define DCB_DONE_BIT   0x80000000
     40 
     41 #define CH_DESC_DONE            0
     42 #define CH_CHAIN_DONE           1
     43 #define CH_INTR_COALESCING_INTR 2
     44 #define CH_DESC_CONTROLLED_INTR 3
     45 
     46 void
     47 soc_cmicx_pktdma_desc_endian_set(int unit, int cmc, int channel, int big_endian)
     48 {
     49     uint32 val = 0;
     50 
     51     val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel));
     52     val &= ~PKTDMA_DESC_BIG_ENDIAN;
     53     if (big_endian) {
     54         val |= PKTDMA_DESC_BIG_ENDIAN;
     55     }
     56     soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel), val);
     57 }
     58 
     59 void
     60 soc_cmicx_pktdma_hdr_endian_set(int unit, int cmc, int channel, int big_endian)
     61 {
     62     uint32 val = 0;
     63 
     64     val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel));
     65     val &= ~PKTDMA_HEADER_ENDIAN;
     66     if (big_endian) {
     67         val |= PKTDMA_HEADER_ENDIAN;
     68     }
     69     soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel), val);
     70 }
     71 
     72 void
     73 soc_cmicx_pktdma_data_endian_set(int unit, int cmc, int channel, int big_endian)
     74 {
     75     uint32 val = 0;
     76 
     77     val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel));
     78     val &= ~PKTDMA_BIG_ENDIAN;
     79     if (big_endian) {
     80         val |= PKTDMA_BIG_ENDIAN;
     81     }
     82     soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel), val);
     83 }
     84 
     85 uint32
     86 soc_cmicx_pktdma_cos_ctrl_rx0_get(int unit, int cmc, int channel)
     87 {
     88     return soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, channel));
     89 }
     90 
     91 uint32
     92 soc_cmicx_pktdma_cos_ctrl_rx1_get(int unit, int cmc, int channel)
     93 {
     94     return soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, channel));
     95 }
     96 
     97 uint32
     98 soc_cmicx_pktdma_cos_ctrl_rx0_reg_addr_get(int unit, int cmc, int channel)
     99 {
    100     return CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, channel);
    101 }
    102 
    103 uint32
    104 soc_cmicx_pktdma_cos_ctrl_rx1_reg_addr_get(int unit, int cmc, int channel)
    105 {
    106     return CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, channel);
    107 }
    108 
    109 uint32
    110 soc_cmicx_pktdma_cos_ctrl_queue_id_get(int unit, int cmc, int channel, int queue)
    111 {
    112     uint32 reg_addr;
    113     reg_addr = (queue < 32) ?
    114                 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, channel) :
    115                 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, channel);
    116 
    117     return soc_pci_read(unit, reg_addr);
    118 }
    119 
    120 sal_vaddr_t
    121 soc_cmicx_pktdma_desc_addr_get(int unit, int cmc, int channel)
    122 {
    123     uint32 val1;
    124     sal_paddr_t paddr;
    125 
    126     val1 = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_LO_OFFSET(cmc, channel));
    127 
    128 #if defined(COMPILER_OVERRIDE_NO_LONGLONG) || defined(__PEDANTIC__)
    129     paddr = (sal_paddr_t)val1;
    130 #else
    131     if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) {
    132         paddr = (((uint64)((soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, channel)))
    133                         & ~(CMIC_PCIE_SO_OFFSET)) << 32) | val1);
    134     } else {
    135         paddr = (((uint64)((soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, channel)))) << 32) | val1);
    136     }
    137 #endif
    138 
    139     return (sal_vaddr_t)soc_cm_p2l(unit, paddr);
    140 }
    141 
    142 uint32
    143 soc_cmicx_pktdma_header_size_get(int unit)
    144 {
    145     uint32 hdr_size = 0;
    146 
    147     /* The header size is an encoded value from only the first 4 bits of
    148      * the CMIC_TOP_EP_TO_CPU_HEADER_SIZE register. The actual header
    149      * size is the encoded value multiplied by 8.
    150      */
    151     hdr_size = ((soc_pci_read(unit, CMIC_TOP_EP_TO_CPU_HEADER_SIZE_OFFSET) & 0xf) * 8);
    152 
    153     return hdr_size;
    154 }
    155 
    156 /* Static Driver Functions */
    157 
    158 /*
    159  * Function:
    160  *      cmicx_dma_get_intr_base
    161  * Purpose:
    162  *      The interrupt numbers are dependent on the cmc.
    163  *      This calculates the interrupt base number.
    164  * Parameters:
    165  *      cmc - cmc#
    166  * Returns:
    167  *      The appropriate interrupt base for associated cmc
    168  * Notes:
    169  */
    170 
    171 static uint32
    172 cmicx_dma_get_intr_base(int cmc)
    173 {
    174     uint32 intr_base = 0;
    175 
    176     intr_base = (cmc == 0)? CMC0_CH0_DESC_DONE: CMC1_CH0_DESC_DONE;
    177 
    178     return intr_base;
    179 }
    180 
    181 /*
    182  * Function:
    183  *      cmicx_pkdma_ch_desc_done
    184  * Purpose:
    185  *      The interrupt handler for channel descriptor done
    186  *
    187  * Parameters:
    188  *      unit  - SOC unit #
    189  *      *data - pointer provided during registration
    190  */
    191 
    192 static void
    193 cmicx_pktdma_ch_desc_done(int unit, void *data)
    194 {
    195     soc_control_t *soc = SOC_CONTROL(unit);
    196     sdc_t *sc;
    197     pktdma_intr_data_t *in_d = (pktdma_intr_data_t *)data;
    198     int vchan = 0;
    199     uint32 val = 0;
    200 
    201     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    202                       (BSL_META_U(unit,
    203                                   "channel desc done cmc = %d ch = %d\n"),
    204                                   in_d->cmc, in_d->ch));
    205 
    206     val = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(in_d->cmc));
    207 
    208     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    209                       (BSL_META_U(unit,
    210                                   "shared irq stat0 val in desc done cb = %x\n"), val));
    211 
    212     val &= (DS_CMCx_CHy_DMA_DESC_DONE(in_d->ch) | DS_CMCx_CHy_DMA_CHAIN_DONE(in_d->ch) |
    213                    DS_CMCx_CHy_DESC_CONTROLLED_INTR(in_d->ch));
    214 
    215     vchan = (CMICX_N_DMA_CHAN * in_d->cmc) + in_d->ch;
    216     sc = &soc->soc_channels[vchan];
    217 
    218     if (sc->sc_q_cnt > 0) {
    219         soc_dma_cmicx_done_desc(unit, vchan);
    220     } else {
    221         soc_pci_write(unit,
    222                       CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(in_d->cmc),
    223                       val | (DS_CMCx_CHy_DMA_DESC_DONE(in_d->ch)));
    224     }
    225 }
    226 
    227 /*
    228  * Function:
    229  *      cmicx_pktdma_ch_chain_done
    230  * Purpose:
    231  *      The interrupt handler for channel chain done
    232  *
    233  * Parameters:
    234  *      unit  - SOC unit #
    235  *      *data - pointer provided during registration
    236  */
    237 
    238 static void
    239 cmicx_pktdma_ch_chain_done(int unit, void *data)
    240 {
    241     soc_control_t *soc = SOC_CONTROL(unit);
    242     sdc_t *sc;
    243     pktdma_intr_data_t *in_d = (pktdma_intr_data_t *)data;
    244     int vchan = 0;
    245     uint32 val = 0;
    246 
    247     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    248                       (BSL_META_U(unit,
    249                                   "channel chain done cmc = %d ch = %d\n"),
    250                                   in_d->cmc, in_d->ch));
    251 
    252     val = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(in_d->cmc));
    253 
    254     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    255                       (BSL_META_U(unit,
    256                                   "shared irq stat0 val in chain done cb = %x\n"), val));
    257 
    258     val &= (DS_CMCx_CHy_DMA_DESC_DONE(in_d->ch) | DS_CMCx_CHy_DMA_CHAIN_DONE(in_d->ch) |
    259                    DS_CMCx_CHy_DESC_CONTROLLED_INTR(in_d->ch));
    260 
    261     vchan = (CMICX_N_DMA_CHAN * in_d->cmc) + in_d->ch;
    262     sc = &soc->soc_channels[vchan];
    263 
    264     if (sc->sc_q_cnt > 0) {
    265         soc_dma_done_chain(unit, vchan);
    266     } else {
    267          soc_pci_write(unit,
    268                       CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(in_d->cmc),
    269                       val | (DS_CMCx_CHy_DMA_CHAIN_DONE(in_d->ch)));
    270     }
    271 }
    272 
    273 /*
    274  * Function:
    275  *      cmicx_dma_ctrl_init
    276  * Purpose:
    277  *      Initialize the CMICX DMA Control to a known good state for
    278  *      the specified SOC unit.
    279  * Parameters:
    280  *      unit - SOC unit #
    281  * Returns:
    282  *      SOC_E_NONE - success
    283  *      SOC_E_XXXX - error code
    284  * Notes:
    285  */
    286 
    287 int
    288 cmicx_dma_ctrl_init(int unit)
    289 {
    290     int rv = SOC_E_NONE;
    291     int cmc;
    292     uint32 val, chan, vchan;
    293 
    294     for(vchan=0; vchan < SOC_DCHAN_NUM(unit); vchan++) {
    295         cmc = vchan / CMICX_N_DMA_CHAN;
    296         chan = vchan % CMICX_N_DMA_CHAN;
    297 
    298         val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan));
    299         val &= (PKTDMA_BIG_ENDIAN | PKTDMA_DESC_BIG_ENDIAN | PKTDMA_HEADER_ENDIAN);
    300         soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), val);
    301     }
    302 
    303     /*
    304      * This has to be done only once after both CMIC and EP blocks
    305      * are out of reset.
    306      */
    307 
    308 #ifdef BCM_TOMAHAWK3_SUPPORT
    309     /* This is the SW WAR for TH3-3751. Since only 6 bits of
    310        iproc_cmic_to_ep_credits[5:0] are being used, so we cannot set the
    311        max credits to be released to EP to 64. Hence the SW WAR is to set the
    312        max credits to 63 first and then release to EP and set to 1 and release
    313        it again.
    314     */
    315     if (SOC_IS_TOMAHAWK3(unit)) {
    316         READ_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, &val);
    317 
    318         soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr,
    319                           &val, WR_EP_INTF_CREDITSf, 0x1);
    320         soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr,
    321                           &val, MAX_CREDITSf, 0x3F);
    322 
    323         WRITE_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, val);
    324 
    325         soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 1);
    326         soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 0);
    327 
    328         READ_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, &val);
    329 
    330         soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr,
    331                           &val, WR_EP_INTF_CREDITSf, 0x1);
    332         soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr,
    333                           &val, MAX_CREDITSf, 0x1);
    334 
    335         WRITE_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, val);
    336 
    337         soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 1);
    338         soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 0);
    339     } else
    340 #endif
    341     {
    342 #ifdef BCM_HELIX5_SUPPORT
    343     if(SOC_IS_HELIX5(unit)) {
    344 
    345         READ_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, &val);
    346         soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr,
    347                           &val, FLUSH_IP_INTF_BUFFERf, 1);
    348         WRITE_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, val);
    349 
    350         READ_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, &val);
    351         soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr,
    352                           &val, FLUSH_IP_INTF_BUFFERf, 0);
    353         soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr,
    354                           &val, IP_INTF_CREDITSf, 0x20);
    355         WRITE_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, val);
    356 
    357         READ_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, &val);
    358         soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr,
    359                           &val, FLUSH_IP_INTF_BUFFERf, 0);
    360         soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr,
    361                           &val, IP_INTF_CREDITSf, 0x20);
    362         soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr,
    363                           &val, WR_IP_INTF_CREDITSf, 1);
    364         WRITE_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, val);
    365     }
    366 #endif
    367         READ_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, &val);
    368 
    369         soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr,
    370                           &val, MAX_CREDITSf, 0x20);
    371 
    372         WRITE_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, val);
    373         soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr,
    374                           &val, WR_EP_INTF_CREDITSf, 1);
    375 
    376         WRITE_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, val);
    377 
    378         soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 0);
    379         soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 1);
    380     }
    381     /* Set IP_INTERFACE_HEADER_ENDIANESS=1 */
    382     val = soc_pci_read(unit, CMIC_TOP_CONFIG_OFFSET);
    383     val |= 0x80;
    384     soc_pci_write(unit, CMIC_TOP_CONFIG_OFFSET, val);
    385     return rv;
    386 }
    387 
    388 /*
    389  * Function:
    390  *      cmicx_dma_chan_config
    391  * Purpose:
    392  *      Initialize the CMICX DMA channel for the specified SOC unit.
    393  * Parameters:
    394  *      unit - SOC unit #
    395  *      chan - channel #
    396  *      type - tx or rx
    397  *      f_intr - interrupt flags
    398  * Returns:
    399  *      SOC_E_NONE - success
    400  *      SOC_E_XXXX - error code
    401  * Notes:
    402  */
    403 static int
    404 cmicx_dma_chan_config(int unit, int vchan, dvt_t type, uint32 flags)
    405 {
    406     int rv = SOC_E_NONE;
    407     soc_control_t *soc = SOC_CONTROL(unit);
    408     sdc_t *sc = &soc->soc_channels[vchan];
    409     uint32 bits = 0;
    410     int cmc = vchan / CMICX_N_DMA_CHAN;
    411     int chan = vchan % CMICX_N_DMA_CHAN;
    412     uint32 cr;
    413     uint32 intr_base = 0;
    414 
    415     int f_interrupt = (flags & SOC_DMA_F_POLL) == 0;
    416     int f_default = (flags & SOC_DMA_F_DEFAULT) != 0;
    417     int init_hw = TRUE;
    418 
    419     /* Set channel to Continuous Mode */
    420     if (soc_property_get(unit, spn_PDMA_CONTINUOUS_MODE_ENABLE, 0)) {
    421         SOC_DMA_MODE(unit) = SOC_DMA_MODE_CONTINUOUS;
    422     } else {
    423         SOC_DMA_MODE(unit) = SOC_DMA_MODE_CHAINED;
    424     }
    425 
    426     /* Initial state of channel */
    427     sc->sc_flags = 0;                   /* Clear flags to start */
    428 
    429 #ifdef INCLUDE_KNET
    430     if (SOC_KNET_MODE(unit) && SOC_WARM_BOOT(unit) &&
    431         soc_property_get(unit, spn_WARMBOOT_KNET_SHUTDOWN_MODE, 0)) {
    432         init_hw = FALSE;
    433     }
    434 #endif
    435 
    436     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    437                       (BSL_META_U(unit,
    438                                   "channel config cmc = %d channel= %d type = %d\n"),
    439                                    cmc, chan, type));
    440 
    441     intr_base = cmicx_dma_get_intr_base(cmc);
    442 
    443     if (init_hw) {
    444         soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_DESC_DONE);
    445         soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_CHAIN_DONE);
    446         soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_DESC_CONTROLLED_INTR);
    447 
    448         cr = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc,chan));
    449         cr &= ~PKTDMA_ENABLE;
    450         soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), cr);
    451 
    452         soc_pci_write(unit, CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc),
    453                       DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DESC_CONTROLLED_INTR(chan));
    454     }
    455 
    456     if (type == DV_TX) {
    457         bits |= PKTDMA_DIRECTION;
    458         if (f_default) {
    459             soc->soc_dma_default_tx = sc;
    460         }
    461     } else if (type == DV_RX) {
    462         bits &= ~PKTDMA_DIRECTION;
    463         if (f_default) {
    464             soc->soc_dma_default_rx = sc;
    465         }
    466     } else if (type == DV_NONE) {
    467         f_interrupt = FALSE;            /* Force off */
    468     } else {
    469         assert(0);
    470     }
    471 
    472 #ifdef INCLUDE_KNET
    473     if (SOC_KNET_MODE(unit)) {
    474         /* Interrupt are handled by kernel */
    475         f_interrupt = FALSE;
    476     }
    477 #endif
    478 
    479     if (f_interrupt) {
    480         if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) {
    481             soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_DESC_CONTROLLED_INTR);
    482         } else {
    483             soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_DESC_DONE);
    484             soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_CHAIN_DONE);
    485         }
    486     }
    487     sc->sc_type = type;
    488 
    489     if (init_hw) {
    490         cr = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan));
    491 
    492         /* Clear everything except Endianess */
    493         cr &= (PKTDMA_BIG_ENDIAN | PKTDMA_DESC_BIG_ENDIAN | PKTDMA_HEADER_ENDIAN);
    494         cr |= bits;
    495 
    496         if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) {
    497             cr |= PKTDMA_DESC_DONE_INTR_MODE;
    498         }
    499 
    500         if (soc_property_get(unit, spn_PDMA_DESCRIPTOR_PREFETCH_ENABLE, 0)) {
    501             cr |=  PKTDMA_CONTIGUOUS_DESCRIPTORS;
    502         }
    503 
    504         soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), cr);
    505     }
    506 
    507     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    508                       (BSL_META_U(unit,
    509                                   "completed channel config\n")));
    510 
    511     return rv;
    512 }
    513 
    514 /*
    515  * Function:
    516  *      cmicx_dma_chan_start
    517  * Purpose:
    518  *      Start the CMICd DMA channel for the specified SOC unit.
    519  * Parameters:
    520  *      unit - SOC unit #
    521  *      sc   - SOC channel data structure pointer
    522  * Returns:
    523  *      SOC_E_NONE - success
    524  *      SOC_E_XXXX - error code
    525  * Notes:
    526  */
    527 static int
    528 cmicx_dma_chan_start(int unit, sdc_t *sc)
    529 {
    530     int rv = SOC_E_NONE;
    531     dv_t *dv;
    532     int cmc = sc->sc_channel / CMICX_N_DMA_CHAN;
    533     int chan = sc->sc_channel % CMICX_N_DMA_CHAN;
    534     uint32 val;
    535     sal_paddr_t addr;
    536     uint32 intr_base = 0;
    537 
    538     if ((dv = sc->sc_dv_active = sc->sc_q) == NULL) {
    539         sc->sc_q_tail = NULL;
    540         return rv;
    541     }
    542 
    543 #ifdef INCLUDE_KNET
    544     if (SOC_KNET_MODE(unit)) {
    545         return rv;
    546     }
    547 #endif
    548 
    549     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    550                       (BSL_META_U(unit,
    551                                   "Starting channel %d\n"),
    552                        sc->sc_channel));
    553 
    554     /* Set up DMA descriptor address */
    555     addr = soc_cm_l2p(unit, sc->sc_q->dv_dcb);
    556 
    557     soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_LO_OFFSET(cmc, chan),
    558                   PTR_TO_INT(addr));
    559 
    560     if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) {
    561         soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, chan),
    562                   (CMIC_PCIE_SO_OFFSET | PTR_HI_TO_INT(addr)));
    563     } else {
    564         soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, chan), PTR_HI_TO_INT(addr));
    565     }
    566 
    567     if (SOC_DMA_MODE(unit) != SOC_DMA_MODE_CONTINUOUS) {
    568         if (sc->sc_flags & SOC_DMA_F_CLR_CHN_DONE) {
    569             val = soc_pci_read(unit,
    570                                CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan));
    571             val &= ~PKTDMA_ENABLE;
    572             soc_pci_write(unit,
    573                           CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan),
    574                           val);
    575         } else {
    576             sc->sc_flags |= SOC_DMA_F_CLR_CHN_DONE;
    577         }
    578     }
    579 
    580     /* Start DMA - Enable Continuous Mode for this channel */
    581     val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan));
    582     val |= (PKTDMA_ENABLE);
    583 
    584     if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) {
    585         val |= (PKTDMA_CONTINUOUS_ENABLE);
    586     }
    587 
    588     soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), val);
    589 
    590     SDK_CONFIG_MEMORY_BARRIER;
    591 
    592     if (!(sc->sc_flags & SOC_DMA_F_POLL)) {
    593         intr_base = cmicx_dma_get_intr_base(cmc);
    594         if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) {
    595             soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_DESC_CONTROLLED_INTR);
    596         } else {
    597             soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_CHAIN_DONE);
    598         }
    599     }
    600 
    601     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    602                       (BSL_META_U(unit,
    603                                   "completed channel start\n")));
    604 
    605     return rv;
    606 }
    607 
    608 /*
    609  * Function:
    610  *      cmicx_dma_chan_poll
    611  * Purpose:
    612  *      Poll the CMICX DMA channel for the specified SOC unit.
    613  * Parameters:
    614  *      unit - SOC unit #
    615  *      chan - channel #
    616  *      type - poll type (chain done or desc done)
    617  *      detected - poll result pointer to be updated
    618  * Returns:
    619  *      SOC_E_NONE - success
    620  *      SOC_E_XXXX - error code
    621  * Notes:
    622  *      Assumes that SOC_DMA_LOCK is held when called.
    623  */
    624 static int
    625 cmicx_dma_chan_poll(int unit, int vchan, soc_dma_poll_type_t type, int * detected)
    626 {
    627     int rv = SOC_E_NONE;
    628     int cmc = vchan / CMICX_N_DMA_CHAN;
    629     int chan = vchan % CMICX_N_DMA_CHAN;
    630 
    631     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    632                       (BSL_META_U(unit,
    633                                   "channel poll cmc = %d channel = %d\n"),
    634                                    cmc, chan));
    635 
    636     switch (type) {
    637     case SOC_DMA_POLL_DESC_DONE:
    638         *detected = (soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc))
    639                      & DS_CMCx_CHy_DMA_DESC_DONE(chan));
    640         break;
    641     case SOC_DMA_POLL_CHAIN_DONE:
    642         *detected = (soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc))
    643                      & DS_CMCx_CHy_DMA_CHAIN_DONE(chan));
    644         break;
    645     default:
    646         break;
    647     }
    648 
    649     return rv;
    650 }
    651 
    652 /*
    653  * Function:
    654  *      cmicx_dma_chan_abort
    655  * Purpose:
    656  *      Initialize the CMICX DMA channel for the specified SOC unit.
    657  * Parameters:
    658  *      unit - SOC unit #
    659  *      chan - channel #
    660  *      type - tx or rx
    661  *      f_intr - interrupt flags
    662  * Returns:
    663  *      SOC_E_NONE   - Success
    664  *      SOC_E_TIMEOUT - failed (Timeout)
    665  * Notes:
    666  *      Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation.
    667  */
    668 static int
    669 cmicx_dma_chan_abort(int unit, int vchan)
    670 {
    671     int rv = SOC_E_NONE;
    672     int cmc = vchan / CMICX_N_DMA_CHAN;
    673     int chan = vchan % CMICX_N_DMA_CHAN;
    674     int to;
    675     uint32 ctrl, val;
    676     soc_control_t *soc = SOC_CONTROL(unit);
    677     sdc_t *sc = &soc->soc_channels[chan];
    678 
    679     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    680                       (BSL_META_U(unit,
    681                                   "channel abort cmc = %d channel = %d\n"),
    682                                    cmc, chan));
    683 
    684     if ((soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_STAT_OFFSET(cmc, chan))
    685          & PKTDMA_CH_IS_ACTIVE) != 0) {
    686         ctrl = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan));
    687         ctrl |= PKTDMA_ENABLE;
    688         soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), ctrl);
    689         soc_pci_write(unit,
    690                       CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan),
    691                       ctrl | PKTDMA_ABORT);
    692         SDK_CONFIG_MEMORY_BARRIER;
    693 
    694         to = soc_property_get(unit, spn_PDMA_TIMEOUT_USEC, 1000000);
    695         while ((to >= 0) &&
    696                ((soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_STAT_OFFSET(cmc, chan))
    697                  & PKTDMA_CH_IS_ACTIVE) != 0)) {
    698             sal_udelay(10000);
    699             to -= 1000;
    700         }
    701         if ((soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_STAT_OFFSET(cmc, chan))
    702              & PKTDMA_CH_IS_ACTIVE) != 0) {
    703             LOG_ERROR(BSL_LS_SOC_PACKETDMA,
    704                       (BSL_META_U(unit,
    705                                   "soc_dma_abort_channel unit %d: "
    706                                   "channel %d abort timeout\n"),
    707                        unit, chan));
    708             rv = SOC_E_TIMEOUT;
    709             if (SOC_WARM_BOOT(unit)) {
    710                 return rv;
    711             }
    712         }
    713     }
    714     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    715                 (BSL_META_U(unit,
    716                             "soc_dma_abort_channel unit %d: "
    717                             "channel %d\n"),
    718                  unit, chan));
    719 
    720     ctrl = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan));
    721     /* Clearing enable will also clear CHAIN_DONE */
    722     ctrl &= ~(PKTDMA_ENABLE | PKTDMA_ABORT);
    723     soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), ctrl);
    724 
    725     val = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc));
    726 
    727     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    728                       (BSL_META_U(unit,
    729                                   "shared irq stat0 val = %x\n"), val));
    730 
    731     val &= (DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DMA_CHAIN_DONE(chan) |
    732                    DS_CMCx_CHy_DESC_CONTROLLED_INTR(chan));
    733 
    734     soc_pci_write(unit,
    735                   CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc),
    736                   val | (DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DMA_CHAIN_DONE(chan) |
    737                    DS_CMCx_CHy_DESC_CONTROLLED_INTR(chan)));
    738 
    739     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    740                       (BSL_META_U(unit,
    741                                   "In channel abort val of ctrl reg = %x\n"),
    742                                    ctrl));
    743 
    744     SDK_CONFIG_MEMORY_BARRIER;
    745 
    746     /* Mark channel as not started */
    747     sc->sc_dma_started = 0;
    748 
    749     return rv;
    750 }
    751 
    752 /*
    753  * Function:
    754  *      cmicx_dma_chan_dv_start
    755  * Purpose:
    756  *      Adds DV to the ready queue for CMICX DMA for the specified SOC unit.
    757  * Parameters:
    758  *      unit - SOC unit #
    759  *      chan - channel #
    760  * Returns:
    761  *      SOC_E_NONE - success
    762  *      SOC_E_XXXX - error code
    763  * Notes:
    764  *      Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation.
    765  */
    766 static int
    767 cmicx_dma_chan_dv_start(int unit, sdc_t *sc, dv_t *dv_chain)
    768 {
    769     int rv = SOC_E_NONE;
    770     int cmc = sc->sc_channel / CMICX_N_DMA_CHAN;
    771     int chan = sc->sc_channel % CMICX_N_DMA_CHAN;
    772     dcb_t *dcb;
    773     sal_paddr_t reg_val = 0;
    774 
    775     if (dv_chain == sc->sc_q) {
    776         DV_STATE(dv_chain) = DV_S_FILLED;
    777         return rv;
    778     }
    779 
    780     dv_chain->dv_next = NULL;
    781 
    782     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    783                       (BSL_META_U(unit,
    784                                   "channel dv start cmc = %d channel = %d\n"),
    785                                    cmc, chan));
    786 
    787 #ifdef INCLUDE_KNET
    788     if (SOC_KNET_MODE(unit)) {
    789         /* KNET handling of DV start */
    790         if (sc->sc_q_cnt != 0) {
    791             sc->sc_q_tail->dv_next = dv_chain;
    792         } else {
    793             sc->sc_q = dv_chain;
    794         }
    795         sc->sc_q_tail = dv_chain;
    796         sc->sc_q_cnt++;
    797         if (sc->sc_dv_active == NULL) {
    798             if (sc->sc_dma_started) {
    799                 sc->sc_dv_active = sc->sc_q;
    800             } else {
    801                 /* Start DMA if channel not active */
    802                 rv = cmicx_dma_chan_start(unit, sc);
    803                 sc->sc_dma_started = 1;
    804             }
    805         }
    806         return rv;
    807     }
    808 #endif
    809 
    810     if (sc->sc_q_cnt != 0) {
    811         sc->sc_q_tail->dv_next = dv_chain;
    812         if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) {
    813                 /* Set the reload addr of tail
    814                  * to the address of the appended chain
    815                  */
    816                 dcb = SOC_DCB_IDX2PTR(unit, sc->sc_q_tail->dv_dcb,
    817                                       sc->sc_q_tail->dv_vcnt - 1);
    818                 SOC_DCB_ADDR_SET(dv_chain->dv_unit, dcb,
    819                                  (sal_vaddr_t)dv_chain->dv_dcb);
    820         }
    821     } else {
    822         sc->sc_q = dv_chain;
    823     }
    824     sc->sc_q_tail = dv_chain;
    825     sc->sc_q_cnt++;
    826     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    827                       (BSL_META_U(unit,
    828                                   "channel dv start sc_q_cnt = %d\n"),
    829                                    sc->sc_q_cnt));
    830 
    831     if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) {
    832         /* Set the HW register for the new DESC_HALT_ADDR for CMICX
    833          * Need logical to physical mapping for addr
    834          * If DMA is currently halted, writing the new rld addr starts it again
    835          */
    836         reg_val = soc_cm_l2p(unit,
    837                             (void*)SOC_DCB_IDX2PTR(unit, dv_chain->dv_dcb,
    838                             (dv_chain->dv_vcnt - 1)));
    839 
    840         soc_pci_write(unit,
    841                       CMIC_CMCx_PKTDMA_CHy_DESC_HALT_ADDR_LO_OFFSET(cmc, chan),
    842                       PTR_TO_INT(reg_val));
    843 
    844         if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) {
    845             soc_pci_write(unit,
    846                       CMIC_CMCx_PKTDMA_CHy_DESC_HALT_ADDR_HI_OFFSET(cmc, chan),
    847                       CMIC_PCIE_SO_OFFSET | PTR_HI_TO_INT(reg_val));
    848         } else {
    849             soc_pci_write(unit,
    850                       CMIC_CMCx_PKTDMA_CHy_DESC_HALT_ADDR_HI_OFFSET(cmc, chan), PTR_HI_TO_INT(reg_val));
    851         }
    852     }
    853 
    854     SDK_CONFIG_MEMORY_BARRIER;
    855 
    856     /* Start DMA if channel not active */
    857     if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) {
    858         if ((sc->sc_dv_active == NULL) && (!sc->sc_dma_started)) {
    859             rv = cmicx_dma_chan_start(unit, sc);
    860             sc->sc_dma_started = 1;
    861         }
    862     }
    863 
    864     if (SOC_DMA_MODE(unit) != SOC_DMA_MODE_CONTINUOUS) {
    865         if (sc->sc_q_cnt == 1) {
    866             rv = cmicx_dma_chan_start(unit, sc);
    867             sc->sc_dma_started = 1;
    868         }
    869     }
    870 
    871     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    872                       (BSL_META_U(unit,
    873                                   "end of channel dv start\n")));
    874 
    875     return rv;
    876 }
    877 
    878 /*
    879  * Function:
    880  *      cmicx_dma_chan_chain_done
    881  * Purpose:
    882  *      on the CMICX DMA channel for the specified SOC unit.
    883  * Parameters:
    884  *      unit - SOC unit #
    885  *      chan - channel #
    886  *      mitigation - >0 = interrupt mitigation on
    887  * Returns:
    888  *      SOC_E_NONE - success
    889  *      SOC_E_XXXX - error code
    890  * Notes:
    891  *      INTERRUPT LEVEL ROUTINE.
    892  */
    893 static int
    894 cmicx_dma_chan_chain_done(int unit, int vchan, int mitigation)
    895 {
    896     int rv = SOC_E_NONE;
    897     int cmc = vchan / CMICX_N_DMA_CHAN;
    898     int chan = vchan % CMICX_N_DMA_CHAN;
    899     uint32 val;
    900     uint32 intr_base = 0;
    901 
    902     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    903                       (BSL_META_U(unit,
    904                                   "channel chain done cmc = %d channel = %d "
    905                                   "mitigation = %d\n"),
    906                                    cmc, chan, mitigation));
    907 
    908     intr_base = cmicx_dma_get_intr_base(cmc);
    909 
    910     if (mitigation) {
    911         soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_DESC_DONE);
    912         soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_CHAIN_DONE);
    913     } else {
    914         soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_CHAIN_DONE);
    915     }
    916 
    917     /* Disable DMA */
    918     val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan));
    919     val &= ~PKTDMA_ENABLE;
    920     soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), val);
    921 
    922     soc_pci_write(unit,
    923                   CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc),
    924                   DS_CMCx_CHy_DMA_CHAIN_DONE(chan));
    925 
    926     /* Flush posted writes from PCI bridge */
    927     (void)soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc));
    928 
    929     val = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc));
    930 
    931     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    932                       (BSL_META_U(unit,
    933                                   "shared irq stat0 val at chain done = %x\n"), val));
    934 
    935     return rv;
    936 }
    937 
    938 /*
    939  * Function:
    940  *      cmicx_dma_chan_desc_done
    941  * Purpose:
    942  *      Clears desc done on the CMICX DMA channel for the specified SOC unit.
    943  * Parameters:
    944  *      unit - SOC unit #
    945  *      chan - channel #
    946  * Returns:
    947  *      SOC_E_NONE - success
    948  *      SOC_E_XXXX - error code
    949  * Notes:
    950  *      INTERRUPT LEVEL ROUTINE.
    951  */
    952 static int
    953 cmicx_dma_chan_desc_done(int unit, int vchan)
    954 {
    955     int rv = SOC_E_NONE;
    956     int cmc = vchan / CMICX_N_DMA_CHAN;
    957     int chan = vchan % CMICX_N_DMA_CHAN;
    958     uint32 val;
    959 
    960     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    961                       (BSL_META_U(unit,
    962                                   "channel desc done cmc = %d channel = %d\n"),
    963                                    cmc, chan));
    964 
    965     /*
    966      * Older CMIC devices required a read/write/modify to clear done
    967      * interrupts. That does not work here for continuous DMA.  Need only
    968      * to set the bit for the corresponding interrupt to clear.
    969      */
    970     val = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc));
    971 
    972     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
    973                       (BSL_META_U(unit,
    974                                   "shared irq stat0 val = %x\n"), val));
    975 
    976     val &= (DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DMA_CHAIN_DONE(chan) |
    977                    DS_CMCx_CHy_DESC_CONTROLLED_INTR(chan));
    978 
    979     if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) {
    980         soc_pci_write(unit,
    981                       CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc),
    982                       (DS_CMCx_CHy_DESC_CONTROLLED_INTR(chan)));
    983     } else {
    984         soc_pci_write(unit,
    985                       CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc),
    986                       (DS_CMCx_CHy_DMA_DESC_DONE(chan)));
    987     }
    988 
    989     /* Flush posted writes from PCI bridge */
    990     (void)soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc));
    991 
    992     return rv;
    993 }
    994 
    995 /*
    996  * Function:
    997  *      cmicx_dma_chan_desc_done_intr_enable
    998  * Purpose:
    999  *      Clears desc done on the CMICX DMA channel for the specified SOC unit.
   1000  * Parameters:
   1001  *      unit - SOC unit #
   1002  *      chan - channel #
   1003  * Returns:
   1004  *      SOC_E_NONE - success
   1005  *      SOC_E_XXXX - error code
   1006  * Notes:
   1007  *      INTERRUPT LEVEL ROUTINE.
   1008  */
   1009 static int
   1010 cmicx_dma_chan_desc_done_intr_enable(int unit, int vchan)
   1011 {
   1012     int rv = SOC_E_NONE;
   1013     int cmc = vchan / CMICX_N_DMA_CHAN;
   1014     int chan = vchan % CMICX_N_DMA_CHAN;
   1015     uint32 intr_base = 0;
   1016 
   1017     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1018                       (BSL_META_U(unit,
   1019                                   "channel desc done intr enable cmc = %d channel = %d\n"),
   1020                                    cmc, chan));
   1021 
   1022     intr_base = cmicx_dma_get_intr_base(cmc);
   1023 
   1024     if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) {
   1025         soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_DESC_CONTROLLED_INTR);
   1026     } else {
   1027         soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_DESC_DONE);
   1028     }
   1029 
   1030     return rv;
   1031 }
   1032 
   1033 /*
   1034  * Function:
   1035  *      cmicx_dma_chan_reload_done
   1036  * Purpose:
   1037  *      Detect for reload descriptor completed
   1038  * Parameters:
   1039  *      unit - SOC unit #
   1040  *      sc   - SOC channel data structure pointer
   1041  * Returns:
   1042  *      SOC_E_NONE - success
   1043  *      SOC_E_XXXX - error code
   1044  * Notes:
   1045  */
   1046 static int
   1047 cmicx_dma_chan_reload_done(int unit, int vchan, dcb_t * dcb, int *rld_done)
   1048 {
   1049     int rv = SOC_E_NONE;
   1050     uint32 *rld_dcb;
   1051 
   1052     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1053                       (BSL_META_U(unit,
   1054                                   "channel reload done\n")));
   1055 
   1056     *rld_done = 0; /* Default to not reload */
   1057 
   1058     /* There is no pkt data to process for a reload descriptor */
   1059     if(SOC_DCB_RELOAD_GET(unit, dcb)) {
   1060         /* HW sets bit 31 in the dcb's last dword to indicate done */
   1061         rld_dcb = (uint32 *)dcb;
   1062         if (rld_dcb[DCB_LAST_DWORD] & DCB_DONE_BIT) {
   1063             *rld_done = 1;
   1064         }
   1065     }
   1066 
   1067     return rv;
   1068 }
   1069 
   1070 /*
   1071  * Function:
   1072  *      cmicx_dma_chan_counter_get
   1073  * Purpose:
   1074  *      Obtain tx and rx counter values
   1075  * Parameters:
   1076  *      unit    - SOC unit #
   1077  *      vchan   - SOC virtual channel number
   1078  * Returns:
   1079  *      SOC_E_NONE - success
   1080  * Notes:
   1081  */
   1082 static int
   1083 cmicx_dma_chan_counter_get(int unit, int vchan, uint32 *tx_pkt, uint32 *rx_pkt)
   1084 {
   1085     int rv = SOC_E_NONE;
   1086     int cmc = vchan / CMICX_N_DMA_CHAN;
   1087     int chan = vchan % CMICX_N_DMA_CHAN;
   1088 
   1089     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1090                       (BSL_META_U(unit,
   1091                                   "channel counter get\n")));
   1092 
   1093     *tx_pkt = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_TXPKT_OFFSET(cmc, chan));
   1094     *rx_pkt = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_RXPKT_OFFSET(cmc, chan));
   1095 #if 0
   1096     /* keep this code ready and handy, just in case somebody needs it */
   1097     *rx_pkt_drop = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_RXPKT_DROP_OFFSET(cmc, chan));
   1098 #endif
   1099     return rv;
   1100 }
   1101 
   1102 /*
   1103  * Function:
   1104  *      cmicx_dma_chan_counter_clear
   1105  * Purpose:
   1106  *      clear tx and rx counter values
   1107  * Parameters:
   1108  *      unit    - SOC unit #
   1109  *      vchan   - SOC virtual channel number
   1110  *      mask    - to clear the appopriate counter
   1111  * Returns:
   1112  *      SOC_E_NONE - success
   1113  * Notes:
   1114  */
   1115 static int
   1116 cmicx_dma_chan_counter_clear(int unit, int vchan, uint32 mask)
   1117 {
   1118     int rv = SOC_E_NONE;
   1119     int cmc = vchan / CMICX_N_DMA_CHAN;
   1120     int chan = vchan % CMICX_N_DMA_CHAN;
   1121 
   1122     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1123                       (BSL_META_U(unit,
   1124                                   "channel counter clear\n")));
   1125 
   1126     if (mask & 0x1) {
   1127         soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_TXPKT_OFFSET(cmc, chan), 0);
   1128     }
   1129 
   1130     if (mask & 0x2) {
   1131         soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_RXPKT_OFFSET(cmc, chan), 0);
   1132     }
   1133 
   1134     /* Keep this code ready just in case apps start to use this feature of rx pkt drops */
   1135     if (mask & 0x4) {
   1136         soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_RXPKT_DROP_OFFSET(cmc, chan), 0);
   1137     }
   1138 
   1139     return rv;
   1140 }
   1141 
   1142 /*
   1143  * Function:
   1144  *      cmicx_dma_cmc_counter_get
   1145  * Purpose:
   1146  *      Obtain tx and rx counter values
   1147  * Parameters:
   1148  *      unit    - SOC unit #
   1149  *      cmc     - cmc number
   1150  * Returns:
   1151  *      SOC_E_NONE - success
   1152  * Notes:
   1153  */
   1154 static int
   1155 cmicx_dma_cmc_counter_get(int unit, int cmc, uint32 *tx_pkt, uint32 *rx_pkt)
   1156 {
   1157     int rv = SOC_E_NONE;
   1158 
   1159     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1160                       (BSL_META_U(unit,
   1161                                   "cmc counter get\n")));
   1162 
   1163     *tx_pkt = soc_pci_read(unit, CMIC_CMCx_SHARED_PKT_COUNT_TXPKT_OFFSET(cmc));
   1164     *rx_pkt = soc_pci_read(unit, CMIC_CMCx_SHARED_PKT_COUNT_RXPKT_OFFSET(cmc));
   1165 
   1166     return rv;
   1167 }
   1168 
   1169 /*
   1170  * Function:
   1171  *      cmicx_dma_cmc_counter_clear
   1172  * Purpose:
   1173  *      clear tx and rx counter values
   1174  * Parameters:
   1175  *      unit    - SOC unit #
   1176  *      cmc     - cmc number
   1177  *      mask    - to clear the appopriate counter
   1178  * Returns:
   1179  *      SOC_E_NONE - success
   1180  * Notes:
   1181  */
   1182 static int
   1183 cmicx_dma_cmc_counter_clear(int unit, int cmc, uint32 mask)
   1184 {
   1185     int rv = SOC_E_NONE;
   1186 
   1187     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1188                       (BSL_META_U(unit,
   1189                                   "cmc counter clear\n")));
   1190 
   1191     if (mask & 0x1) {
   1192         soc_pci_write(unit, CMIC_CMCx_SHARED_PKT_COUNT_TXPKT_OFFSET(cmc), 0);
   1193     }
   1194 
   1195     if (mask & 0x2) {
   1196         soc_pci_write(unit, CMIC_CMCx_SHARED_PKT_COUNT_RXPKT_OFFSET(cmc), 0);
   1197     }
   1198 
   1199     return rv;
   1200 }
   1201 
   1202 /*
   1203  * Function:
   1204  *      cmicx_loopback_config
   1205  * Purpose:
   1206  *      Set/reset cmicx in loopback mode
   1207  * Parameters:
   1208  *      unit - SOC unit #
   1209  *      cfg  - to set/reset
   1210  * Returns:
   1211  *      SOC_E_NONE - success
   1212  *      SOC_E_XXXX - error code
   1213  * Notes:
   1214  */
   1215 
   1216 int
   1217 cmicx_loopback_config(int unit, uint32 cfg)
   1218 {
   1219     int rv = SOC_E_NONE;
   1220     uint32 val = 0;
   1221 
   1222     val = soc_pci_read(unit, CMIC_TOP_CONFIG_OFFSET);
   1223     val &= 0x3f;
   1224 
   1225     if (cfg & 0x1) {
   1226         val |= (1 << 1);
   1227         soc_pci_write(unit, CMIC_TOP_CONFIG_OFFSET, val);
   1228     } else {
   1229         val &= ~(1 << 1);
   1230         soc_pci_write(unit, CMIC_TOP_CONFIG_OFFSET, val);
   1231     }
   1232 
   1233     return rv;
   1234 }
   1235 
   1236 /*
   1237  * Function:
   1238  *      cmicx_dma_header_size_get
   1239  * Purpose:
   1240  *      obtain the ep to cpu header size
   1241  * Parameters:
   1242  *      unit     - SOC unit #
   1243  *      hdr_size - return value of the ep to cpu header size
   1244  *
   1245  * Returns:
   1246  *      SOC_E_NONE - success
   1247  *      SOC_E_XXXX - error code
   1248  * Notes:
   1249  */
   1250 
   1251 static int
   1252 cmicx_dma_header_size_get(int unit, uint32 *hdr_size)
   1253 {
   1254     int rv = SOC_E_NONE;
   1255 
   1256     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1257                       (BSL_META_U(unit,
   1258                                   "cmicx dma get header size\n")));
   1259 
   1260     *hdr_size = ((soc_pci_read(unit, CMIC_TOP_EP_TO_CPU_HEADER_SIZE_OFFSET) & 0xf) * 8);
   1261 
   1262     return rv;
   1263 }
   1264 
   1265 /*
   1266  * Function:
   1267  *      cmicx_dma_max_rx_channels_get
   1268  * Purpose:
   1269  *      obtain maximum number of dma channels that can be used for BCM RX
   1270  * Parameters:
   1271  *      unit - SOC unit #
   1272  *      max_rx_channels - maximum rx channels that can be used
   1273  * Returns:
   1274  *      SOC_E_NONE - success
   1275  *      SOC_E_XXXX - error
   1276  */
   1277 
   1278 int
   1279 cmicx_dma_max_rx_channels_get(int unit, uint32 *max_rx_channels)
   1280 {
   1281     int rv = SOC_E_NONE;
   1282 
   1283     /*
   1284      * Only CMC0 is used for BCM RX hence we can have
   1285      * CMICX_N_DMA_CHAN number of maximum rx channels
   1286      */
   1287 
   1288     *max_rx_channels = CMICX_N_DMA_CHAN;
   1289 
   1290     return rv;
   1291 }
   1292 
   1293 /*
   1294  * Function:
   1295  *      cmicx_dma_chan_cos_ctrl_get
   1296  * Purpose:
   1297  *      get cos ctrl for a channel
   1298  * Parameters:
   1299  *      unit - SOC unit #
   1300  *      cfg  - to choose appropriate register
   1301  * Returns:
   1302  *      SOC_E_NONE - success
   1303  *      SOC_E_XXXX - error code
   1304  * Notes:
   1305  */
   1306 
   1307 int
   1308 cmicx_dma_chan_cos_ctrl_get(int unit, int vchan, uint32 cfg, uint32 *cos_ctrl)
   1309 {
   1310     int rv = SOC_E_NONE;
   1311     int cmc = vchan / CMICX_N_DMA_CHAN;
   1312     int chan = vchan % CMICX_N_DMA_CHAN;
   1313 
   1314     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1315                       (BSL_META_U(unit,
   1316                                   "channel cos ctrl get\n")));
   1317 
   1318     if (cfg & 0x1) {
   1319         *cos_ctrl = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan));
   1320     } else if (cfg & 0x2) {
   1321         *cos_ctrl = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan));
   1322     }
   1323 
   1324     return rv;
   1325 }
   1326 
   1327 /*
   1328  * Function:
   1329  *      cmicx_dma_chan_cos_ctrl_set
   1330  * Purpose:
   1331  *      get cos ctrl for a channel
   1332  * Parameters:
   1333  *      unit - SOC unit #
   1334  *      cfg  - to choose appropriate register
   1335  * Returns:
   1336  *      SOC_E_NONE - success
   1337  *      SOC_E_XXXX - error code
   1338  * Notes:
   1339  */
   1340 
   1341 int
   1342 cmicx_dma_chan_cos_ctrl_set(int unit, int vchan, uint32 cfg, uint32 cos_ctrl)
   1343 {
   1344     int rv = SOC_E_NONE;
   1345     int cmc = vchan / CMICX_N_DMA_CHAN;
   1346     int chan = vchan % CMICX_N_DMA_CHAN;
   1347 
   1348     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1349                       (BSL_META_U(unit,
   1350                                   "channel cos ctrl set\n")));
   1351 
   1352     if (cfg & 0x1) {
   1353         soc_pci_write(unit,
   1354                       CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan),
   1355                       cos_ctrl);
   1356     } else if (cfg & 0x2) {
   1357         soc_pci_write(unit,
   1358                       CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan),
   1359                       cos_ctrl);
   1360     }
   1361 
   1362     return rv;
   1363 }
   1364 
   1365 /*
   1366  * Function:
   1367  *      cmicx_dma_chan_cos_ctrl_queue_get
   1368  * Purpose:
   1369  *      get cos ctrl for a channel based on queue
   1370  * Parameters:
   1371  *      unit     - SOC unit #
   1372  *      cmc      - CMC #
   1373  *      chan     - chan #
   1374  *      queue    - cos queue
   1375  *      cos_ctrl - cos ctrl val
   1376  * Returns:
   1377  *      SOC_E_NONE - success
   1378  *      SOC_E_XXXX - error code
   1379  * Notes:
   1380  */
   1381 
   1382 int
   1383 cmicx_dma_chan_cos_ctrl_queue_get(int unit, int cmc, int chan,
   1384                                   int queue, uint32 *cos_ctrl)
   1385 {
   1386     int rv = SOC_E_NONE;
   1387     uint32 reg_addr;
   1388 
   1389     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1390                       (BSL_META_U(unit,
   1391                                   "channel cos ctrl queue get\n")));
   1392 
   1393     reg_addr = (queue < 32) ?
   1394                 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan) :
   1395                 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan);
   1396 
   1397     *cos_ctrl = soc_pci_read(unit, reg_addr);
   1398 
   1399     return rv;
   1400 }
   1401 
   1402 /*
   1403  * Function:
   1404  *      cmicx_dma_chan_cos_ctrl_reg_addr_get
   1405  * Purpose:
   1406  *      get cos ctrl for a channel based on queue
   1407  * Parameters:
   1408  *      unit     - SOC unit #
   1409  *      cmc      - CMC #
   1410  *      chan     - chan #
   1411  *      queue    - cos queue
   1412  *      reg_addr - reg addr val
   1413  * Returns:
   1414  *      SOC_E_NONE - success
   1415  *      SOC_E_XXXX - error code
   1416  * Notes:
   1417  */
   1418 
   1419 int
   1420 cmicx_dma_chan_cos_ctrl_reg_addr_get(int unit, int cmc, int chan,
   1421                                      int queue, uint32 *reg_addr)
   1422 {
   1423     int rv = SOC_E_NONE;
   1424 
   1425     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1426                       (BSL_META_U(unit,
   1427                                   "channel cos ctrl reg addr get\n")));
   1428 
   1429     *reg_addr = (queue < 32) ?
   1430                 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan) :
   1431                 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan);
   1432 
   1433     return rv;
   1434 }
   1435 
   1436 /*
   1437  * Function:
   1438  *      cmicx_dma_chan_status_get
   1439  * Purpose:
   1440  *      get channel status
   1441  * Parameters:
   1442  *      unit   - SOC unit #
   1443  *      vchan  - channel #
   1444  *      status - channel status
   1445  *
   1446  * Returns:
   1447  *      SOC_E_NONE - success
   1448  *      SOC_E_XXXX - error code
   1449  * Notes:
   1450  */
   1451 
   1452 int
   1453 cmicx_dma_chan_status_get(int unit, int vchan, uint32 mask, int *status)
   1454 {
   1455     int rv = SOC_E_NONE;
   1456     int cmc = vchan / CMICX_N_DMA_CHAN;
   1457     int chan = vchan % CMICX_N_DMA_CHAN;
   1458 
   1459     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1460                       (BSL_META_U(unit,
   1461                                   "channel status get\n")));
   1462 
   1463     *status = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_STAT_OFFSET(cmc, chan));
   1464 
   1465     return rv;
   1466 }
   1467 
   1468 /*
   1469  * Function:
   1470  *      cmicx_dma_chan_halt_get
   1471  * Purpose:
   1472  *      get channel halt status
   1473  * Parameters:
   1474  *      unit   - SOC unit #
   1475  *      vchan  - channel #
   1476  *      halt   - channel halt status
   1477  *
   1478  * Returns:
   1479  *      SOC_E_NONE - success
   1480  *      SOC_E_XXXX - error code
   1481  * Notes:
   1482  */
   1483 
   1484 int
   1485 cmicx_dma_chan_halt_get(int unit, int vchan, uint32 mask, int *halt)
   1486 {
   1487     int rv  = SOC_E_NONE;
   1488     int cmc = vchan / CMICX_N_DMA_CHAN;
   1489     int chan = vchan % CMICX_N_DMA_CHAN;
   1490 
   1491     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1492                       (BSL_META_U(unit,
   1493                                   "channel halt get\n")));
   1494 
   1495     *halt = (soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_STAT_OFFSET(cmc, chan))
   1496                             & PKTDMA_CH_IN_HALT);
   1497 
   1498     return rv;
   1499 }
   1500 
   1501 /*
   1502  * Function:
   1503  *      cmicx_dma_chan_ctrl_reg_get
   1504  * Purpose:
   1505  *      get channel ctrl reg value
   1506  * Parameters:
   1507  *      unit  - SOC unit #
   1508  *      vchan - channel #
   1509  *      value - channel ctrl reg value
   1510  *
   1511  * Returns:
   1512  *      SOC_E_NONE - success
   1513  *      SOC_E_XXXX - error code
   1514  * Notes:
   1515  */
   1516 
   1517 int
   1518 cmicx_dma_chan_ctrl_reg_get(int unit, int vchan, uint32 *val)
   1519 {
   1520     int rv = SOC_E_NONE;
   1521     int cmc = vchan / CMICX_N_DMA_CHAN;
   1522     int chan = vchan % CMICX_N_DMA_CHAN;
   1523 
   1524     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1525                       (BSL_META_U(unit,
   1526                                   "channel ctrl reg get\n")));
   1527 
   1528     *val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan));
   1529 
   1530     return rv;
   1531 }
   1532 
   1533 /*
   1534  * Function:
   1535  *      cmicx_dma_chan_ctrl_reg_set
   1536  * Purpose:
   1537  *      set channel ctrl reg
   1538  * Parameters:
   1539  *      unit  - SOC unit #
   1540  *      vchan - channel #
   1541  *      value - channel ctrl reg value to set
   1542  *
   1543  * Returns:
   1544  *      SOC_E_NONE - success
   1545  *      SOC_E_XXXX - error code
   1546  * Notes:
   1547  */
   1548 
   1549 int
   1550 cmicx_dma_chan_ctrl_reg_set(int unit, int vchan, uint32 val)
   1551 {
   1552     int rv = SOC_E_NONE;
   1553     int cmc = vchan / CMICX_N_DMA_CHAN;
   1554     int chan = vchan % CMICX_N_DMA_CHAN;
   1555 
   1556     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1557                       (BSL_META_U(unit,
   1558                                   "channel ctrl reg get\n")));
   1559 
   1560     soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), val);
   1561 
   1562     return rv;
   1563 }
   1564 
   1565 /*
   1566  * Function:
   1567  *      cmicx_dma_chan_rxbuf_threshold_config
   1568  * Purpose:
   1569  *      appropriately set mmu back pressure per channel
   1570  * Parameters:
   1571  *      unit  - SOC unit #
   1572  *      vchan - channel #
   1573  *      value - mmu backpressure settings
   1574  *
   1575  * Returns:
   1576  *      SOC_E_NONE - success
   1577  *      SOC_E_XXXX - error code
   1578  * Notes:
   1579  */
   1580 
   1581 int
   1582 cmicx_dma_chan_rxbuf_threshold_config(int unit, int vchan, uint32 val)
   1583 {
   1584     int rv = SOC_E_NONE;
   1585     int cmc = vchan / CMICX_N_DMA_CHAN;
   1586     int chan = vchan % CMICX_N_DMA_CHAN;
   1587 
   1588     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1589                       (BSL_META_U(unit,
   1590                                   "channel rxbuf threshold config\n")));
   1591 
   1592     soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc, chan), val);
   1593 
   1594     return rv;
   1595 }
   1596 
   1597 /*
   1598  * Function:
   1599  *      cmicx_dma_cmc_rxbuf_threshold_config
   1600  * Purpose:
   1601  *      appropriately set mmu back pressure per cmc
   1602  * Parameters:
   1603  *      unit  - SOC unit #
   1604  *      cmc   - cmc #
   1605  *      value - mmu backpressure settings
   1606  *
   1607  * Returns:
   1608  *      SOC_E_NONE - success
   1609  *      SOC_E_XXXX - error code
   1610  * Notes:
   1611  */
   1612 
   1613 int
   1614 cmicx_dma_cmc_rxbuf_threshold_config(int unit, int cmc, uint32 val)
   1615 {
   1616     int rv = SOC_E_NONE;
   1617 
   1618     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1619                       (BSL_META_U(unit,
   1620                                   "cmc rxbuf threshold config\n")));
   1621 
   1622     soc_pci_write(unit, CMIC_CMCx_SHARED_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc), val);
   1623 
   1624     return rv;
   1625 }
   1626 
   1627 /*
   1628  * Function:
   1629  *      cmicx_dma_masks_get
   1630  * Purpose:
   1631  *      obtain the individual big endian masks
   1632  * Parameters:
   1633  *      unit          - SOC unit #
   1634  *      pkt_endian    - pkt endian mask
   1635  *      desc_endian   - desc endian mask
   1636  *      header_endian - header endian mask
   1637  *
   1638  * Returns:
   1639  *      SOC_E_NONE - success
   1640  *      SOC_E_XXXX - error code
   1641  * Notes:
   1642  */
   1643 
   1644 int
   1645 cmicx_dma_masks_get(int unit, uint32 *pkt_endian, uint32 *desc_endian, uint32 *header_endian)
   1646 {
   1647     int rv = SOC_E_NONE;
   1648 
   1649     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1650                       (BSL_META_U(unit,
   1651                                   "cmicx dma get masks\n")));
   1652 
   1653     *pkt_endian    = PKTDMA_BIG_ENDIAN;
   1654     *desc_endian   = PKTDMA_DESC_BIG_ENDIAN;
   1655     *header_endian = PKTDMA_HEADER_ENDIAN;
   1656 
   1657     return rv;
   1658 }
   1659 
   1660 /*
   1661  * Function:
   1662  *      cmicx_dma_chan_tx_purge
   1663  * Purpose:
   1664  *      Purge partial pkt left in the pipeline from TX DMA abort.
   1665  * Parameters:
   1666  *      unit - SOC unit #
   1667  *      chan - channel #
   1668  * Returns:
   1669  *      SOC_E_NONE   - Success
   1670  *      SOC_E_TIMEOUT - failed (Timeout)
   1671  * Notes:
   1672  *      Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation.
   1673  */
   1674 static int
   1675 cmicx_dma_chan_tx_purge(int unit, int vchan, dv_t *dv)
   1676 {
   1677     int rv = SOC_E_NONE;
   1678     int cmc = vchan / CMICX_N_DMA_CHAN;
   1679     int chan = vchan % CMICX_N_DMA_CHAN;
   1680     sal_usecs_t start_time;
   1681     int diff_time;
   1682     uint32 dma_stat;
   1683     uint32 dma_state;
   1684     sal_paddr_t addr;
   1685 
   1686     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1687                       (BSL_META_U(unit,
   1688                                   "channel tx purge cmc = %d channel = %d\n"),
   1689                                    cmc, chan));
   1690 
   1691     soc_pci_write(unit,
   1692                   CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan),
   1693                   soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan))
   1694                   | PKTDMA_DIRECTION);
   1695 
   1696     addr = soc_cm_l2p(unit, dv->dv_dcb);
   1697 
   1698     soc_pci_write(unit,
   1699                   CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_LO_OFFSET(cmc, chan),
   1700                   PTR_TO_INT(addr));
   1701     if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) {
   1702         soc_pci_write(unit,
   1703                   CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, chan),
   1704                   (CMIC_PCIE_SO_OFFSET | PTR_HI_TO_INT(addr)));
   1705     } else {
   1706         soc_pci_write(unit,
   1707                   CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, chan),
   1708                   PTR_HI_TO_INT(addr));
   1709     }
   1710 
   1711     /* Start DMA */
   1712     soc_pci_write(unit,
   1713                   CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan),
   1714                   soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc ,chan))
   1715                   | PKTDMA_ENABLE);
   1716 
   1717     start_time = sal_time_usecs();
   1718     diff_time = 0;
   1719     dma_state = (DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DMA_CHAIN_DONE(chan));
   1720 
   1721     do {
   1722         sal_udelay(SAL_BOOT_SIMULATION ? 1000 : 10);
   1723         dma_stat = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc)) &
   1724             (DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DMA_CHAIN_DONE(chan));
   1725 
   1726         diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
   1727 
   1728         if (diff_time > DMA_ABORT_TIMEOUT) { /* 10 Sec(QT)/10 msec */
   1729             rv = SOC_E_TIMEOUT;
   1730             break;
   1731         } else if (diff_time < 0) {
   1732             /* Restart in case system time changed */
   1733             start_time = sal_time_usecs();
   1734         }
   1735     } while (dma_stat != dma_state);
   1736 
   1737     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1738                       (BSL_META_U(unit,
   1739                                   "disabling dma\n")));
   1740 
   1741     /* Clear CHAIN_DONE and DESC_DONE */
   1742     soc_pci_write(unit,
   1743                   CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan),
   1744                   soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan))
   1745                   & ~PKTDMA_ENABLE);
   1746 
   1747     dma_stat = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc));
   1748     soc_pci_write(unit,
   1749                   CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc),
   1750                   (DS_CMCx_CHy_DMA_DESC_DONE(chan)));
   1751 
   1752     return rv;
   1753 }
   1754 
   1755 
   1756 /*
   1757  * Function:
   1758  *      cmicx_dma_init
   1759  * Purpose:
   1760  *      Initialize the CMICX DMA for the specified SOC unit.
   1761  * Parameters:
   1762  *      unit - SOC unit #
   1763  * Returns:
   1764  *      SOC_E_NONE - success
   1765  *      SOC_E_XXXX - error code
   1766  * Notes:
   1767  */
   1768 static int
   1769 cmicx_dma_init(int unit)
   1770 {
   1771     int cmc, ch;
   1772     soc_cmic_intr_handler_t *handle;
   1773     soc_cmic_intr_handler_t *hitr;
   1774     int rv = SOC_E_NONE;
   1775     uint32 intr_base = 0;
   1776 
   1777     LOG_VERBOSE(BSL_LS_SOC_PACKETDMA,
   1778                       (BSL_META_U(unit,
   1779                                   "cmicx dma init, registering interrupts\n")));
   1780 
   1781     /* Register the descriptor done interrupts */
   1782     handle = sal_alloc(sizeof(soc_cmic_intr_handler_t)*CMIC_CMC_NUM_MAX*
   1783                        CMICX_N_DMA_CHAN, "pktdma_desc_controlled_interrupt");
   1784     if (handle == NULL) {
   1785         return SOC_E_MEMORY;
   1786     }
   1787 
   1788     hitr = handle;
   1789 
   1790     for (cmc = 0; cmc < CMIC_CMC_NUM_MAX; cmc++) {
   1791          intr_base = cmicx_dma_get_intr_base(cmc);
   1792          for (ch = 0; ch < CMICX_N_DMA_CHAN; ch++) {
   1793               _intr_data[cmc][ch].cmc = cmc;
   1794               _intr_data[cmc][ch].ch = ch;
   1795               hitr->num = intr_base + (4 * ch) + CH_DESC_CONTROLLED_INTR;
   1796               hitr->intr_fn = cmicx_pktdma_ch_desc_done;
   1797               hitr->intr_data = &_intr_data[cmc][ch];
   1798               hitr++;
   1799          }
   1800     }
   1801     rv = soc_cmic_intr_register(unit, handle,
   1802                            CMIC_CMC_NUM_MAX*CMICX_N_DMA_CHAN);
   1803     sal_free(handle);
   1804 
   1805     /* Register the chain done interrupts */
   1806     handle = sal_alloc(sizeof(soc_cmic_intr_handler_t)*CMIC_CMC_NUM_MAX*
   1807                        CMICX_N_DMA_CHAN, "pktdma_chain_done_interrupt");
   1808     if (handle == NULL) {
   1809         return SOC_E_MEMORY;
   1810     }
   1811 
   1812     hitr = handle;
   1813 
   1814     for (cmc = 0; cmc < CMIC_CMC_NUM_MAX; cmc++) {
   1815          intr_base = cmicx_dma_get_intr_base(cmc);
   1816          for (ch = 0; ch < CMICX_N_DMA_CHAN; ch++) {
   1817               _intr_data[cmc][ch].cmc = cmc;
   1818               _intr_data[cmc][ch].ch = ch;
   1819               hitr->num = intr_base + (4 * ch) + CH_CHAIN_DONE;
   1820               hitr->intr_fn = cmicx_pktdma_ch_chain_done;
   1821               hitr->intr_data = &_intr_data[cmc][ch];
   1822               hitr++;
   1823          }
   1824     }
   1825     rv = soc_cmic_intr_register(unit, handle,
   1826                            CMIC_CMC_NUM_MAX*CMICX_N_DMA_CHAN);
   1827     sal_free(handle);
   1828 
   1829     /* Register the desc done interrupts */
   1830     handle = sal_alloc(sizeof(soc_cmic_intr_handler_t)*CMIC_CMC_NUM_MAX*
   1831                        CMICX_N_DMA_CHAN, "pktdma_descriptor_done_interrupt");
   1832     if (handle == NULL) {
   1833         return SOC_E_MEMORY;
   1834     }
   1835 
   1836     hitr = handle;
   1837 
   1838     for (cmc = 0; cmc < CMIC_CMC_NUM_MAX; cmc++) {
   1839          intr_base = cmicx_dma_get_intr_base(cmc);
   1840          for (ch = 0; ch < CMICX_N_DMA_CHAN; ch++) {
   1841               _intr_data[cmc][ch].cmc = cmc;
   1842               _intr_data[cmc][ch].ch = ch;
   1843               hitr->num = intr_base + (4 * ch) + CH_DESC_DONE;
   1844               hitr->intr_fn = cmicx_pktdma_ch_desc_done;
   1845               hitr->intr_data = &_intr_data[cmc][ch];
   1846               hitr++;
   1847          }
   1848     }
   1849     rv = soc_cmic_intr_register(unit, handle,
   1850                            CMIC_CMC_NUM_MAX*CMICX_N_DMA_CHAN);
   1851     sal_free(handle);
   1852 
   1853     return rv;
   1854 }
   1855 
   1856 /* Public Assignment Function */
   1857 
   1858 /*
   1859  * Function:
   1860  *      soc_cmicx_dma_drv_init
   1861  * Purpose:
   1862  *      Initialize the CMICX DMA driver for the specified SOC unit.
   1863  *      Assign function pointers for SOC DMA driver interface.
   1864  * Parameters:
   1865  *      unit - SOC unit #
   1866  *      drv  - pointer to the function vector list
   1867  * Returns:
   1868  *      SOC_E_NONE - success
   1869  *      SOC_E_XXXX - error code
   1870  * Notes:
   1871  */
   1872 int
   1873 soc_cmicx_dma_drv_init(int unit, soc_cmic_dma_drv_t *drv)
   1874 {
   1875     int rv = SOC_E_NONE;
   1876 
   1877     drv->init                         = cmicx_dma_init;
   1878     drv->ctrl_init                    = cmicx_dma_ctrl_init;
   1879     drv->chan_config                  = cmicx_dma_chan_config;
   1880     drv->chan_dv_start                = cmicx_dma_chan_dv_start;
   1881     drv->chan_start                   = cmicx_dma_chan_start;
   1882     drv->chan_poll                    = cmicx_dma_chan_poll;
   1883     drv->chan_abort                   = cmicx_dma_chan_abort;
   1884     drv->chan_tx_purge                = cmicx_dma_chan_tx_purge;
   1885     drv->chan_desc_done_intr_enable   = cmicx_dma_chan_desc_done_intr_enable;
   1886     drv->chan_desc_done               = cmicx_dma_chan_desc_done;
   1887     drv->chan_chain_done              = cmicx_dma_chan_chain_done;
   1888     drv->chan_reload_done             = cmicx_dma_chan_reload_done;
   1889     drv->chan_counter_get             = cmicx_dma_chan_counter_get;
   1890     drv->chan_counter_clear           = cmicx_dma_chan_counter_clear;
   1891     drv->chan_cos_ctrl_get            = cmicx_dma_chan_cos_ctrl_get;
   1892     drv->chan_cos_ctrl_set            = cmicx_dma_chan_cos_ctrl_set;
   1893     drv->chan_cos_ctrl_queue_get      = cmicx_dma_chan_cos_ctrl_queue_get;
   1894     drv->chan_cos_ctrl_reg_addr_get   = cmicx_dma_chan_cos_ctrl_reg_addr_get;
   1895     drv->chan_halt_get                = cmicx_dma_chan_halt_get;
   1896     drv->chan_status_get              = cmicx_dma_chan_status_get;
   1897     drv->chan_status_clear            = NULL;
   1898     drv->chan_ctrl_reg_get            = cmicx_dma_chan_ctrl_reg_get;
   1899     drv->chan_ctrl_reg_set            = cmicx_dma_chan_ctrl_reg_set;
   1900     drv->chan_rxbuf_threshold_cfg     = cmicx_dma_chan_rxbuf_threshold_config;
   1901     drv->cmc_rxbuf_threshold_cfg      = cmicx_dma_cmc_rxbuf_threshold_config;
   1902     drv->cmc_counter_get              = cmicx_dma_cmc_counter_get;
   1903     drv->cmc_counter_clear            = cmicx_dma_cmc_counter_clear;
   1904     drv->loopback_config              = cmicx_loopback_config;
   1905     drv->masks_get                    = cmicx_dma_masks_get;
   1906     drv->header_size_get              = cmicx_dma_header_size_get;
   1907     drv->max_rx_channels_get          = cmicx_dma_max_rx_channels_get;
   1908     drv->pci_timeout_handle           = NULL;
   1909 
   1910     return rv;
   1911 }
   1912 #endif /* BCM_CMICX_SUPPORT */