openbcm

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

cmicm_sbusdma_common.c (9547B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * Purpose: CMICM 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_CMICM_SUPPORT) && defined(BCM_SBUSDMA_SUPPORT)
     19 #include <soc/cmicm.h>
     20 
     21 
     22 typedef struct cmicm_sbusdma_ch_s {
     23     sal_spinlock_t   lock;
     24     int timeout;
     25     uint8  ch[SOC_MAX_NUM_DEVICES][CMIC_CMC_NUM_MAX];
     26 }cmicm_sbusdma_ch_t;
     27 
     28 
     29 STATIC cmicm_sbusdma_ch_t  _cmicm_sbusdma_ch;
     30 
     31 
     32 /*******************************************
     33 * @function cmicm_sbusdma_curr_op_details
     34 * purpose Print operation details
     35 *
     36 * @param unit [in] unit
     37 * @param cmc [in] cmc number
     38 * @param ch [in] channel number
     39 *
     40 * @returns SOC_E_NONE
     41 * @returns SOC_E_XXX
     42 *
     43 * @end
     44  */
     45 void
     46 cmicm_sbusdma_curr_op_details(int unit, int cmc, int ch)
     47 {
     48     uint32 rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch));
     49     LOG_VERBOSE(BSL_LS_SOC_COMMON,
     50              (BSL_META_U(unit,
     51                          "STATUS: 0x%08x\n"), rval));
     52     rval = soc_pci_read(unit,
     53                         CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSDMA_CONFIG_OPCODE(cmc, ch));
     54     LOG_VERBOSE(BSL_LS_SOC_COMMON,
     55              (BSL_META_U(unit,
     56                          "OPCODE: 0x%08x\n"), rval));
     57     rval = soc_pci_read(unit,
     58                         CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSDMA_CONFIG_ADDR(cmc, ch));
     59     LOG_VERBOSE(BSL_LS_SOC_COMMON,
     60              (BSL_META_U(unit,
     61                          "START ADDR: 0x%08x\n"), rval));
     62     rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSADDR(cmc, ch));
     63     LOG_VERBOSE(BSL_LS_SOC_COMMON,
     64              (BSL_META_U(unit,
     65                          "CUR ADDR: 0x%08x\n"), rval));
     66 }
     67 
     68 /*******************************************
     69 * @function cmicm_sbusdma_error_details
     70 * purpose Print error details
     71 *
     72 * @param unit [in] unit
     73 * @param rval [in] Error value
     74 *
     75 * @returns SOC_E_NONE
     76 * @returns SOC_E_XXX
     77 *
     78 * @end
     79  */
     80 void
     81 cmicm_sbusdma_error_details(int unit, uint32 rval)
     82 {
     83     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
     84                           rval, DESCRD_ERRORf)) {
     85         LOG_ERROR(BSL_LS_SOC_COMMON,
     86                   (BSL_META_U(unit,
     87                               "Error while reading descriptor from host memory.\n")));
     88     }
     89     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
     90                           rval, SBUSACK_TIMEOUTf)) {
     91         LOG_ERROR(BSL_LS_SOC_COMMON,
     92                   (BSL_META_U(unit,
     93                               "sbus ack not received within configured time.\n")));
     94     }
     95     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
     96                           rval, SBUSACK_ERRORf)) {
     97         LOG_ERROR(BSL_LS_SOC_COMMON,
     98                   (BSL_META_U(unit,
     99                               "H/W received sbus ack with error bit set.\n")));
    100     }
    101     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    102                           rval, SBUSACK_NACKf)) {
    103         LOG_ERROR(BSL_LS_SOC_COMMON,
    104                   (BSL_META_U(unit,
    105                               "H/W received sbus nack with error bit set.\n")));
    106     }
    107     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    108                           rval, SBUSACK_WRONG_OPCODEf)) {
    109         LOG_ERROR(BSL_LS_SOC_COMMON,
    110                   (BSL_META_U(unit,
    111                               "Received sbus ack has wrong opcode.\n")));
    112     }
    113     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    114                           rval, SBUSACK_WRONG_BEATCOUNTf)) {
    115         LOG_ERROR(BSL_LS_SOC_COMMON,
    116                   (BSL_META_U(unit,
    117                               "Received sbus ack data size is not the same as in rep_words "
    118                               "fields.\n")));
    119     }
    120     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    121                           rval, SER_CHECK_FAILf)) {
    122         LOG_ERROR(BSL_LS_SOC_COMMON,
    123                   (BSL_META_U(unit,
    124                               "Received sbus ack with SER_CHECK_FAIL set.\n")));
    125     }
    126     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    127                           rval, HOSTMEMRD_ERRORf)) {
    128         LOG_ERROR(BSL_LS_SOC_COMMON,
    129                   (BSL_META_U(unit,
    130                               "Error while copying SBUSDMA data from Host Memory.\n")));
    131     }
    132     if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr,
    133                           rval, HOSTMEMWR_ERRORf)) {
    134         LOG_ERROR(BSL_LS_SOC_COMMON,
    135                   (BSL_META_U(unit,
    136                               "DMA operation encountered a schan response error "
    137                               "or host side error.\n")));
    138     }
    139 }
    140 
    141 /*******************************************
    142 * @function _cmicm_sbusdma_ch_get
    143 * purpose get idle channel on cmc
    144 *
    145 * @param unit [in] unit #
    146 * @param cmc [in] cmc number 0-2
    147 * @param mask [in] mask for available channels
    148 * @param ch [out] channel number 0-2
    149 *
    150 * @returns SOC_E_BUSY
    151 * @returns SOC_E_NONE
    152 *
    153 * @end
    154  */
    155 STATIC int
    156 _cmicm_sbusdma_ch_get(int unit, int cmc,
    157                        uint8 mask, int *ch)
    158 {
    159     int rv = SOC_E_BUSY;
    160     int i;
    161 
    162     sal_spinlock_lock(_cmicm_sbusdma_ch.lock);
    163     for (i = 0; i < CMIC_CMCx_SBUSDMA_CHAN_MAX; i++) {
    164         if ((mask & 0x01 << i) &&
    165              (_cmicm_sbusdma_ch.ch[unit][cmc] & 0x01 << i)) {
    166             rv = SOC_E_NONE;
    167             *ch = i;
    168             _cmicm_sbusdma_ch.ch[unit][cmc] &= ~(0x01 << i);
    169             break;
    170         }
    171     }
    172     sal_spinlock_unlock(_cmicm_sbusdma_ch.lock);
    173     return rv;
    174 }
    175 
    176 /*******************************************
    177 * @function cmicm_sbusdma_ch_get
    178 * purpose get idle channel on cmc
    179 *
    180 * @param unit [in] unit #
    181 * @param cmc [out] cmc number 0-2
    182 * @param ch [out] channel number 0-2
    183 *
    184 * @returns SOC_E_BUSY
    185 * @returns SOC_E_NONE
    186 *
    187 * @end
    188  */
    189 int cmicm_sbusdma_ch_get(int unit, int *cmc, int *ch)
    190 {
    191     int rv;
    192 
    193     soc_timeout_t to;
    194 
    195     soc_timeout_init(&to, _cmicm_sbusdma_ch.timeout, 100);
    196 
    197     do {
    198         *cmc = CMC0;
    199         rv = _cmicm_sbusdma_ch_get(unit, *cmc,
    200                   CMIC_CMC0_SBUSDMA_CH_MASK, ch);
    201         if (rv == SOC_E_NONE)
    202             break;
    203 
    204         *cmc = CMC1;
    205         rv = _cmicm_sbusdma_ch_get(unit, *cmc,
    206                   CMIC_CMC1_SBUSDMA_CH_MASK, ch);
    207         if (rv == SOC_E_NONE)
    208             break;
    209 
    210         *cmc = CMC2;
    211         rv = _cmicm_sbusdma_ch_get(unit, *cmc,
    212                   CMIC_CMC2_SBUSDMA_CH_MASK, ch);
    213         if (rv == SOC_E_NONE)
    214             break;
    215     } while (!soc_timeout_check(&to));
    216     return rv;
    217 }
    218 
    219 /*******************************************
    220 * @function cmicm_sbusdma_ch_try_get
    221 * purpose get idle channel on cmc
    222 *
    223 * @param unit [in] unit #
    224 * @param cmc [in] cmc number 0-2
    225 * @param ch [in] channel number 0-2
    226 *
    227 * @returns SOC_E_BUSY
    228 * @returns SOC_E_NONE
    229 *
    230 * @end
    231  */
    232 int cmicm_sbusdma_ch_try_get(int unit, int cmc, int ch)
    233 {
    234     int rv = SOC_E_BUSY;
    235     uint8 mask = 0;
    236 
    237     soc_timeout_t to;
    238 
    239     soc_timeout_init(&to, _cmicm_sbusdma_ch.timeout, 100);
    240 
    241     if ((cmc < 0) || (cmc > CMIC_CMC_NUM_MAX - 1) ||
    242         (ch < 0) || (ch > CMIC_CMCx_SBUSDMA_CHAN_MAX - 1)) {
    243         rv = SOC_E_PARAM;
    244         return rv;
    245     }
    246 
    247     if (cmc == 0) {
    248         mask = CMIC_CMC0_SBUSDMA_CH_MASK;
    249     } else if (cmc == 1) {
    250         mask = CMIC_CMC1_SBUSDMA_CH_MASK;
    251     } else if (cmc == 2) {
    252         mask = CMIC_CMC2_SBUSDMA_CH_MASK;
    253     }
    254 
    255     sal_spinlock_lock(_cmicm_sbusdma_ch.lock);
    256     do {
    257         if ((mask & (0x01 << ch)) &&
    258             (_cmicm_sbusdma_ch.ch[unit][cmc] & (0x01 << ch))) {
    259             rv = SOC_E_NONE;
    260             _cmicm_sbusdma_ch.ch[unit][cmc] &= ~(0x01 << ch);
    261             break;
    262         }
    263     } while (!soc_timeout_check(&to));
    264     sal_spinlock_unlock(_cmicm_sbusdma_ch.lock);
    265 
    266     return rv;
    267 }
    268 
    269 /*******************************************
    270 * @function cmicm_sbusdma_ch_put
    271 * purpose put back the freed channel on cmc
    272 *
    273 * @param cmc [in] cmc number 0-2
    274 * @param ch [in] channel number 0-2
    275 *
    276 * @returns SOC_E_PARAM
    277 * @returns SOC_E_NONE
    278 *
    279 * @end
    280  */
    281 int cmicm_sbusdma_ch_put(int unit, int cmc, int ch)
    282 {
    283    int rv = SOC_E_NONE;
    284 
    285    if ((cmc < 0) || (cmc > CMIC_CMC_NUM_MAX - 1) ||
    286        (ch < 0) || (ch > CMIC_CMCx_SBUSDMA_CHAN_MAX - 1)) {
    287        rv = SOC_E_PARAM;
    288        return rv;
    289    }
    290    sal_spinlock_lock(_cmicm_sbusdma_ch.lock);
    291    _cmicm_sbusdma_ch.ch[unit][cmc] |= (0x01 << ch);
    292    sal_spinlock_unlock(_cmicm_sbusdma_ch.lock);
    293 
    294    return rv;
    295 }
    296 
    297 /*******************************************
    298 * @function cmicm_sbusdma_ch_init
    299 * purpose API to Initialize sbusdma channel seletion mechanism
    300 *
    301 * @param unit [in] unit
    302 * @param timeout [in] int
    303 * @param cmic_ch [out] pointer type soc_sbusdma_cmic_ch_t
    304 *
    305 * @returns SOC_E_NONE
    306 * @returns SOC_E_XXX
    307 *
    308 * @end
    309  */
    310 int cmicm_sbusdma_ch_init(int unit, int timeout,
    311                            soc_sbusdma_cmic_ch_t *cmic_ch)
    312 
    313 {
    314    int rv = SOC_E_NONE;
    315 
    316    _cmicm_sbusdma_ch.lock = sal_spinlock_create("sbusdma Lock");
    317 
    318    if (_cmicm_sbusdma_ch.lock == NULL) {
    319         return SOC_E_MEMORY;
    320    }
    321    /* Availability of channels */
    322    _cmicm_sbusdma_ch.ch[unit][0] = CMIC_CMC0_SBUSDMA_CH_MASK;
    323    _cmicm_sbusdma_ch.ch[unit][1] = CMIC_CMC1_SBUSDMA_CH_MASK;
    324    _cmicm_sbusdma_ch.ch[unit][2] = CMIC_CMC2_SBUSDMA_CH_MASK;
    325    _cmicm_sbusdma_ch.timeout = timeout;
    326    cmic_ch->soc_sbusdma_ch_try_get = cmicm_sbusdma_ch_try_get;
    327    cmic_ch->soc_sbusdma_ch_put = cmicm_sbusdma_ch_put;
    328 
    329    return rv;
    330 }
    331 
    332 
    333 #endif