cmicx_miim.c (17805B)
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 * CMICx MIIM (MDIO) functions 8 */ 9 10 #include <shared/bsl.h> 11 #include <sal/core/libc.h> 12 #include <sal/core/boot.h> 13 #include <soc/debug.h> 14 #include <soc/cm.h> 15 #include <soc/drv.h> 16 #include <soc/error.h> 17 #include <sal/core/sync.h> 18 #include <soc/util.h> 19 #include <soc/cmic.h> 20 21 #ifdef _ERR_MSG_MODULE_NAME 22 #error "_ERR_MSG_MODULE_NAME redefined" 23 #endif 24 #define _ERR_MSG_MODULE_NAME BSL_LS_SOC_MIIM 25 26 #ifdef BCM_CMICX_SUPPORT 27 #include <soc/cmicx.h> 28 #include <soc/cmicx_miim.h> 29 #include <soc/iproc.h> 30 #endif 31 32 #if (defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)) 33 #include <soc/dnxc/dnxc_ha.h> 34 #endif 35 36 #if defined(BCM_DNX_SUPPORT) 37 #include <soc/dnx/dnx_err_recovery_manager.h> 38 #include <soc/dnx/dnx_data/auto_generated/dnx_data_access.h> 39 #endif 40 41 #include <soc/phyreg.h> 42 #include <soc/linkctrl.h> 43 44 #ifdef BCM_CMICX_SUPPORT 45 46 /* determine if device supports iProc15 */ 47 int soc_is_miim_12r(int unit) 48 { 49 int is_miim_12r = 0; 50 51 /* iProc 15 devices support 12 MDIO rings */ 52 if (SOC_IS_TOMAHAWK3(unit) || SOC_IS_HELIX5(unit)) { 53 is_miim_12r = 1; 54 } 55 56 return is_miim_12r; 57 } 58 59 uint32 soc_cmicx_miim_cycle_type_get(int unit, int is_write, int clause45, uint32 phy_devad) 60 { 61 uint32 cycle_type = 0; 62 int is_miim_12r = 0; 63 64 /* iProc 15 devices support 12 MDIO rings */ 65 if (soc_is_miim_12r(unit)) { 66 is_miim_12r = 1; 67 } 68 69 if (clause45) { 70 if(is_write) { 71 if (phy_devad & MIIM_CYCLE_C45_WR) { 72 cycle_type = is_miim_12r ? MIIM_CYCLE_12R_C45_REG_WR : MIIM_CYCLE_C45_REG_WR; 73 } else if (phy_devad & MIIM_CYCLE_C45_WR_AD) { 74 cycle_type = is_miim_12r ? MIIM_CYCLE_12R_C45_REG_AD : MIIM_CYCLE_C45_REG_AD; 75 } else { 76 cycle_type = is_miim_12r ? MIIM_CYCLE_12R_C45_AUTO_WR : MIIM_CYCLE_AUTO; 77 } 78 } else { 79 if (phy_devad & MIIM_CYCLE_C45_RD) { 80 cycle_type = is_miim_12r ? MIIM_CYCLE_12R_C45_REG_RD : MIIM_CYCLE_C45_REG_RD; 81 } else if (phy_devad & MIIM_CYCLE_C45_RD_ADINC) { 82 cycle_type = is_miim_12r ? MIIM_CYCLE_12R_C45_REG_RD_ADINC : MIIM_CYCLE_C45_REG_RD_ADINC; 83 } else { 84 cycle_type = is_miim_12r ? MIIM_CYCLE_12R_C45_AUTO_RD : MIIM_CYCLE_AUTO; 85 } 86 } 87 } else { 88 /* clause 22 */ 89 if (is_write) { 90 cycle_type = is_miim_12r ? MIIM_CYCLE_12R_C22_REG_WR : MIIM_CYCLE_C22_REG_WR; 91 } else { 92 cycle_type = is_miim_12r ? MIIM_CYCLE_12R_C22_REG_RD : MIIM_CYCLE_C22_REG_RD; 93 } 94 } 95 96 LOG_DEBUG(BSL_LS_SOC_MIIM, (BSL_META_U(unit, "is_miim_12r %d, cycle_type %d\n"), is_miim_12r, cycle_type)); 97 98 return cycle_type; 99 } 100 101 /** see .h file */ 102 int 103 soc_cmicx_miim_init(int unit) 104 { 105 uint32 reg_val; 106 107 /* Give MDIO control to IPROC */ 108 READ_MIIM_COMMON_CONTROLr(unit, ®_val); 109 soc_reg_field_set(unit, MIIM_COMMON_CONTROLr, ®_val, OVRD_EXT_MDIO_MSTR_CNTRLf, 1); 110 WRITE_MIIM_COMMON_CONTROLr(unit, reg_val); 111 112 return SOC_E_NONE; 113 } 114 115 /** 116 * \brief 117 * Function to get the correct register name and the register address 118 * in dependence of the ring that should be access 119 * 120 * \param [in] unit - Unit # 121 * \param [in] ring_index - ring index to be access # 122 * \param [out] ring_reg - ring register name # 123 * \param [out] reg_addr - ring register address # 124 * 125 * \return 126 * err - see shr_error_e 127 * \remark 128 * * None 129 * \see 130 * * None 131 */ 132 static int 133 soc_cmicx_miim_ring_reg_addr_get(int unit, int ring_index, soc_reg_t * ring_reg, uint32 * reg_addr) 134 { 135 soc_reg_t ring_control_8r_reg[] = {MIIM_RING0_CONTROLr, 136 MIIM_RING1_CONTROLr, 137 MIIM_RING2_CONTROLr, 138 MIIM_RING3_CONTROLr, 139 MIIM_RING4_CONTROLr, 140 MIIM_RING5_CONTROLr, 141 MIIM_RING6_CONTROLr, 142 MIIM_RING7_CONTROLr, 143 INVALIDr}; 144 145 soc_reg_t ring_control_12r_reg[] = {MIIM_RING0_CONTROLr, 146 MIIM_RING1_CONTROLr, 147 MIIM_RING2_CONTROLr, 148 MIIM_RING3_CONTROLr, 149 MIIM_RING4_CONTROLr, 150 MIIM_RING5_CONTROLr, 151 MIIM_RING6_CONTROLr, 152 MIIM_RING7_CONTROLr, 153 MIIM_RING8_CONTROLr, 154 MIIM_RING9_CONTROLr, 155 MIIM_RING10_CONTROLr, 156 MIIM_RING11_CONTROLr, 157 INVALIDr}; 158 soc_reg_t *ring_control_reg = NULL; 159 160 int ring_idx_end = 0; 161 162 /* determine mdio ring end based on if this is iProc14 of iProc15 device */ 163 ring_idx_end = soc_is_miim_12r(unit) ? CMICX_MIIM_12R_RING_INDEX_END : CMICX_MIIM_RING_INDEX_END; 164 165 if ((ring_index < CMICX_MIIM_RING_INDEX_START) || 166 (ring_index > ring_idx_end)) { 167 LOG_ERROR(BSL_LS_SOC_MIIM, (BSL_META_U(unit, "Invalid CMICx MIIM Ring index %d\n"), ring_index)); 168 return SOC_E_PARAM; 169 } 170 171 ring_control_reg = soc_is_miim_12r(unit) ? ring_control_12r_reg : ring_control_8r_reg; 172 173 *ring_reg = ring_control_reg[ring_index]; 174 175 *reg_addr = soc_reg_addr(unit, *ring_reg, REG_PORT_ANY, 0); 176 177 return SOC_E_NONE; 178 } 179 180 /** 181 * \brief 182 * Function to get the divisor delay of the given ring 183 * 184 * \param [in] unit - Unit # 185 * \param [in] ring_index - ring index to be access # 186 * \param [out] out_delay - ring out divisor delay value # 187 * 188 * \return 189 * err - see shr_error_e 190 * \remark 191 * * None 192 * \see 193 * * None 194 */ 195 int 196 soc_cmicx_miim_divider_ring_delay_set(int unit, int ring_index, int out_delay) 197 { 198 uint32 reg_val, reg_addr; 199 soc_reg_t ring_reg; 200 SOC_INIT_FUNC_DEFS; 201 202 _SOC_IF_ERR_EXIT(soc_cmicx_miim_ring_reg_addr_get(unit, ring_index, &ring_reg, ®_addr)); 203 204 soc_iproc_getreg(unit, reg_addr, ®_val); 205 206 if (out_delay != MIIM_INTERNAL_EXTERNAL_DELAY_INVALID) { 207 soc_reg_field_set(unit, ring_reg, ®_val, MDIO_OUT_DELAYf, out_delay); 208 } 209 210 soc_iproc_setreg(unit, reg_addr, reg_val); 211 212 exit: 213 SOC_FUNC_RETURN; 214 } 215 216 /** 217 * \brief 218 * Function to set the divisor delay of the given ring 219 * 220 * \param [in] unit - Unit # 221 * \param [in] ring_index - ring index to be access # 222 * \param [int] out_delay - ring out divisor delay value # 223 * 224 * \return 225 * err - see shr_error_e 226 * \remark 227 * * None 228 * \see 229 * * None 230 */ 231 int 232 soc_cmicx_miim_divider_ring_delay_get(int unit, int ring_index, int * out_delay) 233 { 234 uint32 reg_val, reg_addr; 235 soc_reg_t ring_reg; 236 SOC_INIT_FUNC_DEFS; 237 238 _SOC_IF_ERR_EXIT(soc_cmicx_miim_ring_reg_addr_get(unit, ring_index, &ring_reg, ®_addr)); 239 240 soc_iproc_getreg(unit, reg_addr, ®_val); 241 242 *out_delay = soc_reg_field_get(unit, ring_reg, reg_val, MDIO_OUT_DELAYf); 243 244 exit: 245 SOC_FUNC_RETURN; 246 } 247 248 /** see .h file */ 249 int 250 soc_cmicx_miim_divider_set_ring(int unit, int ring_index, int int_divider, int ext_divider, int out_delay) 251 { 252 uint32 reg_val, reg_addr; 253 soc_reg_t ring_reg; 254 SOC_INIT_FUNC_DEFS; 255 256 _SOC_IF_ERR_EXIT(soc_cmicx_miim_ring_reg_addr_get(unit, ring_index, &ring_reg, ®_addr)); 257 258 soc_iproc_getreg(unit, reg_addr, ®_val); 259 260 if (int_divider != -1) { 261 soc_reg_field_set(unit, ring_reg, ®_val, CLOCK_DIVIDER_INTf, int_divider); 262 } 263 264 if (ext_divider != -1) { 265 soc_reg_field_set(unit, ring_reg, ®_val, CLOCK_DIVIDER_EXTf, ext_divider); 266 } 267 268 if (out_delay != -1) { 269 soc_reg_field_set(unit, ring_reg, ®_val, MDIO_OUT_DELAYf, out_delay); 270 } 271 272 soc_iproc_setreg(unit, reg_addr, reg_val); 273 274 exit: 275 SOC_FUNC_RETURN; 276 } 277 278 /** see .h file */ 279 int 280 soc_cmicx_miim_divider_set_all(int unit, int int_divider, int ext_divider, int out_delay) 281 { 282 int ring_idx = 0; 283 int ring_idx_end = 0; 284 285 /* determine mdio ring end based on if this is iProc14 of iProc15 device */ 286 ring_idx_end = soc_is_miim_12r(unit) ? CMICX_MIIM_12R_RING_INDEX_END : CMICX_MIIM_RING_INDEX_END; 287 288 for (ring_idx = CMICX_MIIM_RING_INDEX_START; ring_idx <= ring_idx_end; ring_idx++) { 289 soc_cmicx_miim_divider_set_ring(unit, ring_idx, int_divider, ext_divider, out_delay); 290 } 291 292 return SOC_E_NONE; 293 } 294 295 /** see .h file */ 296 int 297 soc_cmicx_miim_operation(int unit, int is_write, int clause, int int_delay, int ext_delay, 298 uint32 phy_id, uint32 phy_reg_addr, uint16 *phy_data) 299 { 300 uint32 reg_val = 0, internal_select, real_phy_id, real_bus_id, is_done, is_error; 301 uint32 devad = 0; 302 soc_timeout_t to; 303 int clause45 = 0; 304 uint32 cycle_type = 0, phy_devad = 0; 305 int current_out_delay = 0, new_out_delay = 0; 306 SOC_INIT_FUNC_DEFS; 307 308 #if (defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)) 309 if (SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) { 310 if (is_write && dnxc_ha_is_access_disabled(unit,DNXC_HA_ALLOW_SCHAN)) 311 { 312 LOG_WARN(BSL_LS_SOC_MIIM, 313 (BSL_META_U(unit, 314 "soc_cmicx_miim_operation: ERROR, It is not currently allowed to modify HW\n"))); 315 _SOC_IF_ERR_EXIT(SOC_E_FAIL); 316 } 317 } 318 #endif 319 320 #if defined(BCM_DNX_SUPPORT) && defined(DNX_ERR_RECOVERY_VALIDATION) 321 322 if (SOC_IS_DNX(unit)) { 323 if (is_write && !DNX_ERR_RECOVERY_HW_ACCESS_IS_VALID(unit)) 324 { 325 LOG_WARN(BSL_LS_SOC_MIIM, 326 (BSL_META_U(unit, 327 "soc_cmicx_miim_operation: ERROR, Invalid error recovery hw access\n"))); 328 _SOC_IF_ERR_EXIT(SOC_E_FAIL); 329 } 330 } 331 #endif 332 333 clause45 = (SOC_CLAUSE_45 == clause); 334 335 /* parse phy_id to bus, phy, and internal indication 336 * phy_id encoding: 337 * bit7, 1: internal MDIO bus, 0: external MDIO bus 338 * bit9,8,6,5, mdio bus number 339 * bit4-0, mdio addresses 340 */ 341 internal_select = (phy_id & 0x80) ? 1 : 0; 342 real_phy_id = phy_id & ~(PHY_ID_BUS_UPPER_MASK | PHY_ID_BUS_LOWER_MASK); 343 real_phy_id &= ~(0x80); /*clear internal / external bit*/ 344 real_bus_id = PHY_ID_BUS_NUM(phy_id); 345 346 MIIM_LOCK(unit); 347 348 /** 349 * Workaround to artificially support different divider delays for INTERNAL and EXTERNAL DIVISORs 350 */ 351 _SOC_IF_ERR_EXIT(soc_cmicx_miim_divider_ring_delay_get(unit, real_bus_id, ¤t_out_delay)); 352 new_out_delay = internal_select ? int_delay : ext_delay; 353 /** 354 * Change only if new and old are different and if an actual valid delay value was rovided 355 */ 356 if(new_out_delay != current_out_delay && new_out_delay != MIIM_INTERNAL_EXTERNAL_DELAY_INVALID) { 357 _SOC_IF_ERR_EXIT(soc_cmicx_miim_divider_ring_delay_set(unit, real_bus_id, new_out_delay)); 358 } 359 360 /* preper transaction data */ 361 /* _SOC_IF_ERR_EXIT(READ_MIIM_CH0_ADDRESSr(unit, ®_val)); */ 362 _SOC_IF_ERR_EXIT(soc_iproc_getreg(unit, soc_reg_addr(unit, MIIM_CH0_ADDRESSr, REG_PORT_ANY, 0), ®_val)); 363 soc_reg_field_set(unit, MIIM_CH0_ADDRESSr, ®_val, PHY_IDf, real_phy_id); 364 365 if (clause45) { 366 /* cleanup of devad flags */ 367 devad = SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr) & 0x1f; 368 369 soc_reg_field_set(unit, MIIM_CH0_ADDRESSr, ®_val, CLAUSE_45_REG_ADRRf, SOC_PHY_CLAUSE45_REGAD(phy_reg_addr)); 370 371 /* IPROC 15 and higher devices */ 372 if (soc_is_miim_12r(unit)) { 373 soc_reg_field_set(unit, MIIM_CH0_ADDRESSr, ®_val, CLAUSE_22_REGADRR_OR_45_DTYPEf, devad); 374 } else { 375 soc_reg_field_set(unit, MIIM_CH0_ADDRESSr, ®_val, CLAUSE_45_DTYPEf, devad); 376 } 377 } else { 378 /* IPROC 15 and higher devices */ 379 if (soc_is_miim_12r(unit)) { 380 soc_reg_field_set(unit, MIIM_CH0_ADDRESSr, ®_val, CLAUSE_22_REGADRR_OR_45_DTYPEf, (phy_reg_addr & 0x1f)); 381 } else { 382 soc_reg_field_set(unit, MIIM_CH0_ADDRESSr, ®_val, CLAUSE_22_REG_ADRRf, (phy_reg_addr & 0x1f)); 383 } 384 } 385 /* _SOC_IF_ERR_EXIT(WRITE_MIIM_CH0_ADDRESSr(unit, reg_val)); */ 386 _SOC_IF_ERR_EXIT(soc_iproc_setreg(unit, soc_reg_addr(unit, MIIM_CH0_ADDRESSr, REG_PORT_ANY, 0), reg_val)); 387 388 if (clause45){ 389 LOG_VERBOSE(BSL_LS_SOC_MIIM, 390 (BSL_META_U(unit, 391 "soc_cmicx_miim_operation cl45 %s: " 392 "(id=0x%02x readr=0x%x dtype=0x%x data=0x%04x clause45=%d, real_phy_id=%d, real_bus_id=%d)\n"), 393 is_write ? "write" : "read ", phy_id, SOC_PHY_CLAUSE45_REGAD(phy_reg_addr), SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr), 394 *phy_data, clause45, real_phy_id,real_bus_id)); 395 } else { 396 LOG_VERBOSE(BSL_LS_SOC_MIIM, 397 (BSL_META_U(unit, 398 "soc_cmicx_miim_operation cl22 %s: " 399 "(id=0x%02x addr=0x%02x data=0x%04x clause45=%d, real_phy_id=%d, real_bus_id=%d)\n"), 400 is_write ? "write" : "read ", phy_id, phy_reg_addr, *phy_data, clause45,real_phy_id,real_bus_id)); 401 } 402 403 /* _SOC_IF_ERR_EXIT(READ_MIIM_CH0_PARAMSr(unit, ®_val)); */ 404 _SOC_IF_ERR_EXIT(soc_iproc_getreg(unit, soc_reg_addr(unit, MIIM_CH0_PARAMSr, REG_PORT_ANY, 0), ®_val)); 405 soc_reg_field_set(unit, MIIM_CH0_PARAMSr, ®_val, SEL_INT_PHYf, internal_select); 406 soc_reg_field_set(unit, MIIM_CH0_PARAMSr, ®_val, RING_MAPf, (1 << real_bus_id)); 407 408 /* Only applicable for iProc 14 devices */ 409 if (!soc_is_miim_12r(unit)) { 410 soc_reg_field_set(unit, MIIM_CH0_PARAMSr, ®_val, SEL_CL45f, clause45); 411 soc_reg_field_set(unit, MIIM_CH0_PARAMSr, ®_val, RD_ENf, is_write ? 0 : 1); 412 soc_reg_field_set(unit, MIIM_CH0_PARAMSr, ®_val, WR_ENf, is_write ? 1 : 0); 413 } 414 415 /* 416 * Configure correct MDIO CYCLE type depending on if this data only mode 417 * without corresponding address cycle for MDIO transcation. 418 */ 419 phy_devad = phy_reg_addr >> 16; 420 cycle_type = soc_cmicx_miim_cycle_type_get(unit, is_write, clause45, phy_devad); 421 422 /* IPROC 15 and higher devices */ 423 if (soc_is_miim_12r(unit)) { 424 soc_reg_field_set(unit, MIIM_CH0_PARAMSr, ®_val, MDIO_OP_TYPEf, cycle_type); 425 } else { 426 soc_reg_field_set(unit, MIIM_CH0_PARAMSr, ®_val, MDIO_CYCLEf, cycle_type); 427 } 428 429 if(is_write) { 430 soc_reg_field_set(unit, MIIM_CH0_PARAMSr, ®_val, PHY_WR_DATAf, *phy_data); 431 } else { 432 soc_reg_field_set(unit, MIIM_CH0_PARAMSr, ®_val, PHY_WR_DATAf, 0x0); 433 } 434 435 /* _SOC_IF_ERR_EXIT(WRITE_MIIM_CH0_PARAMSr(unit, reg_val)); */ 436 _SOC_IF_ERR_EXIT(soc_iproc_setreg(unit, soc_reg_addr(unit, MIIM_CH0_PARAMSr, REG_PORT_ANY, 0), reg_val)); 437 438 /* start transaction */ 439 reg_val = 0; 440 soc_reg_field_set(unit, MIIM_CH0_CONTROLr, ®_val, STARTf, 0x1); 441 /* _SOC_IF_ERR_EXIT(WRITE_MIIM_CH0_CONTROLr(unit, reg_val)); */ 442 _SOC_IF_ERR_EXIT(soc_iproc_setreg(unit, soc_reg_addr(unit, MIIM_CH0_CONTROLr, REG_PORT_ANY, 0), reg_val)); 443 444 /* poll for DONE bit*/ 445 soc_timeout_init(&to, SOC_CONTROL(unit)->miimTimeout, 2500); 446 447 while (1){ 448 /* _SOC_IF_ERR_EXIT(READ_MIIM_CH0_STATUSr(unit, ®_val)); */ 449 _SOC_IF_ERR_EXIT(soc_iproc_getreg(unit, soc_reg_addr(unit, MIIM_CH0_STATUSr, REG_PORT_ANY, 0), ®_val)); 450 is_done = soc_reg_field_get(unit, MIIM_CH0_STATUSr, reg_val, DONEf); 451 if (is_done) { 452 break; /* MIIM operation is done */ 453 } 454 455 if (soc_timeout_check(&to)) { 456 LOG_ERROR(BSL_LS_SOC_MIIM, 457 (BSL_META_U(unit, 458 "MiimTimeOut: %s, " 459 "timeout (id=0x%02x addr=0x%02x)\n"), 460 is_write ? "write" : "read" , 461 phy_id, phy_reg_addr)); 462 _SOC_IF_ERR_EXIT(SOC_E_TIMEOUT); 463 } 464 } 465 466 LOG_DEBUG(BSL_LS_SOC_MIIM, 467 (BSL_META_U(unit, 468 " Done in %d polls\n"), to.polls)); 469 470 /* check for transaction error */ 471 is_error = soc_reg_field_get(unit, MIIM_CH0_STATUSr, reg_val, ERRORf); 472 if (is_error) { 473 LOG_ERROR(BSL_LS_SOC_MIIM, 474 (BSL_META_U(unit, 475 " MDIO transaction Error\n"))); 476 _SOC_IF_ERR_EXIT(SOC_E_FAIL); 477 } 478 479 /* in case of read - get data */ 480 if (!is_write) { 481 *phy_data = (uint16)soc_reg_field_get(unit, MIIM_CH0_STATUSr, reg_val, PHY_RD_DATAf); 482 LOG_VERBOSE(BSL_LS_SOC_MIIM, 483 (BSL_META_U(unit, 484 "soc_cmicx_miim_operation read data: %d \n"),*phy_data)); 485 } 486 487 /* cleanup */ 488 reg_val = 0; 489 soc_reg_field_set(unit, MIIM_CH0_CONTROLr, ®_val, STARTf, 0x0); 490 /* _SOC_IF_ERR_EXIT(WRITE_MIIM_CH0_CONTROLr(unit, reg_val)); */ 491 _SOC_IF_ERR_EXIT(soc_iproc_setreg(unit, soc_reg_addr(unit, MIIM_CH0_CONTROLr, REG_PORT_ANY, 0), reg_val)); 492 493 exit: 494 /* in case we failed - try to cleanup */ 495 if (SOC_FUNC_ERROR) { 496 reg_val = 0; 497 soc_reg_field_set(unit, MIIM_CH0_CONTROLr, ®_val, STARTf, 0x0); 498 /* WRITE_MIIM_CH0_CONTROLr(unit, reg_val); */ /* no need to catch error in case of failrue */ 499 _SOC_IF_ERR_EXIT(soc_iproc_setreg(unit, soc_reg_addr(unit, MIIM_CH0_CONTROLr, REG_PORT_ANY, 0), reg_val)); 500 } 501 502 /* Release linkscan pause and MIIM lock */ 503 MIIM_UNLOCK(unit); 504 505 SOC_FUNC_RETURN; 506 } 507 508 #endif /* BCM_CMICX_SUPPORT */