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_fifodma.c (31966B)


      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 FIFO DMA Driver
      8  */
      9 
     10 #include <shared/bsl.h>
     11 #include <shared/alloc.h>
     12 #include <soc/drv.h>
     13 #include <soc/debug.h>
     14 #include <soc/cm.h>
     15 #include <soc/fifodma_internal.h>
     16 
     17 #if defined(BCM_CMICX_SUPPORT)
     18 #include <soc/cmicx.h>
     19 #include <soc/intr_cmicx.h>
     20 
     21 #ifdef BCM_DNXF_SUPPORT
     22 #include <soc/dnxf/cmn/dnxf_drv.h>
     23 /*dnxf data*/
     24 #include <soc/dnxf/dnxf_data/auto_generated/dnxf_data_fabric.h>
     25 #endif
     26 
     27 #ifdef BCM_DNX_SUPPORT
     28 #include <sal/core/dpc.h>
     29 #include <soc/dnx/dnx_fifodma.h>
     30 #endif
     31 
     32 typedef struct fifodma_intr_data_s {
     33     int cmc;
     34     int ch;
     35 }fifodma_intr_data_t;
     36 
     37 static fifodma_intr_data_t _intr_data[CMIC_CMC_NUM_MAX][CMICX_N_FIFODMA_CHAN];
     38 
     39 /*
     40  * Function:
     41  *      cmicx_fifodma_ch_endian_set
     42  * Purpose:
     43  *      To set cmicx fifo dma channel endianness
     44  *
     45  * Parameters:
     46  *      unit    - SOC unit #
     47  *      channel - channel number
     48  *      be      - big_endian
     49  *
     50  * @returns SOC_E_NONE
     51  */
     52 int
     53 cmicx_fifodma_ch_endian_set(int unit, int channel, int be) {
     54     uint32 val = 0;
     55 
     56     val = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(channel));
     57     soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &val,
     58                       ENDIANESSf, be);
     59     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(channel), val);
     60     return SOC_E_NONE;
     61 }
     62 
     63 /*
     64  * Function:
     65  *      cmicx_ctr_evict_fifodma_done
     66  * Purpose:
     67  *      The interrupt handler for fifodma channel interrupt
     68  *
     69  * Parameters:
     70  *      unit  - SOC unit #
     71  *      *data - pointer provided during registration
     72  */
     73 
     74 static void
     75 cmicx_ctr_evict_fifodma_done(int unit, void *data)
     76 {
     77     soc_control_t *soc = SOC_CONTROL(unit);
     78     fifodma_intr_data_t *in_d = (fifodma_intr_data_t *)data;
     79 
     80     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
     81                       (BSL_META_U(unit,
     82                                   "fifo dma done cmc = %d ch = %d\n"),
     83                                   in_d->cmc, in_d->ch));
     84 
     85     soc_cmic_intr_disable(unit, INTR_FIFO_DMA(in_d->ch));
     86 
     87     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(in_d->ch), 0x3);
     88 
     89     if (soc->ctrEvictDmaIntrEnb) {
     90         SOC_CONTROL(unit)->stat.intr_fifo_dma[in_d->ch]++;
     91         sal_sem_give(soc->ctrEvictIntr);
     92     }
     93 }
     94 
     95 /*
     96  * Function:
     97  *      cmicx_l2_mod_fifodma_done
     98  * Purpose:
     99  *      The interrupt handler for fifodma channel interrupt
    100  *
    101  * Parameters:
    102  *      unit  - SOC unit #
    103  *      *data - pointer provided during registration
    104  */
    105 
    106 static void
    107 cmicx_l2_mod_fifodma_done(int unit, void *data)
    108 {
    109     soc_control_t *soc = SOC_CONTROL(unit);
    110     fifodma_intr_data_t *in_d = (fifodma_intr_data_t *)data;
    111 
    112     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    113                       (BSL_META_U(unit,
    114                                   "fifo dma done cmc = %d ch = %d\n"),
    115                                   in_d->cmc, in_d->ch));
    116 
    117     soc_cmic_intr_disable(unit, INTR_FIFO_DMA(in_d->ch));
    118 
    119     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(in_d->ch), 0x3);
    120 
    121     if (soc->l2modDmaIntrEnb) {
    122         SOC_CONTROL(unit)->stat.intr_fifo_dma[in_d->ch]++;
    123         sal_sem_give(soc->arl_notify);
    124     }
    125 }
    126 
    127 /*
    128  * Function:
    129  *      cmicx_bsc_export_fifodma_done
    130  * Purpose:
    131  *      The interrupt handler for fifodma channel interrupt
    132  *
    133  * Parameters:
    134  *      unit  - SOC unit #
    135  *      *data - pointer provided during registration
    136  */
    137 
    138 static void
    139 cmicx_bsc_export_fifodma_done(int unit, void *data)
    140 {
    141     fifodma_intr_data_t *in_d = (fifodma_intr_data_t *)data;
    142 
    143 #ifdef BCM_FLOWTRACKER_EXPORT_FIFO_SUPPORT
    144     soc_control_t *soc = SOC_CONTROL(unit);
    145 #endif /* BCM_FLOWTRACKER_EXPORT_FIFO_SUPPORT */
    146 
    147     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    148                       (BSL_META_U(unit,
    149                                   "fifo dma done cmc = %d ch = %d\n"),
    150                                   in_d->cmc, in_d->ch));
    151 
    152     soc_cmic_intr_disable(unit, INTR_FIFO_DMA(in_d->ch));
    153 
    154     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(in_d->ch), 0x3);
    155 
    156 #ifdef BCM_FLOWTRACKER_EXPORT_FIFO_SUPPORT
    157     if (soc->ftExportIntrEnb) {
    158         SOC_CONTROL(unit)->stat.intr_fifo_dma[in_d->ch]++;
    159         sal_sem_give(soc->ftExportIntr);
    160     }
    161 #endif /* BCM_FLOWTRACKER_EXPORT_FIFO_SUPPORT */
    162 }
    163 
    164 
    165 #ifdef BCM_DNXF_SUPPORT
    166 /*
    167  * Function:
    168  *      cmicx_dnxf_fifodma_done
    169  * Purpose:
    170  *      The interrupt handler for fifodma channel interrupt
    171  *
    172  * Parameters:
    173  *      unit  - SOC unit #
    174  *      *data - pointer provided during registration
    175  */
    176 static void
    177 cmicx_dnxf_fifodma_done(int unit, void *data)
    178 {
    179     fifodma_intr_data_t *in_d = (fifodma_intr_data_t *)data;
    180 
    181     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    182                       (BSL_META_U(unit,
    183                                   "fifo dma done cmc = %d ch = %d\n"),
    184                                   in_d->cmc, in_d->ch));
    185 
    186     soc_cmic_intr_disable(unit, INTR_FIFO_DMA(in_d->ch));
    187 
    188     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(in_d->ch), 0x3);
    189 
    190     if (dnxf_data_fabric.cell.fifo_dma_enable_get(unit) && SOC_DNXF_CONTROL(unit)->rx_thread_fifo_dma_semaphore != NULL) {
    191         SOC_CONTROL(unit)->stat.intr_fifo_dma[in_d->ch]++;
    192         sal_sem_give(SOC_DNXF_CONTROL(unit)->rx_thread_fifo_dma_semaphore);
    193     }
    194 }
    195 #endif
    196 
    197 
    198 #ifdef BCM_DNX_SUPPORT
    199 /*
    200  * Function:
    201  *      cmicx_dnx_fifodma_done
    202  * Purpose:
    203  *      The interrupt handler for dnx fifodma channel interrupt
    204  *
    205  * Parameters:
    206  *      unit  - SOC unit #
    207  *      *data - pointer provided during registration
    208  */
    209 
    210 static void
    211 cmicx_dnx_fifodma_done(int unit, void *data)
    212 {
    213     int rv;
    214     fifodma_intr_data_t *in_d = (fifodma_intr_data_t *)data;
    215 
    216     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    217                       (BSL_META_U(unit,
    218                                   "fifo dma done cmc = %d ch = %d\n"),
    219                                   in_d->cmc, in_d->ch));
    220 
    221     soc_cmic_intr_disable(unit, INTR_FIFO_DMA(in_d->ch));
    222     /** Clear HOSTMEM OVERFLOW and TIMEOUT interrupt */
    223     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(in_d->ch), 0x3);
    224     /** Handle under sal_dpc in case this might be a long operation in the interrupt context */
    225     rv = sal_dpc(dnx_fifodma_intr_handler, INT_TO_PTR(unit), INT_TO_PTR(in_d->ch), NULL, NULL, NULL);
    226     if (rv)
    227     {
    228         LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    229                           (BSL_META_U(unit,
    230                                       "DPC failed to execute fifo dma handler for cmc = %d ch = %d\n"),
    231                                       in_d->cmc, in_d->ch));
    232 
    233         /*
    234          * Interrupt is enabled in dnx_fifodma_intr_handler.
    235          * In the case of DPC failure, interrupt is disabled forerver, so enable it here.
    236          */
    237         soc_cmic_intr_enable(unit, INTR_FIFO_DMA(in_d->ch));
    238     }
    239 }
    240 #endif
    241 
    242 /**
    243  * Function used to (partially) configure the DMA to
    244  * write to a redirect writes from a register/memory
    245  * to a host memory.
    246  *
    247  *
    248  * @param unit
    249  * @param ch - Channel used. should be between 0 and 3.
    250  * @param is_mem
    251  * @param mem -name of memory, if memory is used (0 otherwise).
    252  * @param reg - name of register, if register used (0 otherwise).
    253  * @param copyno
    254  * @param force_entry_size - in a case that entry size does not match
    255  *        the register\memory size  - ignore when equals to 0.
    256  * @param host_entries  - number of host entries used by the DMA.
    257  *  Must be a power of 2 between 64 and 16384.
    258  *  Note that only after host_entries writes does the DMA wrap around the host_buff.
    259  * @param host_buff - local memory on which the DMA writes. should be big enough to
    260  *                     allow host_entries writes,
    261  * in other words whould be the size of host_entries * ( size of memory or
    262  *                         register used, in bytes).
    263  *
    264  * Other register the caller may need to configure seperatly:
    265  *  CMIC_CMCx_FIFO_CHy_RD_DMA_HOSTMEM_THRESHOLD - The amount of writes by the DMA until a
    266  *  threshold based interrupt occurs.
    267  *
    268  *  TIMEOUT_COUNT field in CMIC_CMCx_FIFO_CHy_RD_DMA - Time between a DMA write and a
    269  *                          timeout based interrupt.
    270  *  (May be set to 0 to disable timeout based interrupts).
    271  *
    272  *  Endianess field in CMIC_CMCx_FIFO_CHy_RD_DMA.
    273  *
    274  * @return int - success or failure.
    275  */
    276 
    277 static int
    278 soc_fifo_dma_start_memreg(int unit, int ch,
    279                                     int is_mem, soc_mem_t mem, soc_reg_t reg,
    280                                     int copyno, int force_entry_size,
    281                                     int host_entries, void *host_buff)
    282 {
    283     uint8 at;
    284     uint32 rval, data_beats, sel;
    285     int blk;
    286     schan_msg_t msg;
    287     int acc_type;
    288     sal_paddr_t     addr;
    289 
    290     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    291                       (BSL_META_U(unit,
    292                                   "cmicx fifodma start for chan %d, host entries %d\n"),
    293                                   ch, host_entries));
    294 
    295     if (ch < 0 || ch > 12 || host_buff == NULL) {
    296         return SOC_E_PARAM;
    297     }
    298 
    299     switch (host_entries) {
    300         case 64:    sel = 0; break;
    301         case 128:   sel = 1; break;
    302         case 256:   sel = 2; break;
    303         case 512:   sel = 3; break;
    304         case 1024:  sel = 4; break;
    305         case 2048:  sel = 5; break;
    306         case 4096:  sel = 6; break;
    307         case 8192:  sel = 7; break;
    308         case 16384: sel = 8; break;
    309         default:
    310            return SOC_E_PARAM;
    311     }
    312 
    313     /* Differentiate between reg and mem to get address, size and block */
    314     if ((!is_mem) && SOC_REG_IS_VALID(unit, reg)) {
    315         data_beats = BYTES2WORDS(soc_reg_bytes(unit, reg));
    316         rval = soc_reg_addr_get(unit, reg, REG_PORT_ANY, 0,
    317                                 SOC_REG_ADDR_OPTION_NONE, &blk, &at);
    318     } else {
    319         data_beats = soc_mem_entry_words(unit, mem);
    320         if (copyno == MEM_BLOCK_ANY) {
    321             copyno = SOC_MEM_BLOCK_ANY(unit, mem);
    322         }
    323         rval = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at);
    324         blk = SOC_BLOCK2SCH(unit, copyno);
    325     }
    326 
    327     /* Force entry size */
    328     if (force_entry_size > 0)
    329     {
    330         data_beats = BYTES2WORDS(force_entry_size);
    331     }
    332 
    333     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_SBUS_START_ADDRESS_OFFSET(ch), rval);
    334 
    335     schan_msg_clear(&msg);
    336     if (is_mem) {
    337         acc_type = SOC_MEM_ACC_TYPE(unit, mem);
    338     } else {
    339         acc_type = 0;
    340     }
    341 
    342     soc_schan_header_cmd_set(unit, &msg.header, FIFO_POP_CMD_MSG, blk, 0,
    343                              acc_type, 4, 0, 0);
    344     /* Set 1st schan ctrl word as opcode */
    345     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_OPCODE_OFFSET(ch), msg.dwords[0]);
    346 
    347     addr = soc_cm_l2p(unit, host_buff);
    348 
    349     soc_pci_write(unit,
    350                   CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_HOSTMEM_START_ADDRESS_LO_OFFSET(ch),
    351                   PTR_TO_INT(addr));
    352     if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) {
    353         soc_pci_write(unit,
    354                   CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_HOSTMEM_START_ADDRESS_HI_OFFSET(ch),
    355                   (CMIC_PCIE_SO_OFFSET | PTR_HI_TO_INT(addr)));
    356     } else {
    357         soc_pci_write(unit,
    358                   CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_HOSTMEM_START_ADDRESS_HI_OFFSET(ch),
    359                   (PTR_HI_TO_INT(addr)));
    360     }
    361 
    362     rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch));
    363 
    364     soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval,
    365                       BEAT_COUNTf, data_beats);
    366     soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval,
    367                       HOST_NUM_ENTRIES_SELf, sel);
    368     soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval,
    369                       ABORTf, 0);
    370     soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval,
    371                       TIMEOUT_COUNTf, 1000);
    372     soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval,
    373                       NACK_FATALf, 1);
    374 
    375     if (soc_feature(unit, soc_feature_multi_sbus_cmds)) {
    376         
    377     }
    378 
    379     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch), rval);
    380 
    381     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_HOSTMEM_THRESHOLD_OFFSET(ch),
    382                  host_entries/10);
    383 
    384     soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval, ENABLEf, 1);
    385     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch), rval);
    386 
    387     return SOC_E_NONE;
    388 }
    389 
    390 /*******************************************
    391 * @function _cmicx_fifodma_start
    392 * purpose to start fifo dma channel
    393 *
    394 * @param unit [in] unit #
    395 * @param ch [in] channel number
    396 *
    397 * @returns SOC_E_PARAM
    398 * @returns SOC_E_NONE
    399 *
    400 * @end
    401  */
    402 static int
    403 _cmicx_fifodma_start(int unit, int ch, int is_mem,
    404                   soc_mem_t mem, soc_reg_t reg,
    405                   int copyno, int force_entry_size,
    406                   int host_entries, void *host_buff)
    407 {
    408     return soc_fifo_dma_start_memreg(unit, ch,
    409                                      is_mem, mem, reg,
    410                                      copyno, force_entry_size, host_entries, host_buff);
    411 }
    412 
    413 /*******************************************
    414 * @function _cmicx_fifodma_stop
    415 * purpose to stop fifo dma channel
    416 *
    417 * @param unit [in] unit #
    418 * @param chan [in] channel number
    419 *
    420 * @returns SOC_E_BUSY
    421 * @returns SOC_E_NONE
    422 *
    423 * @end
    424  */
    425 static int
    426 _cmicx_fifodma_stop(int unit, int ch)
    427 {
    428     int iter = 0;
    429     uint32 rval;
    430     int to = SAL_BOOT_QUICKTURN ? 30000000 : 10000000;
    431     uint32 aborted = 0;
    432 
    433     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    434                       (BSL_META_U(unit,
    435                                   "cmicx fifodma stop for chan %d\n"), ch));
    436 
    437     if (ch < 0 || ch > 12) {
    438         return SOC_E_PARAM;
    439     }
    440 
    441     rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch));
    442     if (!soc_reg_field_get(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, rval, ENABLEf)) {
    443         return SOC_E_NONE;
    444     }
    445 
    446     rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch));
    447     soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval, ABORTf, 1);
    448     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch), rval);
    449 
    450     sal_udelay(1000);
    451     rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_OFFSET(ch));
    452     aborted = soc_reg_field_get(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_STATr,
    453                                 rval, ABORTEDf);
    454     if (SAL_BOOT_BCMSIM) {
    455         aborted = 1;
    456     }
    457     while (aborted == 0 && iter++ < to) {
    458         sal_udelay(1000);
    459         rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_OFFSET(ch));
    460         aborted = soc_reg_field_get(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_STATr,
    461                                     rval, ABORTEDf);
    462     }
    463 
    464     rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch));
    465     soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval, ENABLEf, 0);
    466     soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch), rval);
    467 
    468     if (iter >= to) {
    469         LOG_ERROR(BSL_LS_SOC_FIFODMA,
    470                   (BSL_META_U(unit,
    471                               "FIFO DMA abort failed !!\n")));
    472         return SOC_E_INTERNAL;
    473     }
    474 
    475     return SOC_E_NONE;
    476 
    477 }
    478 
    479 
    480 /*******************************************
    481 * @function _cmicx_fifodma_intr_enable
    482 * purpose to enable interrupt
    483 *
    484 * @param unit [in] unit #
    485 * @param ch [in] channel
    486 *
    487 * @returns SOC_E_BUSY
    488 * @returns SOC_E_NONE
    489 *
    490 * @end
    491  */
    492 static int
    493 _cmicx_fifodma_intr_enable(int unit, int ch)
    494 {
    495     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    496                       (BSL_META_U(unit,
    497                                   "cmicx fifodma interrupt enable for chan %d\n"), ch));
    498 
    499     soc_cmic_intr_enable(unit, INTR_FIFO_DMA(ch));
    500 
    501     return 0;
    502 }
    503 
    504 /*******************************************
    505 * @function _cmicx_fifodma_intr_disable
    506 * purpose to disable interrupt
    507 *
    508 * @param unit [in] unit #
    509 * @param ch [in] channel
    510 *
    511 * @returns SOC_E_BUSY
    512 * @returns SOC_E_NONE
    513 *
    514 * @end
    515  */
    516 static int
    517 _cmicx_fifodma_intr_disable(int unit, int ch)
    518 {
    519     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    520                       (BSL_META_U(unit,
    521                                   "cmicx fifodma interrupt disable for chan %d\n"), ch));
    522 
    523     soc_cmic_intr_disable(unit, INTR_FIFO_DMA(ch));
    524 
    525     return 0;
    526 }
    527 
    528 /*******************************************
    529 * @function _cmicx_fifodma_get_read_ptr
    530 * purpose to get read ptr
    531 *
    532 * @param unit [in] unit #
    533 *
    534 * @returns SOC_E_BUSY
    535 * @returns SOC_E_NONE
    536 *
    537 * @end
    538  */
    539 static int
    540 _cmicx_fifodma_get_read_ptr(int unit, int chan, void **host_ptr, int *count)
    541 {
    542     return 0;
    543 }
    544 
    545 /*******************************************
    546 * @function _cmicx_fifodma_advance_read_ptr
    547 * purpose to advance read ptr
    548 *
    549 * @param unit [in] unit #
    550 *
    551 * @returns SOC_E_BUSY
    552 * @returns SOC_E_NONE
    553 *
    554 * @end
    555  */
    556 static int
    557 _cmicx_fifodma_advance_read_ptr(int unit, int chan, int count)
    558 {
    559     return 0;
    560 }
    561 
    562 /*******************************************
    563 * @function _cmicx_fifodma_set_entries_read
    564 * purpose to read set entries
    565 *
    566 * @param unit [in] unit #
    567 *
    568 * @returns SOC_E_BUSY
    569 * @returns SOC_E_NONE
    570 *
    571 * @end
    572  */
    573 static int
    574 _cmicx_fifodma_set_entries_read(int unit, int ch, uint32 num)
    575 {
    576     uint32 rval = 0;
    577 
    578     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    579                       (BSL_META_U(unit,
    580                                   "cmicx fifodma set %d entries for chan %d\n"), num, ch));
    581 
    582     if (ch < 0 || ch > 12) {
    583         return SOC_E_PARAM;
    584     }
    585 
    586     soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_NUM_OF_ENTRIES_READ_FRM_HOSTMEMr, &rval,
    587                       ENTRYCOUNTf, num);
    588     soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_NUM_OF_ENTRIES_READ_FRM_HOSTMEMr, &rval,
    589                       WR_NUMBER_OF_ENTRIESf, 1);
    590 
    591     soc_pci_write(unit,
    592         CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_NUM_OF_ENTRIES_READ_FRM_HOSTMEM_OFFSET(ch), rval);
    593 
    594     return SOC_E_NONE;
    595 }
    596 
    597 /*******************************************
    598 * @function _cmicx_fifodma_num_entries_get
    599 * purpose to get number of entries
    600 *
    601 * @param unit [in] unit #
    602 *
    603 * @returns SOC_E_BUSY
    604 * @returns SOC_E_NONE
    605 *
    606 * @end
    607  */
    608 static int
    609 _cmicx_fifodma_num_entries_get(int unit, int ch, int *count)
    610 {
    611     uint32 val = 0;
    612 
    613     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    614                       (BSL_META_U(unit,
    615                                   "cmicx fifodma entries get for chan %d\n"), ch));
    616 
    617     if (ch < 0 || ch > 12) {
    618         return SOC_E_PARAM;
    619     }
    620 
    621     val = soc_pci_read(unit,
    622                   CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_NUM_OF_ENTRIES_VALID_IN_HOSTMEM_OFFSET(ch));
    623 
    624     *count = val;
    625 
    626     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    627                       (BSL_META_U(unit,
    628                                   "cmicx fifodma %d entries get for chan %d\n"), val, ch));
    629     if (val) {
    630         return SOC_E_NONE;
    631     }
    632 
    633     return SOC_E_EMPTY;
    634 }
    635 
    636 /*******************************************
    637 * @function _cmicx_fifodma_status_clear
    638 * purpose to clear fifo dma channel status
    639 *
    640 * @param unit [in] unit #
    641 * @param chan [in] channel number
    642 *
    643 * @returns SOC_E_BUSY
    644 * @returns SOC_E_NONE
    645 *
    646 * @end
    647  */
    648 static int
    649 _cmicx_fifodma_status_clear(int unit, int chan)
    650 {
    651     soc_reg_t stat_clr_reg;
    652     uint32 stat_clr_addr;
    653     uint32 stat_clr_mask;
    654 
    655     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    656                       (BSL_META_U(unit,
    657                                   "cmicx fifodma status clear for chan %d\n"), chan));
    658 
    659     if (chan < 0 || chan > 12) {
    660         return SOC_E_PARAM;
    661     }
    662 
    663     stat_clr_reg = CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_STATr;
    664     stat_clr_mask = 0;
    665     soc_reg_field_set(unit, stat_clr_reg, &stat_clr_mask, HOSTMEM_TIMEOUTf, 1);
    666     soc_reg_field_set(unit, stat_clr_reg, &stat_clr_mask, HOSTMEM_OVERFLOWf, 1);
    667 
    668     stat_clr_addr = CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(chan);
    669 
    670     soc_pci_write(unit, stat_clr_addr, stat_clr_mask);
    671 
    672     return SOC_E_NONE;
    673 }
    674 
    675 /*******************************************
    676 * @function _cmicx_fifodma_status_get
    677 * purpose to obtain fifo dma channel status
    678 *
    679 * @param unit [in] unit #
    680 * @param chan [in] channel number
    681 *
    682 * @returns SOC_E_BUSY
    683 * @returns SOC_E_NONE
    684 *
    685 * @end
    686  */
    687 static int
    688 _cmicx_fifodma_status_get(int unit, int chan, uint32 *status)
    689 {
    690     uint32 stat_addr;
    691 
    692     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    693                       (BSL_META_U(unit,
    694                                   "cmicx fifodma status get for chan %d\n"), chan));
    695 
    696     if (chan < 0 || chan > 12) {
    697         return SOC_E_PARAM;
    698     }
    699 
    700     stat_addr = CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_OFFSET(chan);
    701 
    702     *status = soc_pci_read(unit, stat_addr);
    703 
    704     return SOC_E_NONE;
    705 }
    706 
    707 /*******************************************
    708 * @function _cmicx_fifodma_masks_get
    709 * purpose to obtain fifodma masks
    710 *
    711 * @param unit [in] unit #
    712 * @param chan [in] channel number
    713 *
    714 * @returns SOC_E_BUSY
    715 * @returns SOC_E_NONE
    716 *
    717 * @end
    718  */
    719 static int
    720 _cmicx_fifodma_masks_get(int unit, uint32 *hostmem_timeout, uint32 *hostmem_overflow, uint32 *error, uint32 *done)
    721 {
    722     int rv   = SOC_E_NONE;
    723 
    724     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    725                       (BSL_META_U(unit,
    726                                   "cmicx fifodma masks get\n")));
    727 
    728     *hostmem_timeout  = 1 << 3;
    729     *hostmem_overflow = 1 << 2;
    730     *error            = 1 << 0;
    731     *done             = 1 << 4;
    732 
    733     return rv;
    734 }
    735 
    736 /*******************************************
    737 * @function _cmicx_l2mod_sbus_fifo_field_set
    738 * obtain l2 mod sbus field set
    739 *
    740 * @param unit   [in] unit #
    741 * @param field  [in] field
    742 * @param enable [in] enable
    743 *
    744 * @returns SOC_E_BUSY
    745 * @returns SOC_E_NONE
    746 *
    747 * @end
    748  */
    749 static int
    750 _cmicx_l2mod_sbus_fifo_field_set(int unit, soc_field_t field, int enable)
    751 {
    752     uint32 rval = 0;
    753     uint32 fval = enable?1:0;
    754 
    755     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    756                       (BSL_META_U(unit,
    757                                   "cmicx l2mod sbus fifo set\n")));
    758 
    759     if (SOC_IS_TRIDENT3X(unit)) {
    760         if(soc_reg_field_valid(unit, L2_MOD_FIFO_ENABLEr, field)) {
    761             SOC_IF_ERROR_RETURN(READ_L2_MOD_FIFO_ENABLEr(unit, &rval));
    762 
    763             soc_reg_field_set(unit, L2_MOD_FIFO_ENABLEr, &rval, field, fval);
    764 
    765             SOC_IF_ERROR_RETURN(WRITE_L2_MOD_FIFO_ENABLEr(unit, rval));
    766         }
    767         return SOC_E_NONE;
    768     }
    769 
    770     return SOC_E_UNAVAIL;
    771 }
    772 
    773 /*******************************************
    774 * @function _cmicx_l2mod_sbus_fifo_field_get
    775 * obtain l2 mod sbus field get
    776 *
    777 * @param unit   [in] unit #
    778 * @param field  [in] field
    779 * @param enable [in] enable
    780 *
    781 * @returns SOC_E_BUSY
    782 * @returns SOC_E_NONE
    783 *
    784 * @end
    785  */
    786 static int
    787 _cmicx_l2mod_sbus_fifo_field_get(int unit, soc_field_t field, int *enable)
    788 {
    789     uint32 reg = 0;
    790     uint32 fval = 0;
    791 
    792     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    793                       (BSL_META_U(unit,
    794                                   "cmicx l2mod sbus fifo get\n")));
    795 
    796 
    797     if (SOC_IS_TRIDENT3X(unit)) {
    798         if(soc_reg_field_valid(unit, L2_MOD_FIFO_ENABLEr, field)) {
    799             SOC_IF_ERROR_RETURN(READ_L2_MOD_FIFO_ENABLEr(unit, &reg));
    800 
    801             fval = soc_reg_field_get(unit, L2_MOD_FIFO_ENABLEr, reg, field);
    802         }
    803         *enable = fval?1:0;
    804         return SOC_E_NONE;
    805     }
    806 
    807     return SOC_E_UNAVAIL;
    808 }
    809 
    810 /*******************************************
    811 * @function cmicx_fifodma_init
    812 * purpose API to Initialize cmicx FIFO DMA
    813 *
    814 * @param unit [in] unit
    815 * @param drv [out] soc_fifodma_drv_t pointer
    816 *
    817 * @returns SOC_E_NONE
    818 * @returns SOC_E_XXX
    819 *
    820 * @end
    821  */
    822 int cmicx_fifodma_init(int unit, soc_fifodma_drv_t *drv)
    823 {
    824     int rv = SOC_E_NONE;
    825     int cmc = 0;
    826     soc_cmic_intr_handler_t *handle;
    827     soc_cmic_intr_handler_t *hitr;
    828     uint32 val, y;
    829     int nof_channels = CMICX_N_FIFODMA_CHAN;
    830 
    831     LOG_VERBOSE(BSL_LS_SOC_FIFODMA,
    832                       (BSL_META_U(unit,
    833                                   "cmicx fifo dma init, registering interrupts\n")));
    834 
    835     /* Register the descriptor done interrupts */
    836     handle = sal_alloc(sizeof(soc_cmic_intr_handler_t)*CMICX_N_FIFODMA_CHAN,
    837                        "fifodma_interrupt");
    838     if (handle == NULL) {
    839         return SOC_E_MEMORY;
    840     }
    841 
    842     hitr = handle;
    843 
    844 #ifdef BCM_DNXF_SUPPORT
    845     if (SOC_IS_DNXF(unit))
    846     {
    847         int ch = 0;
    848 
    849         /* Number of supported channels */
    850         nof_channels = dnxf_data_fabric.cell.fifo_dma_nof_channels_get(unit);
    851 
    852         for (ch = 0; ch < nof_channels; ++ch)
    853         {
    854             _intr_data[cmc][0].cmc = cmc;
    855             _intr_data[cmc][0].ch = ch;
    856             hitr->num = INTR_FIFO_DMA(ch);
    857             hitr->intr_fn = cmicx_dnxf_fifodma_done;
    858             hitr->intr_data = &_intr_data[cmc][ch];
    859             hitr++;
    860         }
    861     }
    862     else
    863 #endif
    864 #ifdef BCM_DNX_SUPPORT
    865     if (SOC_IS_DNX(unit))
    866     {
    867         int ch = 0;
    868         /* Number of supported channels */
    869         for(ch = 0; ch < CMICX_N_FIFODMA_CHAN; ch++) {
    870             _intr_data[cmc][ch].cmc = cmc;
    871             _intr_data[cmc][ch].ch = ch;
    872             hitr->num = INTR_FIFO_DMA(ch);
    873             hitr->intr_fn = cmicx_dnx_fifodma_done;
    874             hitr->intr_data = &_intr_data[cmc][ch];
    875             hitr++;
    876         }
    877     }
    878     else
    879 #endif
    880 
    881     {
    882         /* For Channel 0 */
    883         _intr_data[cmc][0].cmc = cmc;
    884         _intr_data[cmc][0].ch = 0;
    885         hitr->num = INTR_FIFO_DMA(0);
    886         hitr->intr_fn = cmicx_l2_mod_fifodma_done;
    887         hitr->intr_data = &_intr_data[cmc][0];
    888         hitr++;
    889         /* For Channel 1 */
    890         _intr_data[cmc][1].cmc = cmc;
    891         _intr_data[cmc][1].ch = 1;
    892         hitr->num = INTR_FIFO_DMA(1);
    893         hitr->intr_fn = cmicx_ctr_evict_fifodma_done;
    894         hitr->intr_data = &_intr_data[cmc][1];
    895         hitr++;
    896 
    897         /* For Channel 2 */
    898         _intr_data[cmc][2].cmc = cmc;
    899         _intr_data[cmc][2].ch = 2;
    900         hitr->num = INTR_FIFO_DMA(2);
    901         hitr->intr_fn = cmicx_bsc_export_fifodma_done;
    902         hitr->intr_data = &_intr_data[cmc][2];
    903         hitr++;
    904     }
    905 
    906     rv = soc_cmic_intr_register(unit, handle,
    907                                 nof_channels);
    908     sal_free(handle);
    909 
    910     /*
    911      * Set CMIC_COMMON_POOL_SHARED_CONFIG Register,
    912      * FIFO DMA are sent through AXI master port of CMC0
    913      */
    914     val = soc_pci_read(unit, CMIC_COMMON_POOL_SHARED_CONFIG_OFFSET);
    915 
    916     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_CONFIGr,
    917                       &val, MAP_FIFODMA_SLICE2_MEMWR_REQf,
    918                       MAP_FIFO_DMA_MEMWR_REQ_CMC0);
    919 
    920     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_CONFIGr,
    921                       &val, MAP_FIFODMA_SLICE1_MEMWR_REQf,
    922                       MAP_FIFO_DMA_MEMWR_REQ_CMC0);
    923 
    924     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_CONFIGr,
    925                       &val, MAP_FIFODMA_SLICE0_MEMWR_REQf,
    926                       MAP_FIFO_DMA_MEMWR_REQ_CMC0);
    927 
    928     soc_pci_write(unit, CMIC_COMMON_POOL_SHARED_CONFIG_OFFSET, val);
    929 
    930     /*
    931      * Programming WRR (Arbitration) within CMC. Configure WRR weight
    932      * for FIFO DMA channels. The defaults should work but still
    933      * writing the defaults.
    934      */
    935     val = soc_pci_read(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_ARB_CTRL_OFFSET);
    936 
    937     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_ARB_CTRLr,
    938                       &val, SLICE2_MEMWR_WRR_WEIGHTf,
    939                       CMICX_FIFO_DMA_MEMWR_WRR_WEIGHT);
    940 
    941     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_ARB_CTRLr,
    942                       &val, SLICE1_MEMWR_WRR_WEIGHTf,
    943                       CMICX_FIFO_DMA_MEMWR_WRR_WEIGHT);
    944 
    945     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_ARB_CTRLr,
    946                       &val, SLICE0_MEMWR_WRR_WEIGHTf,
    947                       CMICX_FIFO_DMA_MEMWR_WRR_WEIGHT);
    948 
    949     soc_pci_write(unit,
    950                   CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_ARB_CTRL_OFFSET,
    951                   val);
    952 
    953     val = soc_pci_read(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_OFFSET);
    954 
    955     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr,
    956                       &val, CHANNEL0_MEMWR_AXI_IDf,
    957                       CMICX_FIFO_DMA_AXI_ID);
    958 
    959     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr,
    960                       &val, CHANNEL1_MEMWR_AXI_IDf,
    961                       CMICX_FIFO_DMA_AXI_ID);
    962 
    963     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr,
    964                       &val, CHANNEL2_MEMWR_AXI_IDf,
    965                       CMICX_FIFO_DMA_AXI_ID);
    966 
    967     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr,
    968                       &val, CHANNEL3_MEMWR_AXI_IDf,
    969                       CMICX_FIFO_DMA_AXI_ID);
    970 
    971     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr,
    972                       &val, CHANNEL4_MEMWR_AXI_IDf,
    973                       CMICX_FIFO_DMA_AXI_ID);
    974 
    975     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr,
    976                       &val, CHANNEL5_MEMWR_AXI_IDf,
    977                       CMICX_FIFO_DMA_AXI_ID);
    978 
    979     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr,
    980                       &val, CHANNEL6_MEMWR_AXI_IDf,
    981                       CMICX_FIFO_DMA_AXI_ID);
    982 
    983     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr,
    984                       &val, CHANNEL7_MEMWR_AXI_IDf,
    985                       CMICX_FIFO_DMA_AXI_ID);
    986 
    987     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr,
    988                       &val, CHANNEL8_MEMWR_AXI_IDf,
    989                       CMICX_FIFO_DMA_AXI_ID);
    990 
    991     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr,
    992                       &val, CHANNEL9_MEMWR_AXI_IDf,
    993                       CMICX_FIFO_DMA_AXI_ID);
    994 
    995     soc_pci_write(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_OFFSET, val);
    996 
    997 
    998     val = soc_pci_read(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_1_OFFSET);
    999 
   1000     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_1r,
   1001                       &val, CHANNEL10_MEMWR_AXI_IDf,
   1002                       CMICX_FIFO_DMA_AXI_ID);
   1003 
   1004     soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_1r,
   1005                       &val, CHANNEL11_MEMWR_AXI_IDf,
   1006                       CMICX_FIFO_DMA_AXI_ID);
   1007 
   1008     soc_pci_write(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_1_OFFSET, val);
   1009 
   1010     for(y = 0; y < CMICX_N_FIFODMA_CHAN; y++) {
   1011         cmicx_fifodma_ch_endian_set(unit, y, 0);
   1012     }
   1013 
   1014     drv->fifodma_start             = _cmicx_fifodma_start;
   1015     drv->fifodma_stop              = _cmicx_fifodma_stop;
   1016     drv->fifodma_intr_enable       = _cmicx_fifodma_intr_enable;
   1017     drv->fifodma_intr_disable      = _cmicx_fifodma_intr_disable;
   1018     drv->fifodma_get_read_ptr      = _cmicx_fifodma_get_read_ptr;
   1019     drv->fifodma_advance_read_ptr  = _cmicx_fifodma_advance_read_ptr;
   1020     drv->fifodma_set_entries_read  = _cmicx_fifodma_set_entries_read;
   1021     drv->fifodma_num_entries_get   = _cmicx_fifodma_num_entries_get;
   1022     drv->fifodma_status_clear      = _cmicx_fifodma_status_clear;
   1023     drv->fifodma_status_get        = _cmicx_fifodma_status_get;
   1024     drv->fifodma_masks_get         = _cmicx_fifodma_masks_get;
   1025     drv->l2mod_sbus_fifo_field_set = _cmicx_l2mod_sbus_fifo_field_set;
   1026     drv->l2mod_sbus_fifo_field_get = _cmicx_l2mod_sbus_fifo_field_get;
   1027 
   1028     return(rv);
   1029 }
   1030 
   1031 /*******************************************
   1032 * @function cmicx_fifodma_deinit
   1033 * purpose API to Deinitialize cmicx FIFO DMA
   1034 *
   1035 * @param unit [in] unit
   1036 * @param drv [in] soc_fifodma_drv_t pointer
   1037 *
   1038 * @returns SOC_E_NONE
   1039 
   1040 *
   1041 * @end
   1042  */
   1043 int cmicx_fifodma_deinit(int unit, soc_fifodma_drv_t *drv)
   1044 {
   1045     drv->fifodma_start             = NULL;
   1046     drv->fifodma_stop              = NULL;
   1047     drv->fifodma_intr_enable       = NULL;
   1048     drv->fifodma_intr_disable      = NULL;
   1049     drv->fifodma_get_read_ptr      = NULL;
   1050     drv->fifodma_advance_read_ptr  = NULL;
   1051     drv->fifodma_set_entries_read  = NULL;
   1052     drv->fifodma_num_entries_get   = NULL;
   1053     drv->fifodma_status_clear      = NULL;
   1054     drv->fifodma_status_get        = NULL;
   1055     drv->fifodma_masks_get         = NULL;
   1056     drv->l2mod_sbus_fifo_field_set = NULL;
   1057     drv->l2mod_sbus_fifo_field_get = NULL;
   1058 
   1059     return SOC_E_NONE;
   1060 }
   1061 
   1062 #endif /* BCM_CMICX_SUPPORT */
   1063