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_schan.c (16650B)


      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  * CMICM S-Channel (internal command bus) support
      8  */
      9 
     10 #include <shared/bsl.h>
     11 #include <sal/core/libc.h>
     12 #include <sal/core/boot.h>
     13 #include <sal/core/dpc.h>
     14 #include <soc/drv.h>
     15 #include <soc/debug.h>
     16 #include <soc/cm.h>
     17 #include <soc/error.h>
     18 #include <soc/cmic.h>
     19 #include <soc/schanmsg_internal.h>
     20 
     21 #ifdef BCM_CMICM_SUPPORT
     22 #include <soc/cmicm.h>
     23 
     24 #define SOC_CHECK_MULTI_CMC(unit) \
     25          (soc_feature(unit, soc_feature_cmicm_multi_schan_cmc) && \
     26                 (SOC_PCI_CMCS_NUM(unit) > 1))
     27 
     28 typedef struct cmicm_schan_ch_s {
     29     sal_spinlock_t lock;
     30     int timeout;
     31     uint8 ch[CMIC_CMC_NUM_MAX+1];
     32 } cmicm_schan_ch_t;
     33 
     34 
     35 STATIC cmicm_schan_ch_t  _cmicm_schan_ch[SOC_MAX_NUM_DEVICES];
     36 STATIC int _soc_schan_multi_cmc[SOC_MAX_NUM_DEVICES];
     37 
     38 
     39 /*******************************************
     40 * @function fschan_wait_idle
     41 * @Purpose FIFO SCHAN wait function.
     42 *
     43 * @param unit [in] unit
     44 *
     45 * @returns SOC_E_NONE
     46 * @returns SOC_E_XXX
     47 * @end
     48  */
     49 int
     50 fschan_wait_idle(int unit)
     51 {
     52     int cmc = SOC_PCI_CMC(unit);
     53     soc_timeout_t to;
     54 
     55     soc_timeout_init(&to, SOC_CONTROL(unit)->schanTimeout, 100);
     56     do {
     57         if (0==(soc_pci_read(unit, CMIC_CMCx_FSCHAN_STATUS_OFFSET(cmc)) & FSCHAN_BUSY)) {
     58             return SOC_E_NONE;
     59         }
     60     } while (!soc_timeout_check(&to));
     61     return SOC_E_TIMEOUT;
     62 }
     63 
     64 /*******************************************
     65 * @function _soc_cmicm_schan_reset
     66 * @Purpose Resets the CMIC S-Channel interface.
     67 *
     68 * @param unit [in] unit
     69 * @param cmc [in] cmc number 0-2 or 3 for common
     70 * @param ch [in] channel number 0
     71 *
     72 * @returns None
     73 * @comments This is required when we sent
     74 * a message and did not receive a response after the poll count was
     75 * exceeded.
     76 * @end
     77  */
     78 STATIC void
     79 _soc_cmicm_schan_reset(int unit, int cmc, int ch)
     80 {
     81     uint32 val, addr;
     82 
     83     COMPILER_REFERENCE(ch);
     84 
     85     addr = CMIC_COMMON_CMCx_SCHAN_CTRL_OFFSET(cmc);
     86     val = soc_pci_read(unit, addr);
     87     /* Toggle S-Channel abort bit in CMIC_SCHAN_CTRL register */
     88     soc_pci_write(unit, addr, val | SC_CMCx_SCHAN_ABORT);
     89     SDK_CONFIG_MEMORY_BARRIER;
     90     soc_pci_write(unit, addr, val);
     91     SDK_CONFIG_MEMORY_BARRIER;
     92 
     93     if (SAL_BOOT_QUICKTURN) {
     94         /* Give Quickturn at least 2 cycles */
     95         sal_usleep(10 * MILLISECOND_USEC);
     96     }
     97 }
     98 
     99 
    100 /*******************************************
    101 * @function _soc_cmicm_schan_intr_wait
    102 * purpose interrupt wait to complete SCHAN operation
    103 *
    104 * @param unit [in] unit
    105 * @param cmc [in] cmc number 0-2 or 3 for common
    106 *
    107 * @returns SOC_E_NONE
    108 * @returns SOC_E_XXX
    109 *
    110 * @comments  Called by schan_op_* functions.
    111 * wait on a schan interrupt.  When schan interrupts are disabled,
    112 * _soc_cmicm_schan_poll_wait is called instead.
    113 
    114 * @end
    115  */
    116 STATIC int
    117 _soc_cmicm_schan_intr_wait(int unit, int cmc)
    118 {
    119     uint32 errAddr;
    120     int rv = SOC_E_NONE;
    121 
    122     if (cmc != CMIC_CMC_NUM_MAX) {
    123         soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_SCH_OP_DONE);
    124     } else {
    125         /* this is for common SCHAN, this is available to all cmcs */
    126         soc_cmicm_cmcx_intr1_enable(unit, (cmc - 1),
    127                                         IRQ_CMCx_COMMON_SCHAN_DONE);
    128     }
    129     if (sal_sem_take(SOC_CONTROL(unit)->schanIntr[cmc],
    130                      SOC_CONTROL(unit)->schanTimeout) != 0) {
    131         rv = SOC_E_TIMEOUT;
    132     } else {
    133         LOG_VERBOSE(BSL_LS_SOC_SCHAN,
    134                  (BSL_META_U(unit,
    135                              "  Interrupt received\n")));
    136 
    137         if (SOC_CONTROL(unit)->schan_result[cmc] & SC_CMCx_MSG_NAK) {
    138             rv = SOC_E_FAIL;
    139         }
    140         if (soc_feature(unit, soc_feature_schan_hw_timeout)) {
    141             if (SOC_CONTROL(unit)->schan_result[cmc] &
    142                 SC_CMCx_MSG_TIMEOUT_TST) {
    143                 rv = SOC_E_TIMEOUT;
    144             }
    145         }
    146 
    147         if (soc_feature(unit, soc_feature_schan_err_check)) {
    148             uint32 schan_err, err_bit = 0;
    149 
    150             errAddr = CMIC_COMMON_CMCx_SCHAN_ERR_OFFSET(cmc);
    151             schan_err = soc_pci_read(unit, errAddr);
    152             err_bit = soc_reg_field_get(unit, CMIC_CMC0_SCHAN_ERRr, schan_err, ERRBITf);
    153 
    154             if (err_bit) {
    155                 rv = SOC_E_FAIL;
    156                 LOG_ERROR(BSL_LS_SOC_SCHAN, (BSL_META_U(unit,
    157                     "  ERRBIT received in CMIC_SCHAN_ERR.\n")));
    158             }
    159         }
    160     }
    161 
    162     if (cmc != CMIC_CMC_NUM_MAX) {
    163         soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_SCH_OP_DONE);
    164     } else {
    165         /* this is for common SCHAN, this is available to all cmcs */
    166         soc_cmicm_cmcx_intr1_disable(unit, (cmc - 1),
    167                                       IRQ_CMCx_COMMON_SCHAN_DONE);
    168     }
    169 
    170     return rv;
    171 }
    172 
    173 /*******************************************
    174 * @function _soc_cmicm_schan_poll_wait
    175 * purpose POLL wait to complete cmicm SCHAN operation
    176 *
    177 * @param unit [in] unit
    178 * @param cmc [in] cmc number 0-2 or 3 for common
    179 * @param msg [in] schan_msg_t
    180 *
    181 * @returns SOC_E_NONE
    182 * @returns SOC_E_XXX
    183 *
    184 * @end
    185 * @comments  Called by schan_cmicm_schan_op function.
    186 * In case interrupts are disabled, wait on a schan response via polling.
    187  */
    188 STATIC int
    189 _soc_cmicm_schan_poll_wait(int unit, int cmc, schan_msg_t *msg)
    190 {
    191     uint32 schanCtrl, ctrlAddr, msgAddr, errAddr;
    192     int rv = SOC_E_NONE;
    193     soc_timeout_t to;
    194 
    195     soc_timeout_init(&to, SOC_CONTROL(unit)->schanTimeout, 100);
    196     ctrlAddr = CMIC_COMMON_CMCx_SCHAN_CTRL_OFFSET(cmc);
    197 
    198     while (((schanCtrl = soc_pci_read(unit, ctrlAddr)) & SC_CMCx_MSG_DONE) == 0) {
    199         if (soc_timeout_check(&to)) {
    200             return SOC_E_TIMEOUT;
    201         }
    202     }
    203 
    204     if (rv == SOC_E_NONE) {
    205         LOG_VERBOSE(BSL_LS_SOC_SCHAN,
    206                  (BSL_META_U(unit,
    207                              "  Done in %d polls\n"), to.polls));
    208     }
    209 
    210     if (schanCtrl & SC_CMCx_MSG_NAK) {
    211         schan_msg_t resp_msg;
    212 
    213         /* This is still the input opcode */
    214         msgAddr = CMIC_COMMON_CMCx_SCHAN_MESSAGEn(cmc, 1);
    215         resp_msg.dwords[1] = soc_pci_read(unit, msgAddr);
    216 
    217         rv = SOC_E_FAIL;
    218         LOG_VERBOSE(BSL_LS_SOC_SCHAN,
    219                  (BSL_META_U(unit,
    220                              "  NAK received from SCHAN.\n")));
    221 
    222         switch (msg->header.v2.opcode) {
    223             case TABLE_INSERT_CMD_MSG:
    224             case TABLE_DELETE_CMD_MSG:
    225             case TABLE_LOOKUP_CMD_MSG:
    226                 if (resp_msg.genresp.response.type != SCHAN_GEN_RESP_TYPE_ERROR) {
    227                     /* Not a parity error */
    228                     break;
    229                 }
    230                 /* Else fallthru */
    231             case READ_MEMORY_CMD_MSG:
    232             case READ_REGISTER_CMD_MSG:
    233 #if defined(BCM_XGS_SUPPORT)
    234             {
    235                 int dst_blk, opcode;
    236                 soc_schan_header_cmd_get(unit, &msg->header, &opcode, &dst_blk,
    237                     NULL, NULL, NULL, NULL, NULL);
    238 
    239                 (void)soc_ser_mem_nack(INT_TO_PTR(unit),
    240                     INT_TO_PTR(msg->gencmd.address),
    241                     INT_TO_PTR(dst_blk),
    242                     opcode == READ_REGISTER_CMD_MSG ? INT_TO_PTR(1) : 0, 0);
    243             }
    244 #endif
    245             default:
    246                 break;
    247         }
    248     }
    249     if ((schanCtrl & SC_CMCx_MSG_SER_CHECK_FAIL) &&
    250         soc_feature(unit, soc_feature_ser_parity)){
    251         rv = SOC_E_FAIL;
    252         LOG_ERROR(BSL_LS_SOC_SCHAN, (BSL_META_U(unit,
    253                   "  SER Parity Check Error.\n")));
    254 
    255 #if defined(BCM_XGS_SUPPORT)
    256         sal_dpc(soc_ser_fail, INT_TO_PTR(unit),
    257                 INT_TO_PTR(msg->gencmd.address), 0, 0, 0);
    258 #endif
    259     }
    260 
    261     if (soc_feature(unit, soc_feature_schan_hw_timeout)) {
    262         if (schanCtrl & SC_CMCx_MSG_TIMEOUT_TST) {
    263             rv = SOC_E_TIMEOUT;
    264         }
    265     }
    266 
    267     if (soc_feature(unit, soc_feature_schan_err_check)) {
    268         uint32 schan_err, err_bit = 0;
    269 
    270         errAddr = CMIC_COMMON_CMCx_SCHAN_ERR_OFFSET(cmc);
    271         schan_err = soc_pci_read(unit, errAddr);
    272         err_bit = soc_reg_field_get(unit, CMIC_CMC0_SCHAN_ERRr, schan_err, ERRBITf);
    273 
    274         if (err_bit) {
    275             rv = SOC_E_FAIL;
    276             LOG_ERROR(BSL_LS_SOC_SCHAN, (BSL_META_U(unit,
    277                       "  ERRBIT received in CMIC_SCHAN_ERR.\n")));
    278         }
    279     }
    280     soc_pci_write(unit, ctrlAddr, SC_CMCx_MSG_CLR);
    281 
    282     return rv;
    283 }
    284 
    285 /*******************************************
    286 * @function _soc_cmicm_schan_op
    287 * purpose cmicm SCHAN operation
    288 *
    289 * @param unit [in] unit
    290 * @param msg [in] schan_msg_t
    291 * @param dwc_write [in] Write messages
    292 * @param dwc_write [in] read messages
    293 * @param intr [in] use interrupt
    294 *
    295 * @returns SOC_E_NONE
    296 * @returns SOC_E_XXX
    297 *
    298 * @end
    299 * @comments  This is the basic logic for schan
    300  */
    301 
    302 STATIC int
    303 _soc_cmicm_schan_op(int unit, schan_msg_t *msg, int dwc_write,
    304                    int dwc_read, int intr)
    305 {
    306     uint32 ctrlAddr, msgAddr;
    307     int i, rv;
    308     int cmc;
    309 
    310     if (soc_schan_op_sanity_check(unit, msg, dwc_write, dwc_read, &rv) == TRUE) {
    311         return rv;
    312     }
    313 
    314 #if defined(BCM_SABER2_SUPPORT)
    315    if (!(SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM)) {
    316        if (SOC_IS_SABER2(unit)) {
    317         if (msg->header.v4.dst_blk == SOC_BLOCK_INFO(unit, OAMP_BLOCK(unit)).
    318                                       schan) {
    319            if (msg->header.v4.opcode == WRITE_REGISTER_CMD_MSG) {
    320                LOG_VERBOSE(BSL_LS_SOC_SCHAN,
    321                            (BSL_META_U(unit,
    322                            "OAMP Write Block access OLD :%x \n"),
    323                            msg->writecmd.address));
    324                msg->writecmd.address =
    325                (msg->writecmd.address >> 8) & 0x000003ff;
    326                LOG_VERBOSE(BSL_LS_SOC_SCHAN,
    327                            (BSL_META_U(unit,
    328                            "NEW :%x \n"), msg->writecmd.address));
    329            }
    330            if (msg->header.v4.opcode == READ_REGISTER_CMD_MSG) {
    331                LOG_VERBOSE(BSL_LS_SOC_SCHAN,
    332                            (BSL_META_U(unit,
    333                            "OAMP READ Block access OLD:%x "),
    334                            msg->readcmd.address));
    335                msg->readcmd.address =
    336                (msg->readcmd.address >> 8) & 0x000003ff;
    337                LOG_VERBOSE(BSL_LS_SOC_SCHAN,
    338                            (BSL_META_U(unit,
    339                            "New: %x \n"), msg->readcmd.address));
    340            }
    341         }
    342        }
    343    }
    344 #endif /* BCM_SABER2_SUPPORT */
    345 
    346     if (_soc_schan_multi_cmc[unit]){
    347         SOC_IF_ERROR_RETURN(cmicm_schan_ch_get(unit, &cmc));
    348     } else {
    349         SCHAN_LOCK(unit);
    350         cmc = SOC_PCI_CMC(unit);
    351     }
    352 
    353     do {
    354         rv = SOC_E_NONE;
    355 
    356         /* Write raw S-Channel Data: dwc_write words */
    357         for (i = 0; i < dwc_write; i++) {
    358             msgAddr = CMIC_COMMON_CMCx_SCHAN_MESSAGEn(cmc, i);
    359             soc_pci_write(unit, msgAddr, msg->dwords[i]);
    360         }
    361 
    362         /* Tell CMIC to start */
    363         ctrlAddr = CMIC_COMMON_CMCx_SCHAN_CTRL_OFFSET(cmc);
    364         soc_pci_write(unit, ctrlAddr, SC_CMCx_MSG_START);
    365 
    366         /* Wait for completion using either the interrupt or polling method */
    367         if (intr && SOC_CONTROL(unit)->schanIntrEnb) {
    368             rv = _soc_cmicm_schan_intr_wait(unit, cmc);
    369         } else {
    370             rv = _soc_cmicm_schan_poll_wait(unit, cmc, msg);
    371         }
    372 
    373         if (soc_schan_timeout_check(unit, &rv, msg, cmc, 0) == TRUE) {
    374             break;
    375         }
    376 
    377         /* Read in data from S-Channel buffer space, if any */
    378         for (i = 0; i < dwc_read; i++) {
    379             msgAddr = CMIC_COMMON_CMCx_SCHAN_MESSAGEn(cmc, i);
    380             msg->dwords[i] = soc_pci_read(unit, msgAddr);
    381         }
    382 
    383         if (LOG_CHECK(BSL_LS_SOC_SCHAN | BSL_VERBOSE)) {
    384             soc_schan_dump(unit, msg, dwc_read);
    385         }
    386 
    387     } while (0);
    388 
    389     if (_soc_schan_multi_cmc[unit]) {
    390         cmicm_schan_ch_put(unit, cmc);
    391     } else {
    392         SCHAN_UNLOCK(unit);
    393     }
    394 
    395     if (rv == SOC_E_TIMEOUT) {
    396         if (LOG_CHECK(BSL_LS_SOC_SCHAN | BSL_ERROR)) {
    397             LOG_ERROR(BSL_LS_SOC_SCHAN,
    398                       (BSL_META_U(unit,
    399                         "SchanTimeOut:soc_schan_op operation timed out cmc=%d\n"), cmc));
    400             soc_schan_dump(unit, msg, dwc_write);
    401         }
    402     }
    403 
    404     return rv;
    405 }
    406 
    407 /*******************************************
    408 * @function _cmicm_schan_ch_get
    409 * purpose get idle schan on cmc
    410 *
    411 * @param unit [in] unit #
    412 * @param *cmc [out] cmc number 0-2 or 3 for common
    413 *
    414 * @returns SOC_E_BUSY
    415 * @returns SOC_E_NONE
    416 *
    417 * @end
    418  */
    419 STATIC int
    420 _cmicm_schan_ch_get(int unit, int *cmc)
    421 {
    422     int rv = SOC_E_BUSY;
    423     int i;
    424 
    425     sal_spinlock_lock(_cmicm_schan_ch[unit].lock);
    426     for (i = 0; i <= CMIC_CMC_NUM_MAX; i++) {
    427         if (_cmicm_schan_ch[unit].ch[i] & 0x01) {
    428             rv = SOC_E_NONE;
    429             *cmc = i;
    430             _cmicm_schan_ch[unit].ch[i] &= ~(0x01);
    431             break;
    432         }
    433     }
    434     sal_spinlock_unlock(_cmicm_schan_ch[unit].lock);
    435     return rv;
    436 }
    437 
    438 /*******************************************
    439 * @function cmicm_schan_ch_get
    440 * purpose get idle schan on cmc
    441 *
    442 * @param unit [in] unit #
    443 * @param cmc [out] cmc number 0-2 or 3 for common
    444 *
    445 * @returns SOC_E_BUSY
    446 * @returns SOC_E_NONE
    447 *
    448 * @end
    449  */
    450 int cmicm_schan_ch_get(int unit, int *cmc)
    451 {
    452     int rv;
    453 
    454     soc_timeout_t to;
    455 
    456     soc_timeout_init(&to, _cmicm_schan_ch[unit].timeout, 100);
    457 
    458     do {
    459         rv = _cmicm_schan_ch_get(unit, cmc);
    460         if (rv == SOC_E_NONE)
    461             break;
    462     } while (!soc_timeout_check(&to));
    463     return rv;
    464 }
    465 
    466 /*******************************************
    467 * @function cmicm_schan_ch_try_get
    468 * purpose get idle channel on cmc
    469 *
    470 * @param unit [in] unit #
    471 * @param cmc [in] cmc number 0-2 or 3 for common
    472 *
    473 * @returns SOC_E_BUSY
    474 * @returns SOC_E_NONE
    475 *
    476 * @end
    477  */
    478 int cmicm_schan_ch_try_get(int unit, int cmc)
    479 {
    480     int rv = SOC_E_BUSY;
    481 
    482     soc_timeout_t to;
    483 
    484     soc_timeout_init(&to, _cmicm_schan_ch[unit].timeout, 100);
    485 
    486     sal_spinlock_lock(_cmicm_schan_ch[unit].lock);
    487     do {
    488         if (_cmicm_schan_ch[unit].ch[cmc] & 0x01) {
    489             rv = SOC_E_NONE;
    490             _cmicm_schan_ch[unit].ch[cmc] &= ~(0x01);
    491             break;
    492         }
    493     } while (!soc_timeout_check(&to));
    494     sal_spinlock_unlock(_cmicm_schan_ch[unit].lock);
    495 
    496     return rv;
    497 }
    498 
    499 /*******************************************
    500 * @function cmicm_schan_ch_put
    501 * purpose put back the freed channel on cmc
    502 *
    503 * @param unit [in] unit #
    504 * @param cmc [in] cmc number 0-2 or 3 for common
    505 *
    506 * @returns SOC_E_PARAM
    507 * @returns SOC_E_NONE
    508 *
    509 * @end
    510  */
    511 int cmicm_schan_ch_put(int unit, int cmc)
    512 {
    513    int rv = SOC_E_NONE;
    514 
    515    if ((cmc < 0) || (cmc > CMIC_CMC_NUM_MAX)) {
    516        rv = SOC_E_PARAM;
    517        return rv;
    518    }
    519    sal_spinlock_lock(_cmicm_schan_ch[unit].lock);
    520    _cmicm_schan_ch[unit].ch[cmc] |= 0x01;
    521    sal_spinlock_unlock(_cmicm_schan_ch[unit].lock);
    522 
    523    return rv;
    524 }
    525 
    526 /*******************************************
    527 * @function cmicm_schan_ch_init
    528 * purpose API to Initialize schan channel seletion mechanism
    529 *
    530 * @param unit [in] unit
    531 * @param timeout [in] timeout
    532 *
    533 * @returns SOC_E_NONE
    534 * @returns SOC_E_XXX
    535 *
    536 * @end
    537  */
    538 int cmicm_schan_ch_init(int unit, int timeout)
    539 {
    540    int rv = SOC_E_NONE;
    541    int i;
    542 
    543    _cmicm_schan_ch[unit].lock = sal_spinlock_create("schan Lock");
    544 
    545    if (_cmicm_schan_ch[unit].lock == NULL) {
    546         return SOC_E_MEMORY;
    547    }
    548    /* Availability of channels */
    549     for (i = 0; i <= CMIC_CMC_NUM_MAX; i++) {
    550        _cmicm_schan_ch[unit].ch[i] = 0x01;
    551     }
    552    return rv;
    553 
    554 }
    555 
    556 /*******************************************
    557 * @function _soc_cmicm_schan_deinit
    558 * purpose API to de-intialize cmicm SCHAN
    559 *
    560 * @param unit [in] unit
    561 *
    562 * @returns SOC_E_NONE
    563 * @returns SOC_E_XXX
    564 *
    565 * @end
    566  */
    567 STATIC int
    568 _soc_cmicm_schan_deinit(int unit)
    569 {
    570     int cmc;
    571 
    572     for (cmc = 0; cmc <= CMIC_CMC_NUM_MAX; cmc++) {
    573        _soc_cmicm_schan_reset(unit, cmc, 0);
    574     }
    575     sal_spinlock_destroy(_cmicm_schan_ch[unit].lock);
    576 
    577     return SOC_E_NONE;
    578 }
    579 
    580 /*******************************************
    581 * @function soc_schan_cmicm_init
    582 * purpose API to Initialize cmicm SCHAN
    583 *
    584 * @param unit [in] unit
    585 * @param drv [out] soc_cmic_schan_drv_t pointer
    586 *
    587 * @returns SOC_E_NONE
    588 * @returns SOC_E_XXX
    589 *
    590 * @end
    591  */
    592 int soc_cmicm_schan_init(int unit, soc_cmic_schan_drv_t *drv)
    593 {
    594     /* Cache multi CMC flag */
    595     sal_memset(_soc_schan_multi_cmc, 0, sizeof(_soc_schan_multi_cmc));
    596     if (SOC_CHECK_MULTI_CMC(unit)) {
    597         _soc_schan_multi_cmc[unit] = 1;
    598     }
    599     drv->soc_schan_deinit = _soc_cmicm_schan_deinit;
    600     drv->soc_schan_op = _soc_cmicm_schan_op;
    601     drv->soc_schan_reset = _soc_cmicm_schan_reset;
    602 
    603     SOC_IF_ERROR_RETURN(cmicm_schan_ch_init(unit,
    604                         CMIC_CMCx_SCHAN_CHSELECT_TIMEOUT));
    605 
    606     return SOC_E_NONE;
    607 }
    608 
    609 #endif /* BCM_CMICM_SUPPORT */