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_sbusdma_common.c (23428B)


      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 SBUS-DMA Common utility functions
      8  */
      9 
     10 #include <shared/bsl.h>
     11 #include <soc/debug.h>
     12 #include <soc/cm.h>
     13 #include <sal/core/sync.h>
     14 #include <soc/util.h>
     15 #include <soc/drv.h>
     16 #include <soc/sbusdma_internal.h>
     17 
     18 #if defined(BCM_CMICX_SUPPORT) && defined(BCM_SBUSDMA_SUPPORT)
     19 #include <soc/cmicx.h>
     20 #include <soc/intr_cmicx.h>
     21 
     22 
     23 typedef struct intr_data_s {
     24     int cmc;
     25     int ch;
     26 }intr_data_t;
     27 
     28 
     29 typedef struct cmicx_sbusdma_ch_s {
     30     sal_spinlock_t   lock[SOC_MAX_NUM_DEVICES];
     31     int timeout;
     32     sal_sem_t sem[SOC_MAX_NUM_DEVICES];
     33     uint8  ch[SOC_MAX_NUM_DEVICES][CMIC_CMC_NUM_MAX];
     34     uint8  wait[SOC_MAX_NUM_DEVICES][CMIC_CMC_NUM_MAX];
     35 }cmicx_sbusdma_ch_t;
     36 
     37 
     38 STATIC intr_data_t _intr_data[CMIC_CMC_NUM_MAX][CMIC_CMCx_SBUSDMA_CHAN_MAX];
     39 
     40 STATIC cmicx_sbusdma_ch_t  _cmicx_sbusdma_ch;
     41 
     42 
     43 /*******************************************
     44 * @function cmicx_sbusdma_curr_op_details
     45 * purpose Print operation details
     46 *
     47 * @param unit [in] unit
     48 * @param cmc [in] cmc number
     49 * @param ch [in] channel number
     50 *
     51 * @returns SOC_E_NONE
     52 * @returns SOC_E_XXX
     53 *
     54 * @end
     55  */
     56 void
     57 cmicx_sbusdma_curr_op_details(int unit, int cmc, int ch)
     58 {
     59     uint32 rval;
     60 
     61     /* Set up the trigger incase PCI trace need to be taken */
     62     soc_pci_analyzer_trigger(unit);
     63 
     64     rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch));
     65     LOG_WARN(BSL_LS_SOC_COMMON,
     66              (BSL_META_U(unit,
     67                          "STATUS: 0x%08x. cmc = %d, ch = %d\n"), rval, cmc, ch));
     68     rval = soc_pci_read(unit,
     69                         CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSDMA_CONFIG_OPCODE(cmc, ch));
     70     LOG_WARN(BSL_LS_SOC_COMMON,
     71              (BSL_META_U(unit,
     72                          "OPCODE: 0x%08x\n"), rval));
     73     rval = soc_pci_read(unit,
     74                         CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSDMA_CONFIG_ADDR_LO(cmc, ch));
     75     LOG_WARN(BSL_LS_SOC_COMMON,
     76              (BSL_META_U(unit,
     77                          "HOSTMEM ADDR LO: 0x%08x\n"), rval));
     78     rval = soc_pci_read(unit,
     79                         CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSDMA_CONFIG_ADDR_HI(cmc, ch));
     80     LOG_WARN(BSL_LS_SOC_COMMON,
     81              (BSL_META_U(unit,
     82                          "HOSTMEM ADDR HI: 0x%08x\n"), rval));
     83     rval = soc_pci_read(unit,
     84                    CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSDMA_CONFIG_SBUS_START_ADDRESS(cmc, ch));
     85     LOG_WARN(BSL_LS_SOC_COMMON,
     86              (BSL_META_U(unit,
     87                          "START ADDR: 0x%08x\n"), rval));
     88     rval = soc_pci_read(unit,
     89                        CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSDMA_CONFIG_COUNT(cmc, ch));
     90     LOG_WARN(BSL_LS_SOC_COMMON,
     91              (BSL_META_U(unit,
     92                          "COUNT: 0x%08x\n"), rval));
     93     rval = soc_pci_read(unit,
     94                        CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSDMA_CONFIG_REQUEST(cmc, ch));
     95     LOG_WARN(BSL_LS_SOC_COMMON,
     96              (BSL_META_U(unit,
     97                          "REQUEST: 0x%08x\n"), rval));
     98 
     99     rval = soc_pci_read(unit,
    100                        CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSDMA_ITER_COUNT(cmc, ch));
    101     LOG_WARN(BSL_LS_SOC_COMMON,
    102              (BSL_META_U(unit,
    103                          "ITER COUNT: 0x%08x\n"), rval));
    104 
    105     rval = soc_pci_read(unit,
    106               CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch));
    107 
    108     LOG_WARN(BSL_LS_SOC_COMMON,
    109              (BSL_META_U(unit,
    110                          "CONTROL: 0x%08x\n"), rval));
    111 
    112    rval = soc_pci_read(unit,
    113               CMIC_CMCx_SBUSDMA_CHy_CUR_HOSTMEM_ADDRESS_LO(cmc, ch));
    114 
    115     LOG_WARN(BSL_LS_SOC_COMMON,
    116              (BSL_META_U(unit,
    117                          "CUR_HOSTMEM_ADDRESS_LO: 0x%08x\n"), rval));
    118 
    119    rval = soc_pci_read(unit,
    120               CMIC_CMCx_SBUSDMA_CHy_CUR_HOSTMEM_ADDRESS_HI(cmc, ch));
    121 
    122     LOG_WARN(BSL_LS_SOC_COMMON,
    123              (BSL_META_U(unit,
    124                          "CUR_HOSTMEM_ADDRESS_HI: 0x%08x\n"), rval));
    125 
    126    rval = soc_pci_read(unit,
    127               CMIC_CMCx_SBUSDMA_CHy_CUR_DESC_ADDRESS_LO(cmc, ch));
    128 
    129     LOG_WARN(BSL_LS_SOC_COMMON,
    130              (BSL_META_U(unit,
    131                          "CUR_DESC_ADDRESS_LO: 0x%08x\n"), rval));
    132 
    133    rval = soc_pci_read(unit,
    134               CMIC_CMCx_SBUSDMA_CHy_CUR_DESC_ADDRESS_HI(cmc, ch));
    135 
    136     LOG_WARN(BSL_LS_SOC_COMMON,
    137              (BSL_META_U(unit,
    138                          "CUR_DESC_ADDRESS_HI: 0x%08x\n"), rval));
    139 
    140 #ifdef BCM_ESW_SUPPORT
    141     if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TOMAHAWKX(unit)){
    142         uint32 val;
    143         for (val = 0x10800; val <= 0x10840; val += 0x10) {
    144             soc_iproc_setreg(
    145                 unit, soc_reg_addr(unit, DMU_CRU_IPROC_DEBUG_SELr,
    146                 REG_PORT_ANY, 0), val);
    147             sal_udelay(1);
    148             soc_iproc_getreg(
    149                 unit, soc_reg_addr(unit, DMU_CRU_IPROC_DEBUG_STATUSr,
    150                 REG_PORT_ANY, 0), &rval);
    151             LOG_WARN(BSL_LS_SOC_COMMON,
    152                      (BSL_META_U(unit,
    153                       "DMU_SEL = 0x%08x, DMU_STAT = 0x%08x\n"), val, rval));
    154             rval = soc_pci_read(unit,
    155                        CMIC_CMCx_SHARED_AXI_STAT_OFFSET(cmc));
    156             LOG_WARN(BSL_LS_SOC_COMMON,
    157                       (BSL_META_U(unit,
    158                                   "CMIC_CMCx_SHARED_AXI_STAT: 0x%08x\n"), rval));
    159         }
    160     }
    161 #endif
    162 
    163 }
    164 
    165 /*******************************************
    166 * @function cmicx_sbusdma_error_details
    167 * purpose Print error details
    168 *
    169 * @param unit [in] unit
    170 * @param rval [in] Error value
    171 *
    172 * @returns SOC_E_NONE
    173 * @returns SOC_E_XXX
    174 *
    175 * @end
    176  */
    177 void
    178 cmicx_sbusdma_error_details(int unit, uint32 rval)
    179 {
    180     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    181                           rval, DESCRD_ERRORf)) {
    182         LOG_ERROR(BSL_LS_SOC_COMMON,
    183                   (BSL_META_U(unit,
    184                               "Error while reading descriptor from host memory.\n")));
    185     }
    186     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    187                           rval, SBUSACK_TIMEOUTf)) {
    188         LOG_ERROR(BSL_LS_SOC_COMMON,
    189                   (BSL_META_U(unit,
    190                               "sbus ack not received within configured time.\n")));
    191     }
    192     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    193                           rval, SBUSACK_ERRORf)) {
    194         LOG_ERROR(BSL_LS_SOC_COMMON,
    195                   (BSL_META_U(unit,
    196                               "H/W received sbus ack with error bit set.\n")));
    197     }
    198     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    199                           rval, SBUSACK_NACKf)) {
    200         LOG_ERROR(BSL_LS_SOC_COMMON,
    201                   (BSL_META_U(unit,
    202                               "H/W received sbus nack with error bit set.\n")));
    203     }
    204     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    205                           rval, SBUSACK_WRONG_OPCODEf)) {
    206         LOG_ERROR(BSL_LS_SOC_COMMON,
    207                   (BSL_META_U(unit,
    208                               "Received sbus ack has wrong opcode.\n")));
    209     }
    210     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    211                           rval, SBUSACK_WRONG_BEATCOUNTf)) {
    212         LOG_ERROR(BSL_LS_SOC_COMMON,
    213                   (BSL_META_U(unit,
    214                               "Received sbus ack data size is not the same as in rep_words "
    215                               "fields.\n")));
    216     }
    217     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    218                           rval, SER_CHECK_FAILf)) {
    219         LOG_ERROR(BSL_LS_SOC_COMMON,
    220                   (BSL_META_U(unit,
    221                               "Received sbus ack with SER_CHECK_FAIL set.\n")));
    222     }
    223     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    224                           rval, HOSTMEMRD_ERRORf)) {
    225         LOG_ERROR(BSL_LS_SOC_COMMON,
    226                   (BSL_META_U(unit,
    227                               "Error while copying SBUSDMA data from Host Memory.\n")));
    228     }
    229     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    230                           rval, HOSTMEMWR_ERRORf)) {
    231         LOG_ERROR(BSL_LS_SOC_COMMON,
    232                   (BSL_META_U(unit,
    233                               "DMA operation encountered a schan response error "
    234                               "or host side error.\n")));
    235     }
    236 }
    237 
    238 /*******************************************
    239 * @function _cmicx_sbusdma_ch_get
    240 * purpose get idle channel and cmc
    241 *
    242 * @param unit [in] unit #
    243 * @param cmc [out] cmc number 0-1
    244 * @param ch [out] channel number 0-3
    245 *
    246 * @returns SOC_E_BUSY
    247 * @returns SOC_E_NONE
    248 *
    249 * @end
    250  */
    251 STATIC int
    252 _cmicx_sbusdma_ch_get(int unit, int *cmc, int *ch)
    253 {
    254     int rv = SOC_E_BUSY;
    255     int i;
    256     uint8 mask = 0;
    257 
    258     /*
    259      By Default all resources in CMC1 are reserved for embedded apps, i.e R5 apps,
    260      only CMC0 is avaiable for use.
    261      Return error in case channel allocation failure
    262      */
    263     if (sal_sem_take(_cmicx_sbusdma_ch.sem[unit],
    264         _cmicx_sbusdma_ch.timeout) < 0) {
    265         return rv;
    266     }
    267 
    268     sal_spinlock_lock(_cmicx_sbusdma_ch.lock[unit]);
    269     /* Allocate CMC*/
    270     if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) {
    271         *cmc = CMIC_CMCx_PCI;
    272         mask = CMIC_CMC0_SBUSDMA_CH_MASK;
    273         if (_cmicx_sbusdma_ch.ch[unit][*cmc] == 0) {
    274             /* Check if CMIC_CMCx_AXI is configured */
    275             if (SOC_PCI_CMCS_NUM(unit) > 1) {
    276                 *cmc = CMIC_CMCx_AXI;
    277                 mask = CMIC_CMC1_SBUSDMA_CH_MASK;
    278             }
    279         }
    280     } else {
    281         *cmc = CMIC_CMCx_AXI;
    282         mask = CMIC_CMC1_SBUSDMA_CH_MASK;
    283         if (_cmicx_sbusdma_ch.ch[unit][*cmc] == 0) {
    284             /* Check if CMIC_CMCx_AXI is configured */
    285             if (SOC_PCI_CMCS_NUM(unit) > 1) {
    286                 *cmc = CMIC_CMCx_PCI;
    287                 mask = CMIC_CMC0_SBUSDMA_CH_MASK;
    288             }
    289         }
    290     }
    291     /* Allocate Channel */
    292     for (i = 0; i < CMIC_CMCx_SBUSDMA_CHAN_MAX; i++) {
    293         if ((mask & 0x01 << i) &&
    294              (_cmicx_sbusdma_ch.ch[unit][*cmc] & 0x01 << i)) {
    295             rv = SOC_E_NONE;
    296             *ch = i;
    297             _cmicx_sbusdma_ch.ch[unit][*cmc] &= ~(0x01 << i);
    298             break;
    299         }
    300     }
    301     sal_spinlock_unlock(_cmicx_sbusdma_ch.lock[unit]);
    302     return rv;
    303 }
    304 
    305 /*******************************************
    306 * @function cmicx_sbusdma_ch_try_get
    307 * purpose try to get channel on cmc
    308 *
    309 * @param unit [in] unit #
    310 * @param cmc [out] cmc number 0-1
    311 * @param ch [out] channel number 0-3
    312 *
    313 * @returns SOC_E_BUSY
    314 * @returns SOC_E_NONE
    315 *
    316 * @end
    317  */
    318 int cmicx_sbusdma_ch_try_get(int unit, int cmc, int ch)
    319 {
    320     int rv = SOC_E_BUSY;
    321     soc_timeout_t to;
    322     soc_timeout_init(&to, _cmicx_sbusdma_ch.timeout, 100);
    323 
    324     /* Try to allocate specified Channel from specified CMC */
    325     do {
    326        sal_spinlock_lock(_cmicx_sbusdma_ch.lock[unit]);
    327        if (_cmicx_sbusdma_ch.ch[unit][cmc] & (0x01 << ch)) {
    328            rv = SOC_E_NONE;
    329            _cmicx_sbusdma_ch.ch[unit][cmc] &= ~(0x01 << ch);
    330            sal_spinlock_unlock(_cmicx_sbusdma_ch.lock[unit]);
    331            break;
    332        }
    333        sal_spinlock_unlock(_cmicx_sbusdma_ch.lock[unit]);
    334     } while (!soc_timeout_check(&to));
    335     /* Channel consumed */
    336     if (rv == SOC_E_NONE) {
    337         (void)sal_sem_take(_cmicx_sbusdma_ch.sem[unit]
    338                            ,_cmicx_sbusdma_ch.timeout);
    339     }
    340 
    341     return rv;
    342 }
    343 
    344 /*******************************************
    345 * @function cmicx_sbusdma_ch_get
    346 * purpose get idle channel on cmc
    347 *
    348 * @param unit [in] unit #
    349 * @param cmc [out] cmc number 0-1
    350 * @param ch [out] channel number 0-3
    351 *
    352 * @returns SOC_E_BUSY
    353 * @returns SOC_E_NONE
    354 *
    355 * @end
    356  */
    357 int cmicx_sbusdma_ch_get(int unit, int *cmc, int *ch)
    358 {
    359     int rv;
    360 
    361     if ((soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) ||
    362         (soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE)) {
    363         rv = _cmicx_sbusdma_ch_get(unit, cmc, ch);
    364     } else {
    365         rv = SOC_E_FAIL;
    366     }
    367 
    368     if (SOC_SUCCESS(rv)) {
    369         /* Check if interrupt resources are initialized */
    370         if (SOC_CMC_SBUSDMA_INTR(unit, *cmc, *ch) == NULL) {
    371             cmicx_sbusdma_ch_put(unit, *cmc, *ch);
    372             SOC_STAT(unit)->err_sbusdma_intr_res++;
    373             rv = SOC_E_FAIL;
    374         }
    375     } else {
    376         int i;
    377         /* Get the details of each channel in case of channel allocation fails */
    378         for (i = 0; i < CMIC_CMCx_SBUSDMA_CHAN_MAX; i++) {
    379             cmicx_sbusdma_curr_op_details(unit, *cmc, i);
    380         }
    381     }
    382     return rv;
    383 }
    384 
    385 
    386 /*******************************************
    387 * @function cmicx_sbusdma_ch_put
    388 * purpose put back the freed channel on cmc
    389 *
    390 * @param cmc [in] cmc number 0
    391 * @param ch [in] channel number 0-2
    392 *
    393 * @returns SOC_E_PARAM
    394 * @returns SOC_E_NONE
    395 *
    396 * @end
    397  */
    398 int cmicx_sbusdma_ch_put(int unit, int cmc, int ch)
    399 {
    400     int rv = SOC_E_NONE;
    401 
    402     if ((ch < 0) || (ch > CMIC_CMCx_SBUSDMA_CHAN_MAX -1)) {
    403        rv = SOC_E_PARAM;
    404        return rv;
    405     }
    406     sal_spinlock_lock(_cmicx_sbusdma_ch.lock[unit]);
    407     _cmicx_sbusdma_ch.ch[unit][cmc] |= (0x01 << ch);
    408     sal_spinlock_unlock(_cmicx_sbusdma_ch.lock[unit]);
    409     sal_sem_give(_cmicx_sbusdma_ch.sem[unit]);
    410     return rv;
    411 }
    412 
    413 /*******************************************
    414 * @function cmicx_sbusdma_ch_deinit
    415 * purpose API to de-Initialize sbusdma channel
    416 *
    417 * @param unit [in] unit
    418 *
    419 * @returns SOC_E_NONE
    420 * @returns SOC_E_XXX
    421 *
    422 * @end
    423  */
    424 int cmicx_sbusdma_ch_deinit(int unit)
    425 
    426 {
    427     int i;
    428 
    429     for (i = 0; i < SOC_MAX_NUM_DEVICES; i++) {
    430         if (_cmicx_sbusdma_ch.lock[i] != NULL) {
    431             sal_spinlock_destroy(_cmicx_sbusdma_ch.lock[i]);
    432             _cmicx_sbusdma_ch.lock[i] = NULL;
    433         }
    434     }
    435     /* Cleanup channel semaphore */
    436     for (i = 0; i < SOC_MAX_NUM_DEVICES; i++) {
    437       if (_cmicx_sbusdma_ch.sem[i] != NULL) {
    438           sal_sem_destroy(_cmicx_sbusdma_ch.sem[i]);
    439           _cmicx_sbusdma_ch.sem[i] = NULL;
    440       }
    441     }
    442 
    443     return SOC_E_NONE;
    444 }
    445 
    446 /*******************************************
    447 * @function cmicx_sbusdma_ch_init
    448 * purpose API to Initialize sbusdma channel seletion mechanism
    449 *
    450 * @param unit [in] unit
    451 * @param timeout [in] int
    452 * @param cmic_ch [out] soc_sbusdma_cmic_ch_t pointer
    453 *
    454 * @returns SOC_E_NONE
    455 * @returns SOC_E_XXX
    456 *
    457 * @end
    458  */
    459 int cmicx_sbusdma_ch_init(int unit, int timeout,
    460                             soc_sbusdma_cmic_ch_t *cmic_ch)
    461 
    462 {
    463     int rv = SOC_E_NONE;
    464     int i;
    465 
    466     for (i = 0; i < SOC_MAX_NUM_DEVICES; i++) {
    467         _cmicx_sbusdma_ch.lock[i] = sal_spinlock_create("sbusdma Lock");
    468         if (_cmicx_sbusdma_ch.lock[i] == NULL) {
    469             return SOC_E_MEMORY;
    470         }
    471     }
    472     /* Initialize channel semaphore */
    473     for (i = 0; i < SOC_MAX_NUM_DEVICES; i++) {
    474        _cmicx_sbusdma_ch.sem[i] =
    475            sal_sem_create("SBUSDMA Channel",
    476            sal_sem_COUNTING,
    477            CMIC_CMCx_SBUSDMA_CHAN_MAX * SOC_PCI_CMCS_NUM(unit));
    478        if (_cmicx_sbusdma_ch.sem[i] == NULL) {
    479            return SOC_E_MEMORY;
    480        }
    481     }
    482     /* Availability of channels */
    483     _cmicx_sbusdma_ch.ch[unit][0] = CMIC_CMC0_SBUSDMA_CH_MASK;
    484     _cmicx_sbusdma_ch.ch[unit][1] = CMIC_CMC1_SBUSDMA_CH_MASK;
    485     _cmicx_sbusdma_ch.timeout = timeout;
    486     cmic_ch->soc_sbusdma_ch_try_get = cmicx_sbusdma_ch_try_get;
    487     cmic_ch->soc_sbusdma_ch_put = cmicx_sbusdma_ch_put;
    488     return rv;
    489 
    490 }
    491 
    492 /*******************************************
    493 * @function cmicx_sbusdma_ch_endian_set
    494 * set the endianess value
    495 *
    496 * @param cmc [in] cmc number
    497 * @param ch [in] channel number
    498 * @param ch [in] big_endian
    499 *
    500 * @returns SOC_E_PARAM
    501 * @returns SOC_E_NONE
    502 *
    503 * @end
    504  */
    505 extern int
    506 cmicx_sbusdma_ch_endian_set(int unit, int cmc, int ch, int be)
    507 {
    508     uint32 val;
    509 
    510     if ( ((be != 0) && (be != 1)) ||
    511          (ch >= SOC_SBUSDMA_CH_PER_CMC) ) {
    512         return SOC_E_PARAM;
    513     }
    514 
    515     val = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch));
    516     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr,
    517                                  &val, DESCRIPTOR_ENDIANESSf, be);
    518     soc_pci_write(unit,  CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch), val);
    519 
    520     return SOC_E_NONE;
    521 }
    522 
    523 /*******************************************
    524 * @function _cmicx_sbusdma_start
    525 * start the SBUSDMA
    526 *
    527 * @param unit [in] unit
    528 * @param cmc [in] cmc
    529 * @param ch [in] channel
    530 *
    531 * @returns SOC_E_NONE
    532 *
    533 * @end
    534  */
    535 int
    536 _cmicx_sbusdma_start(int unit, int cmc, int ch)
    537 {
    538     int rv = SOC_E_NONE;
    539     uint32        ctrl;
    540     ctrl = soc_pci_read(unit,
    541               CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch));
    542     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr,
    543                       &ctrl, STARTf, 1);
    544     soc_pci_write(unit, CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch),
    545                   ctrl);
    546 
    547     return rv;
    548 }
    549 /*******************************************
    550 * @function cmicx_sbusdma_stop
    551 * start the SBUSDMA
    552 *
    553 * @param unit [in] unit
    554 * @param cmc [in] cmc
    555 * @param ch [in] channel
    556 *
    557 * @returns SOC_E_NONE
    558 *
    559 * @end
    560  */
    561 int
    562 cmicx_sbusdma_stop(int unit, int cmc, int ch)
    563 {
    564     int rv = SOC_E_NONE;
    565     uint32        ctrl;
    566 
    567     ctrl = soc_pci_read(unit,
    568                    CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch));
    569     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl,
    570                                   STARTf, 0);
    571     soc_reg_field_set(unit, CMIC_CMC0_SBUSDMA_CH0_CONTROLr, &ctrl,
    572                                   ABORTf, 0);
    573     soc_pci_write(unit,
    574             CMIC_CMCx_SBUSDMA_CHy_CONTROL(cmc, ch), ctrl);
    575 
    576     return rv;
    577 }
    578 
    579 /*******************************************
    580 * @function cmicx_sbusdma_intr_wait
    581 * purpose API to wait for DMA complete using interrupt mode
    582 *
    583 * @param unit [in] unit
    584 * @param cmc [in] cmc
    585 * @param ch [in] channel
    586 * @param interval [in] timeout
    587 * @param do_not_perform_start_operation [in] if the argument is non-zero, the operation is assumed to be already started.
    588 *
    589 * @returns SOC_E_NONE
    590 * @returns SOC_E_XXX
    591 *
    592 * @end
    593  */
    594 int
    595 cmicx_sbusdma_intr_wait(int unit, int cmc, int ch, int timeout, uint32 do_not_perform_start_operation)
    596 {
    597     int rv = SOC_E_NONE;
    598     int rval;
    599     soc_control_t *soc = SOC_CONTROL(unit);
    600 
    601     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    602                       (BSL_META_U(unit,
    603                                   "cmc = %d, ch = %d, timeout = %d\n"),
    604                                    cmc, ch, timeout));
    605 
    606     soc_cmic_intr_enable(unit, INTR_SBUSDMA(cmc, ch));
    607 
    608     if (do_not_perform_start_operation == 0 ) {
    609         _cmicx_sbusdma_start(unit, cmc, ch);
    610     }
    611     _cmicx_sbusdma_ch.wait[unit][cmc] |= (0x01 << ch);
    612 
    613     if (sal_sem_take(soc->sbusDmaIntrs[cmc][ch], timeout) < 0) {
    614         rv = SOC_E_TIMEOUT;
    615         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    616                     (BSL_META_U(unit, "Interrupt Timeout\n")));
    617     }
    618     _cmicx_sbusdma_ch.wait[unit][cmc] &= ~(0x01 << ch);
    619     soc_cmic_intr_disable(unit, INTR_SBUSDMA(cmc, ch));
    620 
    621     rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch));
    622     /* Check if DMA is DONE */
    623     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    624                           rval, DONEf)) {
    625         rv = SOC_E_NONE;
    626         if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    627                               rval, ERRORf)) {
    628             rv = SOC_E_FAIL;
    629         }
    630     }
    631     if (rv != SOC_E_NONE) {
    632         cmicx_sbusdma_curr_op_details(unit, cmc, ch);
    633         soc_event_generate(unit, SOC_SWITCH_EVENT_IO_ERROR, cmc, ch, 0);
    634     }
    635 
    636     return rv;
    637 }
    638 
    639 
    640 /*******************************************
    641 * @function cmicx_sbusdma_poll_wait
    642 * purpose API to wait Descriptor using Polling mode
    643 *
    644 * @param unit [in] unit
    645 * @param cmc [in] cmc
    646 * @param ch [in] channel
    647 * @param interval [in] timeout
    648 * @param do_not_perform_start_operation [in] if the argument is non-zero, the operation is assumed to be already started.
    649 *
    650 * @returns SOC_E_NONE
    651 * @returns SOC_E_XXX
    652 *
    653 * @end
    654  */
    655 int
    656 cmicx_sbusdma_poll_wait(int unit, int cmc, int ch, int timeout, uint32 do_not_perform_start_operation)
    657 {
    658     soc_timeout_t to;
    659     int rv = SOC_E_TIMEOUT;
    660     int rval;
    661 
    662     if (do_not_perform_start_operation == 0 ) {
    663         _cmicx_sbusdma_start(unit, cmc, ch);
    664     }
    665     _cmicx_sbusdma_ch.wait[unit][cmc] |= (0x01 << ch);
    666     soc_timeout_init(&to, timeout, 0);
    667 
    668     do {
    669         rval = soc_pci_read(unit,
    670                             CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch));
    671          LOG_VERBOSE(BSL_LS_SOC_COMMON,
    672                        (BSL_META_U(unit,
    673                                    "cmc = %d, ch = %d, rval = %x\n"),
    674                                     cmc, ch, rval));
    675         if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    676                               rval, DONEf)) {
    677             rv = SOC_E_NONE;
    678             if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    679                                   rval, ERRORf)) {
    680                 rv = SOC_E_FAIL;
    681             }
    682             break;
    683         }
    684     } while(!(soc_timeout_check(&to)));
    685 
    686     _cmicx_sbusdma_ch.wait[unit][cmc] &= ~(0x01 << ch);
    687     if (rv != SOC_E_NONE) {
    688         cmicx_sbusdma_curr_op_details(unit, cmc, ch);
    689         soc_event_generate(unit, SOC_SWITCH_EVENT_IO_ERROR, cmc, ch, 0);
    690     }
    691 
    692     return rv;
    693 
    694 }
    695 
    696 
    697 /*******************************************
    698 * @function cmicx_sbusdma_desc_done
    699 * Interrupt handler for descriptor done
    700 *
    701 * @param unit [in] unit
    702 * @param data [in] pointer provided during registration
    703 *
    704 *
    705 * @end
    706  */
    707 
    708 STATIC void
    709 cmicx_sbusdma_ch_done(int unit, void *data)
    710 {
    711     soc_control_t *soc = SOC_CONTROL(unit);
    712     intr_data_t *in_d = (intr_data_t *)data;
    713 
    714     if ((soc->sbusDmaIntrEnb) || (soc->tslamDmaIntrEnb) ||
    715                (soc->tableDmaIntrEnb)) {
    716         if (_cmicx_sbusdma_ch.wait[unit][in_d->cmc] & 0x01 << in_d->ch) {
    717             sal_sem_give(soc->sbusDmaIntrs[in_d->cmc][in_d->ch]);
    718         }
    719     }
    720 }
    721 
    722 /*******************************************
    723 * @function cmicx_sbusdma_vchan_to_cmc_ch
    724 * API takes vchan as input and return cmc and channel
    725 *
    726 * @param unit [in] int
    727 * @param vchan [in] virtual channel
    728 * @param cmc [out] cmc associated
    729 * @param channel [out] channel associated
    730 *
    731 * @returns SOC_E_NONE
    732 * @returns SOC_E_XXX
    733 *
    734 * @end
    735  */
    736 int
    737 cmicx_sbusdma_vchan_to_cmc_ch(int unit, int vchan,
    738                                int *cmc, int *ch)
    739 {
    740     if (vchan < 0 ||
    741          vchan >= SOC_PCI_CMCS_NUM(unit) * CMIC_CMCx_SBUSDMA_CHAN_MAX) {
    742         return SOC_E_PARAM;
    743     }
    744     *cmc = vchan / CMIC_CMCx_SBUSDMA_CHAN_MAX;
    745     *ch =  vchan % CMIC_CMCx_SBUSDMA_CHAN_MAX;
    746 
    747     return SOC_E_NONE;
    748 }
    749 
    750 /*******************************************
    751 * @function cmicx_sbusdma_intr_init
    752 * purpose API to Initialize SBUSDMA interrupts
    753 *
    754 * @param unit [in] unit
    755 *
    756 * @returns SOC_E_NONE
    757 * @returns SOC_E_XXX
    758 *
    759 * @end
    760  */
    761 extern int
    762 cmicx_sbusdma_intr_init(int unit)
    763 {
    764     int cmc, ch;
    765     soc_cmic_intr_handler_t *handle;
    766     soc_cmic_intr_handler_t *hitr;
    767     int rv;
    768 
    769     /* Register the descriptor interrupts */
    770     handle = sal_alloc(sizeof(soc_cmic_intr_handler_t)*CMIC_CMC_NUM_MAX*
    771                        CMIC_CMCx_SBUSDMA_CHAN_MAX, "sbusdma_interrupt");
    772     if (handle == NULL) {
    773         return SOC_E_MEMORY;
    774     }
    775     hitr = handle;
    776     for (cmc = 0; cmc < CMIC_CMC_NUM_MAX; cmc++) {
    777          for (ch = 0; ch < CMIC_CMCx_SBUSDMA_CHAN_MAX; ch++) {
    778               _intr_data[cmc][ch].cmc = cmc;
    779               _intr_data[cmc][ch].ch = ch;
    780               hitr->num = INTR_SBUSDMA(cmc, ch);
    781               hitr->intr_fn = cmicx_sbusdma_ch_done;
    782               hitr->intr_data = &_intr_data[cmc][ch];
    783               hitr++;
    784          }
    785     }
    786     rv = soc_cmic_intr_register(unit, handle,
    787                            CMIC_CMC_NUM_MAX*CMIC_CMCx_SBUSDMA_CHAN_MAX);
    788     sal_free(handle);
    789 
    790     return rv;
    791 }
    792 
    793 
    794 #endif