link.c (86246B)
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 * Hardware Linkscan module 8 * 9 * Hardware linkscan is available, but its use is not recommended 10 * because a software linkscan task is very low overhead and much more 11 * flexible. 12 * 13 * If hardware linkscan is used, each MII operation must temporarily 14 * disable it and wait for the current scan to complete, increasing the 15 * latency. PHY status register 1 may contain clear-on-read bits that 16 * will be cleared by hardware linkscan and not seen later. Special 17 * support is provided for the Serdes MAC. 18 */ 19 20 #include <shared/bsl.h> 21 22 #include <sal/core/libc.h> 23 #include <sal/core/boot.h> 24 25 #include <soc/mem.h> 26 #include <soc/debug.h> 27 #include <soc/cm.h> 28 #include <soc/drv.h> 29 #include <soc/error.h> 30 #include <soc/cmic.h> 31 #ifdef BCM_CMICM_SUPPORT 32 #include <soc/cmicm.h> 33 #endif 34 #ifdef BCM_CMICX_SUPPORT 35 #include <shared/cmicfw/cmicx_link.h> 36 #define CMICX_HW_LINKSCAN 1 37 #endif 38 #include <soc/defs.h> 39 40 #ifdef PORTMOD_SUPPORT 41 #include <soc/portmod/portmod.h> 42 #include <soc/portmod/portmod_common.h> 43 #endif /* PORTMOD_SUPPORT */ 44 45 #ifdef BCM_SABER2_SUPPORT 46 #include <soc/saber2.h> 47 #endif 48 49 #ifdef BCM_TOMAHAWK3_SUPPORT 50 #include <soc/tomahawk3.h> 51 #endif 52 53 #ifdef BCM_HURRICANE3_SUPPORT 54 #include <soc/wolfhound2.h> 55 #endif /* BCM_HURRICANE3_SUPPORT */ 56 57 #if 64 > SOC_MAX_NUM_PORTS 58 #define SOC_CMIC_PHY_PORT_MAX (64) 59 #else 60 #define SOC_CMIC_PHY_PORT_MAX (SOC_MAX_NUM_PORTS) 61 #endif 62 63 #if defined(BCM_CMICM_SUPPORT) 64 65 #ifndef SOC_CMICM_PHY_PORT_MAX 66 #define SOC_CMICM_PHY_PORT_MAX (128) 67 #endif 68 #if SOC_CMICM_PHY_PORT_MAX > SOC_CMIC_PHY_PORT_MAX 69 #undef SOC_CMIC_PHY_PORT_MAX 70 #define SOC_CMIC_PHY_PORT_MAX SOC_CMICM_PHY_PORT_MAX 71 #endif 72 73 #if defined(BCM_CMICDV2_SUPPORT) 74 #ifndef SOC_CMICDV2_PHY_PORT_MAX 75 #define SOC_CMICDV2_PHY_PORT_MAX (SOC_CMICM_PHY_PORT_MAX + 64) 76 #endif 77 #if SOC_CMICDV2_PHY_PORT_MAX > SOC_CMIC_PHY_PORT_MAX 78 #undef SOC_CMIC_PHY_PORT_MAX 79 #define SOC_CMIC_PHY_PORT_MAX SOC_CMICDV2_PHY_PORT_MAX 80 #endif 81 82 #if defined(BCM_CMICDV4_SUPPORT) 83 #ifndef SOC_CMICDV4_PHY_PORT_MAX 84 #define SOC_CMICDV4_PHY_PORT_MAX (SOC_CMICDV2_PHY_PORT_MAX + 128) 85 #endif 86 #if SOC_CMICDV4_PHY_PORT_MAX > SOC_CMIC_PHY_PORT_MAX 87 #undef SOC_CMIC_PHY_PORT_MAX 88 #define SOC_CMIC_PHY_PORT_MAX SOC_CMICDV4_PHY_PORT_MAX 89 #endif 90 #endif /* BCM_CMICDV4_SUPPORT */ 91 #endif /* BCM_CMICDV2_SUPPORT */ 92 93 #endif /* BCM_CMICM_SUPPORT */ 94 95 #define SOC_BITWORD_SET(_a, _word, _val) _a[_word] = _val 96 #define SOC_BITWORD_GET(_a, _word) _a[_word] 97 98 #ifdef BCM_APACHE_SUPPORT 99 /* In Apache, phy ports 1-36 are mapped to 100 * CMIC_MIIM_SCAN_PORTS_0 and CMIC_MIIM_SCAN_PORTS_1 101 * CMIC_MIIM_INT_SEL_MAP_0 and CMIC_MIIM_INT_SEL_MAP_1 102 * CMIC_MIIM_LINK_STATUS_0 and CMIC_MIIM_LINK_STATUS_1 103 * phy ports 37-72 are mapped to 104 * CMIC_MIIM_SCAN_PORTS_2 and CMIC_MIIM_SCAN_PORTS_3 105 * CMIC_MIIM_INT_SEL_MAP_2 and CMIC_MIIM_INT_SEL_MAP_3 106 * CMIC_MIIM_LINK_STATUS_2 and CMIC_MIIM_LINK_STATUS_3 107 */ 108 #define MAX_PORTS_PER_SCAN_CHAIN 64 109 #define APACHE_PORTS_PER_SCAN_CHAIN 36 110 #define APACHE_UNUSED_PORTS_PER_SCAN_CHAIN (MAX_PORTS_PER_SCAN_CHAIN - APACHE_PORTS_PER_SCAN_CHAIN) 111 #define PHY_PORT_TO_LINKSCAN_PORT_XLATE(unit, phy_port) \ 112 do { \ 113 if (SOC_IS_APACHE(unit)) { \ 114 phy_port = (phy_port > APACHE_PORTS_PER_SCAN_CHAIN) ? \ 115 (phy_port + APACHE_UNUSED_PORTS_PER_SCAN_CHAIN) : phy_port;\ 116 } \ 117 } while (0); 118 #define LINKSCAN_PORT_TO_PHY_PORT_XLATE(unit, phy_port) \ 119 do { \ 120 if (SOC_IS_APACHE(unit)) { \ 121 phy_port = ((phy_port > APACHE_PORTS_PER_SCAN_CHAIN) && \ 122 (phy_port <= MAX_PORTS_PER_SCAN_CHAIN)) ? -1 : \ 123 (phy_port > MAX_PORTS_PER_SCAN_CHAIN) ? \ 124 (phy_port - APACHE_UNUSED_PORTS_PER_SCAN_CHAIN) : phy_port;\ 125 } \ 126 } while (0); 127 #else 128 #define PHY_PORT_TO_LINKSCAN_PORT_XLATE(unit, phy_port) 129 #define LINKSCAN_PORT_TO_PHY_PORT_XLATE(unit, phy_port) 130 #endif 131 #define GREYHOUND2_PHY_PORT_OFFSET 7 132 /* 133 * Function: 134 * _soc_link_update 135 * Purpose: 136 * Update the forwarding state in the chip (EPC_LINK). 137 * Parameters: 138 * unit - StrataSwitch unit #. 139 * Returns: 140 * SOC_E_XXX 141 * NOTE: 142 * soc_link_fwd_set and soc_link_mask2_set call 143 * this function to update EPC_LINK_BMAP. soc_link_fwd_set is called 144 * with LINK_LOCK and soc_link_mask2_set is called with PORT_LOCK. 145 * No synchronization mechanism is implemented in this function. Therefore, 146 * the user must make sure that the call to this function is synchronized 147 * between linkscan thread and calling thread. 148 */ 149 150 STATIC int 151 _soc_link_update(int unit) 152 { 153 pbmp_t pbm; 154 #ifdef BCM_TOMAHAWK3_SUPPORT 155 pbmp_t temp_pbm; 156 #endif 157 soc_control_t *soc = SOC_CONTROL(unit); 158 soc_persist_t *sop = SOC_PERSIST(unit); 159 char pfmtl[SOC_PBMP_FMT_LEN], 160 pfmtm2[SOC_PBMP_FMT_LEN], 161 pfmtp[SOC_PBMP_FMT_LEN]; 162 163 COMPILER_REFERENCE(pfmtl); 164 COMPILER_REFERENCE(pfmtm2); 165 COMPILER_REFERENCE(pfmtp); 166 167 SOC_PBMP_ASSIGN(pbm, sop->link_fwd); 168 SOC_PBMP_AND(pbm, soc->link_mask2); 169 170 #if defined(BCM_SABER2_SUPPORT) 171 if (SOC_IS_SABER2(unit)) { 172 /* In Saber2, if OAMP is enabled, keep the OAMP port(5) up */ 173 uint32 rval; 174 SOC_IF_ERROR_RETURN(READ_OAMP_ENABLEr(unit, &rval)); 175 if(soc_reg_field_get(unit, OAMP_ENABLEr, rval, ENABLEf)) { 176 SOC_PBMP_PORT_ADD(pbm, SOC_SB2_SAT_OAMP_PHY_PORT_NUMBER); 177 } 178 } 179 #endif 180 181 LOG_VERBOSE(BSL_LS_SOC_LINK, 182 (BSL_META_U(unit, 183 "_soc_link_update: link=%s m2=%s pbm=%s\n"), 184 SOC_PBMP_FMT(sop->link_fwd, pfmtl), 185 SOC_PBMP_FMT(soc->link_mask2, pfmtm2), 186 SOC_PBMP_FMT(pbm, pfmtp))); 187 188 #ifdef BCM_HERCULES_SUPPORT 189 if (SOC_IS_HERCULES(unit)) { 190 int port; 191 uint32 nlink, olink; 192 193 nlink = SOC_PBMP_WORD_GET(pbm, 0); 194 olink = -1; 195 PBMP_PORT_ITER(unit, port) { 196 SOC_IF_ERROR_RETURN 197 (READ_ING_EPC_LNKBMAPr(unit, port, &olink)); 198 break; 199 } 200 201 if (nlink != olink) { 202 PBMP_PORT_ITER(unit, port) { 203 SOC_IF_ERROR_RETURN 204 (WRITE_ING_EPC_LNKBMAPr(unit, port, nlink)); 205 } 206 } 207 return SOC_E_NONE; 208 } 209 #endif /* BCM_HERCULES_SUPPORT */ 210 211 #ifdef BCM_TRIUMPH_SUPPORT 212 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit) || 213 SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_KATANAX(unit) || 214 SOC_IS_SABER2(unit)) { 215 epc_link_bmap_entry_t entry; 216 SOC_IF_ERROR_RETURN(READ_EPC_LINK_BMAPm(unit, MEM_BLOCK_ALL, 0, 217 &entry)); 218 219 #ifdef BCM_TOMAHAWK3_SUPPORT 220 if (SOC_IS_TOMAHAWK3(unit)) { 221 /* For TH3-5341 WAR, we need to allow the spare port to be 222 set in the epc link bmap. This will allow to send packet to 223 the spare port and not override the bitmap with valid ports. 224 */ 225 soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm, &entry, PORT_BITMAPf, 226 &temp_pbm); 227 if (SOC_PBMP_MEMBER(temp_pbm, _TH3_MMU_SPARE_DST_PORT)) { 228 SOC_PBMP_CLEAR(temp_pbm); 229 SOC_PBMP_PORT_SET(temp_pbm, _TH3_MMU_SPARE_DST_PORT); 230 SOC_PBMP_OR(pbm, temp_pbm); 231 } 232 if (SOC_PBMP_MEMBER(temp_pbm, _TH3_MMU_SPARE_SRC_PORT)) { 233 SOC_PBMP_CLEAR(temp_pbm); 234 SOC_PBMP_PORT_SET(temp_pbm, _TH3_MMU_SPARE_SRC_PORT); 235 SOC_PBMP_OR(pbm, temp_pbm); 236 } 237 } 238 #endif 239 soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, &entry, PORT_BITMAPf, 240 &pbm); 241 if (SOC_MEM_FIELD_VALID(unit, EPC_LINK_BMAPm, ENABLE_SOBMH_BLOCKINGf)) { 242 soc_mem_field32_set(unit, EPC_LINK_BMAPm, &entry, 243 ENABLE_SOBMH_BLOCKINGf, 1); 244 } 245 SOC_IF_ERROR_RETURN(WRITE_EPC_LINK_BMAPm(unit, MEM_BLOCK_ALL, 0, 246 &entry)); 247 248 if (soc_feature(unit, soc_feature_ingress_dest_port_enable)) { 249 ing_dest_port_enable_entry_t dest_en; 250 SOC_IF_ERROR_RETURN 251 (READ_ING_DEST_PORT_ENABLEm(unit, MEM_BLOCK_ANY, 0, &dest_en)); 252 253 soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, 254 &dest_en, PORT_BITMAPf, &pbm); 255 256 SOC_IF_ERROR_RETURN 257 (WRITE_ING_DEST_PORT_ENABLEm(unit, MEM_BLOCK_ANY, 0, &dest_en)); 258 } 259 260 return SOC_E_NONE; 261 } else if (SOC_IS_TR_VL(unit) && !SOC_IS_ENDURO(unit) && !SOC_IS_HURRICANE(unit) 262 && !SOC_IS_GREYHOUND2(unit)) { 263 uint64 nlink64, olink64; 264 265 COMPILER_64_SET(nlink64, SOC_PBMP_WORD_GET(pbm, 1), 266 SOC_PBMP_WORD_GET(pbm, 0)); 267 268 SOC_IF_ERROR_RETURN 269 (soc_reg64_read_any_block(unit, EPC_LINK_BMAP_64r, &olink64)); 270 if (COMPILER_64_NE(nlink64, olink64)) { 271 SOC_IF_ERROR_RETURN 272 (soc_reg64_write_all_blocks(unit, EPC_LINK_BMAP_64r, nlink64)); 273 } 274 return SOC_E_NONE; 275 } else if (SOC_IS_GREYHOUND2(unit)) { 276 uint64 nlink64, olink64; 277 278 COMPILER_64_SET(nlink64, SOC_PBMP_WORD_GET(pbm, 1), 279 SOC_PBMP_WORD_GET(pbm, 0)); 280 SOC_IF_ERROR_RETURN 281 (soc_reg64_read_any_block(unit, EPC_LINK_BMAP_LO_64r, &olink64)); 282 if (COMPILER_64_NE(nlink64, olink64)) { 283 SOC_IF_ERROR_RETURN 284 (soc_reg64_write_all_blocks(unit, EPC_LINK_BMAP_LO_64r, nlink64)); 285 } 286 COMPILER_64_SET(nlink64, SOC_PBMP_WORD_GET(pbm, 3), 287 SOC_PBMP_WORD_GET(pbm, 2)); 288 SOC_IF_ERROR_RETURN 289 (soc_reg64_read_any_block(unit, EPC_LINK_BMAP_HI_64r, &olink64)); 290 if (COMPILER_64_NE(nlink64, olink64)) { 291 SOC_IF_ERROR_RETURN 292 (soc_reg64_write_all_blocks(unit, EPC_LINK_BMAP_HI_64r, nlink64)); 293 } 294 return SOC_E_NONE; 295 } else if(SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE(unit)){ 296 uint32 olink, nlink; 297 nlink = SOC_PBMP_WORD_GET(pbm, 0); 298 299 SOC_IF_ERROR_RETURN 300 (soc_reg_read_any_block(unit, EPC_LINK_BMAP_64r, &olink)); 301 if (nlink != olink) { 302 SOC_IF_ERROR_RETURN 303 (soc_reg_write_all_blocks(unit, EPC_LINK_BMAP_64r, nlink)); 304 } 305 return SOC_E_NONE; 306 } 307 #endif 308 309 #ifdef BCM_ESW_SUPPORT 310 if (SOC_IS_XGS_SWITCH(unit)) { 311 uint32 olink, nlink; 312 313 #if defined(BCM_RAPTOR_SUPPORT) 314 if (soc_feature(unit, soc_feature_register_hi)) { 315 SOC_IF_ERROR_RETURN 316 (WRITE_EPC_LINK_BMAP_HIr(unit, SOC_PBMP_WORD_GET(pbm, 1))); 317 } 318 #endif /* BCM_RAPTOR_SUPPORT */ 319 320 SOC_IF_ERROR_RETURN 321 (soc_reg_read_any_block(unit, EPC_LINK_BMAPr, &olink)); 322 nlink = SOC_PBMP_WORD_GET(pbm, 0); 323 if (nlink != olink) { 324 if (SOC_IS_SHADOW(unit)) { 325 /* Deal with aggregated Interlaken ports */ 326 if (SOC_PBMP_MEMBER(pbm, 9) && 327 !(SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all), 9))) { 328 SOC_PBMP_PORT_ADD(pbm, 10); 329 SOC_PBMP_PORT_ADD(pbm, 11); 330 SOC_PBMP_PORT_ADD(pbm, 12); 331 } 332 if (SOC_PBMP_MEMBER(pbm, 13) && 333 !(SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all), 13))) { 334 SOC_PBMP_PORT_ADD(pbm, 14); 335 SOC_PBMP_PORT_ADD(pbm, 15); 336 SOC_PBMP_PORT_ADD(pbm, 16); 337 } 338 nlink = SOC_PBMP_WORD_GET(pbm, 0); 339 } 340 SOC_IF_ERROR_RETURN 341 (soc_reg_write_all_blocks(unit, EPC_LINK_BMAPr, nlink)); 342 } 343 return SOC_E_NONE; 344 } 345 #endif /* BCM_ESW_SUPPORT */ 346 347 return SOC_E_NONE; /* SOC_E_UNAVAIL? */ 348 } 349 350 /* 351 * Function: 352 * soc_link_fwd_set 353 * Purpose: 354 * Sets EPC_LINK independent of chip type. 355 * Parameters: 356 * unit - StrataSwitch unit #. 357 * pbmp - Value. 358 * Returns: 359 * SOC_E_XXX 360 * Notes: 361 * EPC_LINK should be manipulated only through this routine and 362 * soc_link_maskX_set. 363 */ 364 365 int 366 soc_link_fwd_set(int unit, pbmp_t fwd) 367 { 368 SOC_PERSIST(unit)->link_fwd = fwd; 369 370 return _soc_link_update(unit); 371 } 372 373 /* 374 * Function: 375 * soc_link_fwd_get 376 * Purpose: 377 * Gets EPC_LINK independent of chip type. 378 * Parameters: 379 * unit - StrataSwitch unit #. 380 * pbmp - (OUT) Value. 381 */ 382 383 void 384 soc_link_fwd_get(int unit, pbmp_t *fwd) 385 { 386 *fwd = SOC_PERSIST(unit)->link_fwd; 387 } 388 389 /* 390 * Function: 391 * soc_link_mask2_set 392 * Purpose: 393 * Mask bits in EPC_LINK independent of soc_link_fwd value. 394 * Parameters: 395 * unit - StrataSwitch unit #. 396 * mask - Value. 397 * Returns: 398 * SOC_E_XXX 399 * Notes: 400 * This routine is used to clear bits in the EPC_LINK to support 401 * the mac_fe/ge_enable_set() calls. 402 */ 403 404 int 405 soc_link_mask2_set(int unit, pbmp_t mask) 406 { 407 #if defined(BCM_KATANA2_SUPPORT) 408 int pp_port_id = 0; 409 #endif 410 411 SOC_CONTROL(unit)->link_mask2 = mask; 412 413 #if defined(BCM_KATANA2_SUPPORT) 414 if (soc_feature(unit, soc_feature_linkphy_coe) && 415 SOC_INFO(unit).linkphy_enabled) { 416 SOC_PBMP_REMOVE(SOC_CONTROL(unit)->link_mask2, 417 SOC_INFO(unit).linkphy_pbm); 418 /* If the pp_port is set in the enabled linkphy bmap, set the same in the 419 * link_mask2 bmap, do this only for pp_ports. 420 */ 421 SOC_PBMP_ITER(SOC_INFO(unit).enabled_linkphy_pp_port_pbm, pp_port_id) { 422 if (SOC_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port_id)) { 423 SOC_PBMP_PORT_ADD(SOC_CONTROL(unit)->link_mask2, pp_port_id); 424 } 425 } else { 426 if (SOC_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port_id)) { 427 SOC_PBMP_PORT_REMOVE(SOC_CONTROL(unit)->link_mask2, pp_port_id); 428 } 429 } 430 } 431 if (soc_feature(unit, soc_feature_subtag_coe) && 432 SOC_INFO(unit).subtag_enabled) { 433 SOC_PBMP_REMOVE(SOC_CONTROL(unit)->link_mask2, 434 SOC_INFO(unit).subtag_pbm); 435 /* If the pp_port is set in the enabled subtag bmap, set the same in the 436 * link_mask2 bmap, do this only for pp_ports 437 */ 438 SOC_PBMP_ITER(SOC_INFO(unit).enabled_subtag_pp_port_pbm, pp_port_id) { 439 if (SOC_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port_id)) { 440 SOC_PBMP_PORT_ADD(SOC_CONTROL(unit)->link_mask2, pp_port_id); 441 } 442 } else { 443 if (SOC_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port_id)) { 444 SOC_PBMP_PORT_REMOVE(SOC_CONTROL(unit)->link_mask2, pp_port_id); 445 } 446 } 447 } 448 #endif 449 450 return _soc_link_update(unit); 451 } 452 453 /* 454 * Function: 455 * soc_link_mask2_get 456 * Purpose: 457 * Counterpart to soc_link_mask2_set 458 * Parameters: 459 * unit - StrataSwitch unit #. 460 * mask - (OUT) Value. 461 */ 462 463 void 464 soc_link_mask2_get(int unit, pbmp_t *mask) 465 { 466 *mask = SOC_CONTROL(unit)->link_mask2; 467 } 468 469 #if defined(BCM_ESW_SUPPORT) 470 /* 471 * Function: 472 * _soc_link_scan_ports_write 473 * Purpose: 474 * Writes the CMIC_SCAN_PORTS register(s) of the device with the 475 * provided HW linkscan port configuration. 476 * Parameters: 477 * unit - StrataSwitch unit #. 478 * hw_mii_pbm - Scan ports. 479 * Returns: 480 * Nothing 481 * Notes: 482 * Assumes interrupt suspension handled in the calling function 483 */ 484 485 STATIC void 486 _soc_link_scan_ports_write(int unit, pbmp_t hw_mii_pbm) 487 { 488 uint32 link_pbmp; 489 SHR_BITDCL pb[_SHR_BITDCLSIZE(SOC_CMIC_PHY_PORT_MAX)] = {0}; 490 soc_port_t phy_port, port; 491 492 link_pbmp = SOC_PBMP_WORD_GET(hw_mii_pbm, 0); 493 #if defined(BCM_GOLDWING_SUPPORT) 494 if (SOC_IS_GOLDWING(unit)) { 495 /* (MSB) 15-14-19-18-17-16-13-12-11-10-9-8-7-6-5-4-3-2-1-0 (LSB) */ 496 link_pbmp = (link_pbmp & 0x00003FFF) | 497 ((link_pbmp & 0x000F0000) >> 2) | 498 ((link_pbmp & 0x0000C000) << 4); 499 } 500 #endif /* BCM_GOLDWING_SUPPORT */ 501 #if defined (BCM_SCORPION_SUPPORT) 502 if (SOC_IS_SC_CQ(unit)) { 503 /* CMIC port not included in link status */ 504 link_pbmp >>= 1; 505 } 506 #endif /* BCM_SCORPION_SUPPORT */ 507 sal_memset(pb, 0, sizeof(SHR_BITDCL) * _SHR_BITDCLSIZE(SOC_CMIC_PHY_PORT_MAX)); 508 if (soc_feature(unit, soc_feature_logical_port_num)) { 509 PBMP_ITER(hw_mii_pbm, port) { 510 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 511 #ifdef BCM_GREYHOUND2_SUPPORT 512 if (SOC_IS_GREYHOUND2(unit)) { 513 phy_port = (phy_port >= 58) ? (phy_port + GREYHOUND2_PHY_PORT_OFFSET) 514 : phy_port; 515 } 516 #endif /* BCM_GREYHOUND2_SUPPORT */ 517 if (phy_port == 0) { 518 continue; 519 } 520 if (SOC_IS_HURRICANE2(unit) || SOC_IS_HURRICANE3(unit) || 521 SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit)) { 522 SHR_BITSET(pb, phy_port); 523 } else { 524 PHY_PORT_TO_LINKSCAN_PORT_XLATE(unit, phy_port); 525 SHR_BITSET(pb, phy_port - 1); 526 } 527 } 528 link_pbmp = SOC_BITWORD_GET(pb, 0); 529 } else { 530 PBMP_ITER(hw_mii_pbm, port) { 531 phy_port = port; 532 SHR_BITSET(pb, phy_port); 533 } 534 } 535 #if defined (BCM_CMICM_SUPPORT) 536 if (soc_feature(unit, soc_feature_cmicm)) { 537 WRITE_CMIC_MIIM_SCAN_PORTS_0r(unit, link_pbmp); 538 if (SOC_REG_IS_VALID(unit, CMIC_MIIM_SCAN_PORTS_1r)) { 539 WRITE_CMIC_MIIM_SCAN_PORTS_1r(unit, 540 SOC_BITWORD_GET(pb, 1)); 541 } 542 if (SOC_REG_IS_VALID(unit, CMIC_MIIM_SCAN_PORTS_2r)) { 543 WRITE_CMIC_MIIM_SCAN_PORTS_2r(unit, 544 SOC_BITWORD_GET(pb, 2)); 545 } 546 if (SOC_REG_IS_VALID(unit, CMIC_MIIM_SCAN_PORTS_3r)) { 547 WRITE_CMIC_MIIM_SCAN_PORTS_3r(unit, 548 SOC_BITWORD_GET(pb, 3)); 549 } 550 #if defined (BCM_CMICDV2_SUPPORT) 551 if (SOC_REG_IS_VALID(unit, CMIC_MIIM_SCAN_PORTS_4r)) { 552 WRITE_CMIC_MIIM_SCAN_PORTS_4r(unit, 553 SOC_BITWORD_GET(pb, 4)); 554 } 555 if (SOC_REG_IS_VALID(unit, CMIC_MIIM_SCAN_PORTS_5r)) { 556 WRITE_CMIC_MIIM_SCAN_PORTS_5r(unit, 557 SOC_BITWORD_GET(pb, 5)); 558 } 559 #if defined (BCM_CMICDV4_SUPPORT) 560 if (SOC_REG_IS_VALID(unit, CMIC_MIIM_SCAN_PORTS_6r)) { 561 WRITE_CMIC_MIIM_SCAN_PORTS_6r(unit, 562 SOC_BITWORD_GET(pb, 6)); 563 } 564 if (SOC_REG_IS_VALID(unit, CMIC_MIIM_SCAN_PORTS_7r)) { 565 WRITE_CMIC_MIIM_SCAN_PORTS_7r(unit, 566 SOC_BITWORD_GET(pb, 7)); 567 } 568 if (SOC_REG_IS_VALID(unit, CMIC_MIIM_SCAN_PORTS_8r)) { 569 WRITE_CMIC_MIIM_SCAN_PORTS_8r(unit, 570 SOC_BITWORD_GET(pb, 8)); 571 } 572 if (SOC_REG_IS_VALID(unit, CMIC_MIIM_SCAN_PORTS_9r)) { 573 WRITE_CMIC_MIIM_SCAN_PORTS_9r(unit, 574 SOC_BITWORD_GET(pb, 9)); 575 } 576 #endif /* BCM_CMICDV4_SUPPORT */ 577 #endif /* BCM_CMICDV2_SUPPORT */ 578 } else 579 #endif /* BCM_CMICM_SUPPORT */ 580 #if defined (BCM_CMICX_SUPPORT) 581 if (soc_feature(unit, soc_feature_cmicx)) { 582 #if CMICX_HW_LINKSCAN 583 soc_cmicx_linkscan_config(unit, &hw_mii_pbm); 584 #endif 585 return; 586 } else 587 #endif /* BCM_CMICX_SUPPORT */ 588 { 589 soc_pci_write(unit, CMIC_SCAN_PORTS, link_pbmp); 590 591 if (((SOC_IS_TR_VL(unit)) 592 && !SOC_IS_ENDURO(unit) && !SOC_IS_HURRICANE(unit)) || 593 soc_feature(unit, soc_feature_register_hi)) { 594 WRITE_CMIC_SCAN_PORTS_HIr 595 (unit, SOC_BITWORD_GET(pb, 1)); 596 } 597 #if defined(BCM_TRIDENT_SUPPORT) 598 if (SOC_REG_IS_VALID(unit, CMIC_SCAN_PORTS_HI_2r)) { 599 WRITE_CMIC_SCAN_PORTS_HI_2r 600 (unit, SOC_BITWORD_GET(pb, 2)); 601 } 602 #endif 603 } 604 } 605 #endif /* BCM_ESW_SUPPORT */ 606 607 /* 608 * Function: 609 * soc_linkscan_pause 610 * Purpose: 611 * Pauses link scanning, without disabling it. 612 * This call is used to pause scanning temporarily. 613 * Parameters: 614 * unit - StrataSwitch unit #. 615 * Returns: 616 * Nothing 617 * Notes: 618 * Nesting pauses is provided for. 619 * Software must ensure every pause is accompanied by a continue 620 * or linkscan will never resume. 621 */ 622 void 623 soc_linkscan_pause(int unit) 624 { 625 #if defined(BCM_ESW_SUPPORT) 626 soc_control_t *soc = SOC_CONTROL(unit); 627 int s, stall_count = 0; 628 uint32 schan_ctrl; 629 630 if (NULL == soc) { 631 LOG_ERROR(BSL_LS_SOC_COMMON, 632 (BSL_META_U(unit, 633 "soc_linkscan_pause: SOC_CONTROL not init!\n"))); 634 return; 635 } 636 637 if (SOC_IS_ESW(unit)) { 638 SOC_LINKSCAN_LOCK(unit, s); /* Manipulate flags & regs atomically */ 639 640 if (soc->soc_link_pause++ == 0 && 641 (soc->soc_flags & SOC_F_LSE)) { 642 /* Stop link scan and wait for current pass to finish */ 643 #ifdef BCM_CMICM_SUPPORT 644 if(soc_feature(unit, soc_feature_cmicm)) { 645 /* Turn off HW linkscan */ 646 READ_CMIC_MIIM_SCAN_CTRLr(unit,&schan_ctrl); 647 soc_reg_field_set(unit, CMIC_MIIM_SCAN_CTRLr, &schan_ctrl, 648 MIIM_LINK_SCAN_ENf, 0); 649 WRITE_CMIC_MIIM_SCAN_CTRLr(unit,schan_ctrl); 650 if (soc_feature(unit, soc_feature_linkscan_pause_timeout)) { 651 soc_timeout_t to; 652 /* Wait for Linkscan stopped signal */ 653 soc_timeout_init(&to, 1000000 /*1 sec*/, 100); 654 while (soc_pci_read(unit, CMIC_MIIM_SCAN_STATUS_OFFSET) & 655 CMIC_MIIM_SCAN_BUSY) { 656 if (soc_timeout_check(&to)) { 657 LOG_ERROR(BSL_LS_SOC_COMMON, 658 (BSL_META_U(unit, 659 "soc_linkscan_pause: pausing hw linkscan failed\n"))); 660 break; 661 } 662 } 663 } else { 664 /* Wait for Linkscan stopped signal */ 665 /* We're using this PCI operation to pass some time 666 * since we can't use sal_usleep safely with the 667 * interrupts suspended. Wait > 1ms 668 */ 669 /* Sometimes, value of field MIIM_SCAN_BUSYf of 670 * register CMIC_MIIM_SCAN_STATUSr always is 1, so there are unbounded loops 671 * without condition "stall_count++ < 4000". 672 */ 673 while ((soc_pci_read(unit, CMIC_MIIM_SCAN_STATUS_OFFSET) & CMIC_MIIM_SCAN_BUSY) && 674 stall_count++ < 4000) { 675 /* Nothing */ 676 } 677 } 678 } else 679 #endif 680 #ifdef BCM_CMICX_SUPPORT 681 if(soc_feature(unit, soc_feature_cmicx)) { 682 #if CMICX_HW_LINKSCAN 683 soc_cmicx_linkscan_pause(unit); 684 #endif 685 SOC_LINKSCAN_UNLOCK(unit, s); 686 return; 687 } else 688 #endif 689 { 690 /* Turn off HW linkscan */ 691 soc_pci_write(unit, CMIC_SCHAN_CTRL, SC_MIIM_LINK_SCAN_EN_CLR); 692 693 if (soc_feature(unit, soc_feature_linkscan_pause_timeout)) { 694 soc_timeout_t to; 695 /* Wait for Linkscan stopped signal */ 696 soc_timeout_init(&to, 1000000 /*1 sec*/, 100); 697 while (soc_pci_read(unit, CMIC_SCHAN_CTRL) & 698 SC_MIIM_SCAN_BUSY_TST) { 699 if (soc_timeout_check(&to)) { 700 LOG_ERROR(BSL_LS_SOC_COMMON, 701 (BSL_META_U(unit, 702 "soc_linkscan_pause: pausing hw linkscan failed\n"))); 703 break; 704 } 705 } 706 } else { 707 /* Wait for Linkscan stopped signal */ 708 /* We're using this PCI operation to pass some time 709 * since we can't use sal_usleep safely with the 710 * interrupts suspended. Wait > 1ms 711 */ 712 /* Sometimes, value of field MIIM_SCAN_BUSYf of 713 * register CMIC_MIIM_SCAN_STATUSr always is 1, so there are unbounded loops 714 * without condition "stall_count++ < 4000". 715 */ 716 while ((soc_pci_read(unit, CMIC_SCHAN_CTRL) & SC_MIIM_SCAN_BUSY_TST) && 717 stall_count++ < 6000) { 718 /* Nothing */ 719 } 720 } 721 } 722 if (stall_count >= 6000) { 723 LOG_ERROR(BSL_LS_SOC_COMMON, 724 (BSL_META_U(unit, 725 "soc_linkscan_pause: pausing hw linkscan failed\n"))); 726 } 727 COMPILER_REFERENCE(schan_ctrl); 728 #ifdef BCM_RAVEN_SUPPORT 729 if (SOC_IS_RAVEN(unit)) { 730 /* Wait last HW linkscan operation to complete. 731 * Assume each CMIC read below takes 2us */ 732 stall_count = (soc->hw_linkscan_delay_ns) / 2000; 733 } else 734 #endif 735 { 736 /* Wait > 1us for last HW linkscan operation to complete. */ 737 stall_count = 4; 738 } 739 for (; stall_count > 0; stall_count--) { 740 /* We're using this PCI operation to pass some time 741 * since we can't use sal_usleep safely with the 742 * interrupts suspended. We only record the read value 743 * to prevent any complaint about an uninspected return 744 * value. 745 */ 746 #ifdef BCM_CMICM_SUPPORT 747 if(soc_feature(unit, soc_feature_cmicm)) { 748 schan_ctrl = soc_pci_read(unit, CMIC_MIIM_SCAN_STATUS_OFFSET); 749 } else 750 #endif 751 { 752 schan_ctrl = soc_pci_read(unit, CMIC_SCHAN_CTRL); 753 } 754 } 755 } 756 757 SOC_LINKSCAN_UNLOCK(unit, s); 758 } 759 #endif /* BCM_ESW_SUPPORT */ 760 } 761 762 /* 763 * Function: 764 * soc_linkscan_continue 765 * Purpose: 766 * Continue link scanning after it has been paused. 767 * Parameters: 768 * unit - StrataSwitch unit #. 769 * Returns: 770 * Nothing 771 * Notes: 772 * This routine is designed so if soc_linkscan_config is called, 773 * it won't be confused whether or not a pause is in effect. 774 */ 775 776 void 777 soc_linkscan_continue(int unit) 778 { 779 #if defined(BCM_ESW_SUPPORT) 780 soc_control_t *soc = SOC_CONTROL(unit); 781 int s; 782 #ifdef BCM_CMICM_SUPPORT 783 int cmc = SOC_PCI_CMC(unit); 784 uint32 schan_ctrl; 785 #endif 786 787 if (NULL == soc) { 788 LOG_ERROR(BSL_LS_SOC_COMMON, 789 (BSL_META_U(unit, 790 "soc_linkscan_continue: SOC_CONTROL not init!\n"))); 791 return; 792 } 793 794 if (SOC_IS_ESW(unit)) { 795 SOC_LINKSCAN_LOCK(unit, s); /* Manipulate flags & regs atomically */ 796 797 if (soc->soc_link_pause <= 0) { 798 SOC_LINKSCAN_UNLOCK(unit, s); 799 assert(0); /* Continue not preceded by a pause */ 800 } 801 802 if (--soc->soc_link_pause == 0 && 803 (soc->soc_flags & SOC_F_LSE)) { 804 805 /* 806 * NOTE: whenever hardware linkscan is running, the PHY_REG_ADDR 807 * field of the MIIM_PARAM register must be set to 1 (PHY Link 808 * Status register address). 809 */ 810 #ifdef BCM_CMICM_SUPPORT 811 if(soc_feature(unit, soc_feature_cmicm)) { 812 if (soc_feature(unit, soc_feature_phy_cl45)) { 813 /* 814 ** Clause 22 Register 0x01 (MII_STAT) for FE/GE. 815 ** Clause 45 Register 0x01 (MII_STAT) Devad = 0x1 (PMA_PMD) 816 ** for XE. 817 */ 818 uint32 phy_miim_addr = 0; 819 soc_reg_field_set(unit, CMIC_CMC0_MIIM_ADDRESSr, &phy_miim_addr, 820 CLAUSE_45_DTYPEf, 0x01); 821 soc_reg_field_set(unit, CMIC_CMC0_MIIM_ADDRESSr, &phy_miim_addr, 822 CLAUSE_45_REGADRf, 0x01); 823 /* To set 0x1 to CLAUSE_22_REGADRf is not required. 824 * - in all CMICM device, the CLAUSE_22_REGADRf in register 825 * CMIC_CMCx_MIIM_ADDRESSr is the field overlay from bit0 to 826 * bit4 of CLAUSE_45_REGADRf. 827 */ 828 if (SOC_REG_FIELD_VALID(unit, CMIC_CMC0_MIIM_ADDRESSr, 829 CLAUSE_22_REGADRf)) { 830 soc_reg_field_set(unit, CMIC_CMC0_MIIM_ADDRESSr, 831 &phy_miim_addr, CLAUSE_22_REGADRf, 0x01); 832 } 833 soc_pci_write(unit, CMIC_CMCx_MIIM_ADDRESS_OFFSET(cmc), phy_miim_addr); 834 } else { 835 soc_pci_write(unit, CMIC_CMCx_MIIM_PARAM_OFFSET(cmc), (uint32) 0x01 << 24); 836 } 837 _soc_link_scan_ports_write(unit, soc->hw_linkscan_pbmp); 838 READ_CMIC_MIIM_SCAN_CTRLr(unit,&schan_ctrl); 839 soc_reg_field_set(unit, CMIC_MIIM_SCAN_CTRLr, &schan_ctrl, 840 MIIM_LINK_SCAN_ENf, 1); 841 WRITE_CMIC_MIIM_SCAN_CTRLr(unit,schan_ctrl); 842 } else 843 #endif 844 #if defined (BCM_CMICX_SUPPORT) 845 if (soc_feature(unit, soc_feature_cmicx)) { 846 #if CMICX_HW_LINKSCAN 847 soc_cmicx_linkscan_continue(unit); 848 #endif 849 SOC_LINKSCAN_UNLOCK(unit, s); 850 return; 851 } else 852 #endif 853 { 854 if (soc_feature(unit, soc_feature_phy_cl45)) { 855 /* 856 ** Clause 22 Register 0x01 (MII_STAT) for FE/GE. 857 ** Clause 45 Register 0x01 (MII_STAT) Devad = 0x1 (PMA_PMD) 858 ** for XE. 859 */ 860 uint32 phy_miim_addr = 0; 861 soc_reg_field_set(unit, CMIC_MIIM_ADDRESSr, &phy_miim_addr, 862 CLAUSE_45_DTYPEf, 0x01); 863 soc_reg_field_set(unit, CMIC_MIIM_ADDRESSr, &phy_miim_addr, 864 CLAUSE_45_REGADRf, 0x01); 865 if (SOC_REG_FIELD_VALID(unit, CMIC_CMC0_MIIM_ADDRESSr, 866 CLAUSE_22_REGADRf)) { 867 soc_reg_field_set(unit, CMIC_MIIM_ADDRESSr, &phy_miim_addr, 868 CLAUSE_22_REGADRf, 0x01); 869 } 870 WRITE_CMIC_MIIM_ADDRESSr(unit, phy_miim_addr); 871 } else { 872 soc_pci_write(unit, CMIC_MIIM_PARAM, (uint32) 0x01 << 24); 873 } 874 _soc_link_scan_ports_write(unit, soc->hw_linkscan_pbmp); 875 soc_pci_write(unit, CMIC_SCHAN_CTRL, SC_MIIM_LINK_SCAN_EN_SET); 876 } 877 } 878 879 SOC_LINKSCAN_UNLOCK(unit, s); 880 } 881 #endif /* BCM_ESW_SUPPORT */ 882 } 883 884 /* 885 * Function: 886 * soc_linkscan_register 887 * Purpose: 888 * Provide a callout made when CMIC link scanning detects a link change. 889 * Parameters: 890 * unit - StrataSwitch Unit #. 891 * f - Function called when link status change is detected. 892 * Returns: 893 * SOC_E_XXX 894 * Notes: 895 * Handler called in interrupt context. 896 */ 897 898 int 899 soc_linkscan_register(int unit, void (*f)(int)) 900 { 901 soc_control_t *soc = SOC_CONTROL(unit); 902 903 if (f != NULL && soc->soc_link_callout != NULL) { 904 return SOC_E_EXISTS; 905 } 906 907 soc->soc_link_callout = f; 908 909 return SOC_E_NONE; 910 } 911 912 /* 913 * Function: 914 * soc_linkscan_config 915 * Purpose: 916 * Set ports to scan in CMIC. 917 * Parameters: 918 * unit - StrataSwich Unit # 919 * mii_pbm - Port bit map of ports to scan with MIIM registers 920 * direct_pbm - Port bit map of ports to scan using NON MII. 921 * Returns: 922 * SOC_E_XXX 923 */ 924 925 int 926 soc_linkscan_config(int unit, pbmp_t hw_mii_pbm, pbmp_t hw_direct_pbm) 927 { 928 #if defined(BCM_ESW_SUPPORT) 929 soc_control_t *soc = SOC_CONTROL(unit); 930 #ifdef BCM_HERCULES_SUPPORT 931 uint32 cmic_config; 932 #endif 933 int s, has_mge, has_dge; 934 pbmp_t pbm; 935 936 if (SOC_IS_ESW(unit)) { 937 938 SOC_PBMP_ASSIGN(pbm, hw_mii_pbm); 939 SOC_PBMP_AND(pbm, hw_direct_pbm); 940 assert(SOC_PBMP_IS_NULL(pbm)); /* !(hw_mii_pbm & hw_direct_pbm) */ 941 942 /* 943 * Hardware (direct) scanning is NOT supported on 10/100 ports. 944 */ 945 SOC_PBMP_ASSIGN(pbm, hw_direct_pbm); 946 SOC_PBMP_AND(pbm, PBMP_FE_ALL(unit)); 947 if (SOC_PBMP_NOT_NULL(pbm)) { 948 return SOC_E_UNAVAIL; 949 } 950 951 /* 952 * The LINK_SCAN_GIG control affects ALL ports. Thus, all ports 953 * being scanned by H/W must be either MIIM scanned or scanned 954 * using the direct connection. 955 */ 956 SOC_PBMP_ASSIGN(pbm, PBMP_GE_ALL(unit)); 957 SOC_PBMP_AND(pbm, hw_mii_pbm); 958 has_mge = SOC_PBMP_NOT_NULL(pbm); 959 SOC_PBMP_ASSIGN(pbm, PBMP_GE_ALL(unit)); 960 SOC_PBMP_AND(pbm, hw_direct_pbm); 961 has_dge = SOC_PBMP_NOT_NULL(pbm); 962 if (has_mge && has_dge) { 963 return SOC_E_UNAVAIL; 964 } 965 966 /* 967 * soc_linkscan_pause/continue combination will result in the 968 * registers being setup and started properly if we are enabling for 969 * the first time. 970 */ 971 972 SOC_LINKSCAN_LOCK(unit, s); 973 974 soc_linkscan_pause(unit); 975 976 /* Check if disabling port scanning */ 977 978 SOC_PBMP_ASSIGN(pbm, hw_mii_pbm); 979 SOC_PBMP_OR(pbm, hw_direct_pbm); 980 if (SOC_PBMP_NOT_NULL(pbm)) { 981 /* 982 * NOTE: we are no longer using CC_LINK_STAT_EN since it is 983 * unavailable on 5695 and 5665. EPC_LINK will be updated by 984 * software anyway, it will just take a few extra milliseconds. 985 */ 986 soc->soc_flags |= SOC_F_LSE; 987 } else { 988 soc->soc_flags &= ~SOC_F_LSE; 989 } 990 991 992 #ifdef BCM_CMICX_SUPPORT 993 if(soc_feature(unit, soc_feature_cmicx)) { 994 #if CMICX_HW_LINKSCAN 995 soc_cmicx_linkscan_config(unit, &hw_mii_pbm); 996 #endif 997 soc_linkscan_continue(unit); 998 SOC_LINKSCAN_UNLOCK(unit, s); 999 return SOC_E_NONE; 1000 } 1001 #endif /* BCM_CMICX_SUPPORT */ 1002 1003 #ifdef BCM_HERCULES_SUPPORT 1004 if (soc_reg_field_valid(unit, CMIC_CONFIGr, LINK_STAT_ENf)) { 1005 1006 cmic_config = soc_pci_read(unit, CMIC_CONFIG); 1007 soc_reg_field_set(unit, CMIC_CONFIGr, &cmic_config, LINK_STAT_ENf, 1008 SOC_PBMP_NOT_NULL(pbm) ? 1 : 0); 1009 soc_pci_write(unit, CMIC_CONFIG, cmic_config); 1010 } 1011 #endif 1012 /* The write of the HW linkscan ports is moved to the linkscan 1013 * continue below. Note that though the continue function 1014 * will not write to the CMIC scan ports register if linkscan 1015 * was disabled above, that is only the case when the port bitmap 1016 * is empty. Since linkscan pause clears the bitmap, this is the 1017 * desired result. 1018 */ 1019 SOC_PBMP_ASSIGN(soc->hw_linkscan_pbmp, hw_mii_pbm); 1020 1021 soc_linkscan_continue(unit); 1022 1023 SOC_LINKSCAN_UNLOCK(unit, s); 1024 } 1025 #endif /* BCM_ESW_SUPPORT */ 1026 return SOC_E_NONE; 1027 } 1028 1029 #if defined(BCM_XGS3_SWITCH_SUPPORT) 1030 1031 STATIC int 1032 _soc_linkscan_port_to_phyaddr(int unit, int port) 1033 { 1034 #ifdef PORTMOD_SUPPORT 1035 int nof_cores = 0; 1036 phymod_core_access_t core_acc; 1037 if (soc_feature(unit, soc_feature_portmod)) { 1038 portmod_port_main_core_access_get(unit, port, 1, &core_acc, &nof_cores); 1039 if (nof_cores == 0) { 1040 if ((SOC_PORTCTRL_FUNCTIONS(unit)) && 1041 (SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_port_phyaddr_get)) { 1042 return SOC_PORTCTRL_FUNCTIONS(unit)->soc_portctrl_pm_port_phyaddr_get 1043 (unit, port); 1044 } else { 1045 return -1; 1046 } 1047 } else { 1048 return portmod_port_to_phyaddr(unit, port); 1049 } 1050 } 1051 #endif 1052 1053 return PHY_ADDR(unit, port); 1054 } 1055 1056 extern int 1057 _soc_linkscan_phy_flags_test(int unit, int port, int flags) 1058 { 1059 #ifdef PORTMOD_SUPPORT 1060 if (soc_feature(unit, soc_feature_portmod)) { 1061 /* For disabled ports - return -1, fix it after flexport arch is in place */ 1062 if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all),port)) return (0); 1063 return portmod_port_flags_test(unit, port, flags) == 1 ? 1 : 0; 1064 } 1065 #endif 1066 1067 return PHY_FLAGS_TST(unit, port, flags); 1068 } 1069 1070 1071 STATIC int 1072 _soc_linkscan_fault_status_set(int unit, soc_port_t port) 1073 { 1074 soc_port_t phy_port; 1075 int blk; 1076 int blktype; 1077 uint32 rval; 1078 int i; 1079 1080 if (soc_feature(unit, soc_feature_logical_port_num)) { 1081 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 1082 } else { 1083 phy_port = port; 1084 } 1085 1086 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 1087 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 1088 blktype = SOC_BLOCK_INFO(unit, blk).type; 1089 if ((blktype == SOC_BLK_XLPORT) && 1090 SOC_REG_IS_VALID(unit, XLPORT_FAULT_LINK_STATUSr)) { 1091 1092 rval = 0; 1093 1094 soc_reg_field_set(unit, XLPORT_FAULT_LINK_STATUSr, &rval, 1095 REMOTE_FAULTf, 1); 1096 soc_reg_field_set(unit, XLPORT_FAULT_LINK_STATUSr, &rval, 1097 LOCAL_FAULTf, 1); 1098 SOC_IF_ERROR_RETURN(WRITE_XLPORT_FAULT_LINK_STATUSr(unit, 1099 port, rval)); 1100 } 1101 1102 if ((blktype == SOC_BLK_CLPORT) && 1103 SOC_REG_IS_VALID(unit, CLPORT_FAULT_LINK_STATUSr)) { 1104 1105 rval = 0; 1106 1107 soc_reg_field_set(unit, CLPORT_FAULT_LINK_STATUSr, &rval, 1108 REMOTE_FAULTf, 1); 1109 soc_reg_field_set(unit, CLPORT_FAULT_LINK_STATUSr, &rval, 1110 LOCAL_FAULTf, 1); 1111 SOC_IF_ERROR_RETURN(WRITE_CLPORT_FAULT_LINK_STATUSr(unit, 1112 port, rval)); 1113 } 1114 1115 /* Triumph3 and variants have reg name as PORT_FAULT_LINK_STATUS */ 1116 if ( ((blktype == SOC_BLK_CLPORT) || (blktype == SOC_BLK_XLPORT) || 1117 (blktype == SOC_BLK_XTPORT)) && 1118 (SOC_REG_PORT_VALID(unit, PORT_FAULT_LINK_STATUSr, port)) ) { 1119 1120 rval = 0; 1121 1122 soc_reg_field_set(unit, PORT_FAULT_LINK_STATUSr, &rval, 1123 REMOTE_FAULTf, 1); 1124 soc_reg_field_set(unit, PORT_FAULT_LINK_STATUSr, &rval, 1125 LOCAL_FAULTf, 1); 1126 SOC_IF_ERROR_RETURN(WRITE_PORT_FAULT_LINK_STATUSr(unit, 1127 port, rval)); 1128 } 1129 } 1130 1131 return SOC_E_NONE; 1132 } 1133 1134 int 1135 _soc_linkscan_hw_port_init(int unit, soc_port_t port) 1136 { 1137 STATIC const soc_reg_t protocol_map_reg[] = { 1138 CMIC_MIIM_PROTOCOL_MAPr, 1139 CMIC_MIIM_PROTOCOL_MAP_HIr, 1140 CMIC_MIIM_PROTOCOL_MAP_HI_2r 1141 }; 1142 #if defined (BCM_CMICM_SUPPORT) 1143 STATIC const soc_reg_t protocol_map_reg_cmicm[] = { 1144 CMIC_MIIM_PROTOCOL_MAP_0r, 1145 CMIC_MIIM_PROTOCOL_MAP_1r, 1146 CMIC_MIIM_PROTOCOL_MAP_2r, 1147 CMIC_MIIM_PROTOCOL_MAP_3r, 1148 #if defined (BCM_CMICDV2_SUPPORT) 1149 CMIC_MIIM_PROTOCOL_MAP_4r, 1150 CMIC_MIIM_PROTOCOL_MAP_5r, 1151 #endif 1152 #if defined (BCM_CMICDV3_SUPPORT) 1153 CMIC_MIIM_PROTOCOL_MAP_6r, 1154 CMIC_MIIM_PROTOCOL_MAP_7r, 1155 CMIC_MIIM_PROTOCOL_MAP_8r, 1156 CMIC_MIIM_PROTOCOL_MAP_9r, 1157 #endif 1158 }; 1159 #endif /* End of BCM_CMICM_SUPPORT */ 1160 1161 STATIC const soc_reg_t *protocol_map = protocol_map_reg; 1162 STATIC const soc_reg_t int_sel_map_reg[] = { 1163 CMIC_MIIM_INT_SEL_MAPr, 1164 CMIC_MIIM_INT_SEL_MAP_HIr, 1165 CMIC_MIIM_INT_SEL_MAP_HI_2r 1166 }; 1167 #if defined (BCM_CMICM_SUPPORT) 1168 STATIC const soc_reg_t int_sel_map_reg_cmicm[] = { 1169 CMIC_MIIM_INT_SEL_MAP_0r, 1170 CMIC_MIIM_INT_SEL_MAP_1r, 1171 CMIC_MIIM_INT_SEL_MAP_2r, 1172 CMIC_MIIM_INT_SEL_MAP_3r, 1173 #if defined (BCM_CMICDV2_SUPPORT) 1174 CMIC_MIIM_INT_SEL_MAP_4r, 1175 CMIC_MIIM_INT_SEL_MAP_5r, 1176 #endif 1177 #if defined (BCM_CMICDV3_SUPPORT) 1178 CMIC_MIIM_INT_SEL_MAP_6r, 1179 CMIC_MIIM_INT_SEL_MAP_7r, 1180 CMIC_MIIM_INT_SEL_MAP_8r, 1181 CMIC_MIIM_INT_SEL_MAP_9r, 1182 #endif 1183 }; 1184 #endif /* Enf of BCM_CMICM_SUPPORT */ 1185 1186 STATIC const soc_reg_t *int_sel_map = int_sel_map_reg; 1187 STATIC const soc_reg_t port_type_map_reg[] = { 1188 CMIC_MIIM_PORT_TYPE_MAPr, 1189 CMIC_MIIM_PORT_TYPE_MAP_HIr 1190 }; 1191 STATIC const soc_reg_t port_type_map_bus2_reg[] = { 1192 CMIC_MIIM_PORT_TYPE_MAP_BUS2r, 1193 CMIC_MIIM_PORT_TYPE_MAP_BUS2_HIr 1194 }; 1195 STATIC const soc_reg_t bus_map_reg[] = { 1196 CMIC_MIIM_BUS_MAP_9_0r, CMIC_MIIM_BUS_MAP_19_10r, 1197 CMIC_MIIM_BUS_MAP_29_20r, CMIC_MIIM_BUS_MAP_39_30r, 1198 CMIC_MIIM_BUS_MAP_49_40r, CMIC_MIIM_BUS_MAP_59_50r, 1199 CMIC_MIIM_BUS_MAP_69_60r, CMIC_MIIM_BUS_MAP_79_70r 1200 }; 1201 1202 #if defined (BCM_CMICDV2_SUPPORT) 1203 STATIC const soc_reg_t bus_map_reg_cmicdv2[] = { 1204 CMIC_MIIM_BUS_SEL_MAP_9_0r, CMIC_MIIM_BUS_SEL_MAP_19_10r, 1205 CMIC_MIIM_BUS_SEL_MAP_29_20r, CMIC_MIIM_BUS_SEL_MAP_39_30r, 1206 CMIC_MIIM_BUS_SEL_MAP_49_40r, CMIC_MIIM_BUS_SEL_MAP_59_50r, 1207 CMIC_MIIM_BUS_SEL_MAP_69_60r, CMIC_MIIM_BUS_SEL_MAP_79_70r, 1208 CMIC_MIIM_BUS_SEL_MAP_89_80r, CMIC_MIIM_BUS_SEL_MAP_99_90r, 1209 CMIC_MIIM_BUS_SEL_MAP_109_100r, CMIC_MIIM_BUS_SEL_MAP_119_110r, 1210 CMIC_MIIM_BUS_SEL_MAP_129_120r, CMIC_MIIM_BUS_SEL_MAP_139_130r, 1211 CMIC_MIIM_BUS_SEL_MAP_149_140r, CMIC_MIIM_BUS_SEL_MAP_159_150r, 1212 CMIC_MIIM_BUS_SEL_MAP_169_160r, CMIC_MIIM_BUS_SEL_MAP_179_170r, 1213 CMIC_MIIM_BUS_SEL_MAP_189_180r, CMIC_MIIM_BUS_SEL_MAP_191_190r 1214 }; 1215 #endif 1216 #if defined (BCM_CMICDV3_SUPPORT) 1217 STATIC const soc_reg_t bus_map_reg_cmicdv3[] = { 1218 CMIC_MIIM_BUS_SEL_MAP_7_0r, CMIC_MIIM_BUS_SEL_MAP_15_8r, 1219 CMIC_MIIM_BUS_SEL_MAP_23_16r, CMIC_MIIM_BUS_SEL_MAP_31_24r, 1220 CMIC_MIIM_BUS_SEL_MAP_39_32r, CMIC_MIIM_BUS_SEL_MAP_47_40r, 1221 CMIC_MIIM_BUS_SEL_MAP_55_48r, CMIC_MIIM_BUS_SEL_MAP_63_56r, 1222 CMIC_MIIM_BUS_SEL_MAP_71_64r, CMIC_MIIM_BUS_SEL_MAP_79_72r, 1223 CMIC_MIIM_BUS_SEL_MAP_87_80r, CMIC_MIIM_BUS_SEL_MAP_95_88r, 1224 CMIC_MIIM_BUS_SEL_MAP_103_96r, CMIC_MIIM_BUS_SEL_MAP_111_104r, 1225 CMIC_MIIM_BUS_SEL_MAP_119_112r, CMIC_V3_MIIM_BUS_SEL_MAP_127_120r, 1226 CMIC_MIIM_BUS_SEL_MAP_135_128r, CMIC_MIIM_BUS_SEL_MAP_143_136r, 1227 CMIC_MIIM_BUS_SEL_MAP_151_144r, CMIC_MIIM_BUS_SEL_MAP_159_152r, 1228 CMIC_MIIM_BUS_SEL_MAP_167_160r, CMIC_MIIM_BUS_SEL_MAP_175_168r, 1229 CMIC_MIIM_BUS_SEL_MAP_183_176r, CMIC_MIIM_BUS_SEL_MAP_191_184r, 1230 CMIC_MIIM_BUS_SEL_MAP_199_192r, CMIC_MIIM_BUS_SEL_MAP_207_200r, 1231 CMIC_MIIM_BUS_SEL_MAP_215_208r, CMIC_MIIM_BUS_SEL_MAP_223_216r, 1232 CMIC_MIIM_BUS_SEL_MAP_231_224r, CMIC_MIIM_BUS_SEL_MAP_239_232r, 1233 CMIC_MIIM_BUS_SEL_MAP_247_240r, CMIC_MIIM_BUS_SEL_MAP_255_248r, 1234 CMIC_MIIM_BUS_SEL_MAP_263_256r, CMIC_MIIM_BUS_SEL_MAP_271_264r, 1235 CMIC_MIIM_BUS_SEL_MAP_279_272r, CMIC_MIIM_BUS_SEL_MAP_287_280r, 1236 CMIC_MIIM_BUS_SEL_MAP_295_288r, CMIC_MIIM_BUS_SEL_MAP_303_296r, 1237 CMIC_MIIM_BUS_SEL_MAP_311_304r, CMIC_MIIM_BUS_SEL_MAP_319_312r 1238 }; 1239 #endif 1240 1241 #if defined (BCM_CMICM_SUPPORT) 1242 STATIC const soc_reg_t bus_map_reg_cmicm[] = { 1243 CMIC_MIIM_BUS_SEL_MAP_9_0r, CMIC_MIIM_BUS_SEL_MAP_19_10r, 1244 CMIC_MIIM_BUS_SEL_MAP_29_20r, CMIC_MIIM_BUS_SEL_MAP_39_30r, 1245 CMIC_MIIM_BUS_SEL_MAP_49_40r, CMIC_MIIM_BUS_SEL_MAP_59_50r, 1246 CMIC_MIIM_BUS_SEL_MAP_69_60r, CMIC_MIIM_BUS_SEL_MAP_79_70r, 1247 CMIC_MIIM_BUS_SEL_MAP_89_80r, CMIC_MIIM_BUS_SEL_MAP_99_90r, 1248 CMIC_MIIM_BUS_SEL_MAP_109_100r, CMIC_MIIM_BUS_SEL_MAP_119_110r, 1249 CMIC_MIIM_BUS_SEL_MAP_127_120r 1250 }; 1251 #endif /* End of BCM_CMICM_SUPPORT */ 1252 1253 STATIC const soc_reg_t *bus_map = bus_map_reg; 1254 STATIC const soc_field_t bus_map_9_0_field[] = { 1255 PORT_0_BUS_NUMf, PORT_1_BUS_NUMf, PORT_2_BUS_NUMf, PORT_3_BUS_NUMf, 1256 PORT_4_BUS_NUMf, PORT_5_BUS_NUMf, PORT_6_BUS_NUMf, PORT_7_BUS_NUMf, 1257 PORT_8_BUS_NUMf, PORT_9_BUS_NUMf 1258 }; 1259 STATIC const soc_reg_t phy_map_reg[] = { 1260 CMIC_MIIM_EXT_PHY_ADDR_MAP_3_0r, CMIC_MIIM_EXT_PHY_ADDR_MAP_7_4r, 1261 CMIC_MIIM_EXT_PHY_ADDR_MAP_11_8r, CMIC_MIIM_EXT_PHY_ADDR_MAP_15_12r, 1262 CMIC_MIIM_EXT_PHY_ADDR_MAP_19_16r, CMIC_MIIM_EXT_PHY_ADDR_MAP_23_20r, 1263 CMIC_MIIM_EXT_PHY_ADDR_MAP_27_24r, CMIC_MIIM_EXT_PHY_ADDR_MAP_31_28r, 1264 CMIC_MIIM_EXT_PHY_ADDR_MAP_35_32r, CMIC_MIIM_EXT_PHY_ADDR_MAP_39_36r, 1265 CMIC_MIIM_EXT_PHY_ADDR_MAP_43_40r, CMIC_MIIM_EXT_PHY_ADDR_MAP_47_44r, 1266 CMIC_MIIM_EXT_PHY_ADDR_MAP_51_48r, CMIC_MIIM_EXT_PHY_ADDR_MAP_55_52r, 1267 CMIC_MIIM_EXT_PHY_ADDR_MAP_59_56r, CMIC_MIIM_EXT_PHY_ADDR_MAP_63_60r, 1268 CMIC_MIIM_EXT_PHY_ADDR_MAP_67_64r, CMIC_MIIM_EXT_PHY_ADDR_MAP_71_68r, 1269 CMIC_MIIM_EXT_PHY_ADDR_MAP_75_72r, CMIC_MIIM_EXT_PHY_ADDR_MAP_79_76r, 1270 CMIC_MIIM_EXT_PHY_ADDR_MAP_83_80r, CMIC_MIIM_EXT_PHY_ADDR_MAP_87_84r, 1271 CMIC_MIIM_EXT_PHY_ADDR_MAP_91_88r, CMIC_MIIM_EXT_PHY_ADDR_MAP_95_92r, 1272 CMIC_MIIM_EXT_PHY_ADDR_MAP_99_96r, 1273 CMIC_MIIM_EXT_PHY_ADDR_MAP_103_100r, 1274 CMIC_MIIM_EXT_PHY_ADDR_MAP_107_104r, 1275 CMIC_MIIM_EXT_PHY_ADDR_MAP_111_108r, 1276 CMIC_MIIM_EXT_PHY_ADDR_MAP_115_112r, 1277 CMIC_MIIM_EXT_PHY_ADDR_MAP_119_116r, 1278 CMIC_MIIM_EXT_PHY_ADDR_MAP_123_120r, 1279 CMIC_MIIM_EXT_PHY_ADDR_MAP_127_124r, 1280 #if defined(BCM_CMICDV2_SUPPORT) 1281 CMIC_MIIM_EXT_PHY_ADDR_MAP_131_128r, 1282 CMIC_MIIM_EXT_PHY_ADDR_MAP_135_132r, 1283 CMIC_MIIM_EXT_PHY_ADDR_MAP_139_136r, 1284 CMIC_MIIM_EXT_PHY_ADDR_MAP_143_140r, 1285 CMIC_MIIM_EXT_PHY_ADDR_MAP_147_144r, 1286 CMIC_MIIM_EXT_PHY_ADDR_MAP_151_148r, 1287 CMIC_MIIM_EXT_PHY_ADDR_MAP_155_152r, 1288 CMIC_MIIM_EXT_PHY_ADDR_MAP_159_156r, 1289 CMIC_MIIM_EXT_PHY_ADDR_MAP_163_160r, 1290 CMIC_MIIM_EXT_PHY_ADDR_MAP_167_164r, 1291 CMIC_MIIM_EXT_PHY_ADDR_MAP_171_168r, 1292 CMIC_MIIM_EXT_PHY_ADDR_MAP_175_172r, 1293 CMIC_MIIM_EXT_PHY_ADDR_MAP_179_176r, 1294 CMIC_MIIM_EXT_PHY_ADDR_MAP_183_180r, 1295 CMIC_MIIM_EXT_PHY_ADDR_MAP_187_184r, 1296 CMIC_MIIM_EXT_PHY_ADDR_MAP_191_188r, 1297 #endif 1298 #if defined(BCM_CMICDV3_SUPPORT) 1299 CMIC_MIIM_EXT_PHY_ADDR_MAP_195_192r, 1300 CMIC_MIIM_EXT_PHY_ADDR_MAP_199_196r, 1301 CMIC_MIIM_EXT_PHY_ADDR_MAP_203_200r, 1302 CMIC_MIIM_EXT_PHY_ADDR_MAP_207_204r, 1303 CMIC_MIIM_EXT_PHY_ADDR_MAP_211_208r, 1304 CMIC_MIIM_EXT_PHY_ADDR_MAP_215_212r, 1305 CMIC_MIIM_EXT_PHY_ADDR_MAP_219_216r, 1306 CMIC_MIIM_EXT_PHY_ADDR_MAP_223_220r, 1307 CMIC_MIIM_EXT_PHY_ADDR_MAP_227_224r, 1308 CMIC_MIIM_EXT_PHY_ADDR_MAP_231_228r, 1309 CMIC_MIIM_EXT_PHY_ADDR_MAP_235_232r, 1310 CMIC_MIIM_EXT_PHY_ADDR_MAP_239_236r, 1311 CMIC_MIIM_EXT_PHY_ADDR_MAP_243_240r, 1312 CMIC_MIIM_EXT_PHY_ADDR_MAP_247_244r, 1313 CMIC_MIIM_EXT_PHY_ADDR_MAP_251_248r, 1314 CMIC_MIIM_EXT_PHY_ADDR_MAP_255_252r, 1315 CMIC_MIIM_EXT_PHY_ADDR_MAP_259_256r, 1316 CMIC_MIIM_EXT_PHY_ADDR_MAP_263_260r, 1317 CMIC_MIIM_EXT_PHY_ADDR_MAP_267_264r, 1318 CMIC_MIIM_EXT_PHY_ADDR_MAP_271_268r, 1319 CMIC_MIIM_EXT_PHY_ADDR_MAP_275_272r, 1320 CMIC_MIIM_EXT_PHY_ADDR_MAP_279_276r, 1321 CMIC_MIIM_EXT_PHY_ADDR_MAP_283_280r, 1322 CMIC_MIIM_EXT_PHY_ADDR_MAP_287_284r, 1323 CMIC_MIIM_EXT_PHY_ADDR_MAP_291_288r, 1324 CMIC_MIIM_EXT_PHY_ADDR_MAP_295_292r, 1325 CMIC_MIIM_EXT_PHY_ADDR_MAP_299_296r, 1326 CMIC_MIIM_EXT_PHY_ADDR_MAP_303_300r, 1327 CMIC_MIIM_EXT_PHY_ADDR_MAP_307_304r, 1328 CMIC_MIIM_EXT_PHY_ADDR_MAP_311_308r, 1329 CMIC_MIIM_EXT_PHY_ADDR_MAP_315_312r, 1330 CMIC_MIIM_EXT_PHY_ADDR_MAP_319_316r, 1331 #endif 1332 }; 1333 STATIC const soc_field_t phy_map_3_0_field[] = { 1334 PHY_ID_0f, PHY_ID_1f, PHY_ID_2f, PHY_ID_3f 1335 }; 1336 #ifdef BCM_RAVEN_SUPPORT 1337 soc_control_t *soc = SOC_CONTROL(unit); 1338 #endif 1339 soc_reg_t reg; 1340 soc_field_t field; 1341 int addr; 1342 uint32 rval; 1343 int bus_sel; 1344 soc_port_t phy_port, port_bit; 1345 int embedded_phy_port = 0; 1346 int phy_addr; 1347 int bus_map_array_size; 1348 1349 1350 if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TOMAHAWK3(unit)) { 1351 return SOC_E_NONE; 1352 } 1353 1354 if (soc_feature(unit, soc_feature_logical_port_num)) { 1355 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 1356 } else { 1357 phy_port = port; 1358 } 1359 1360 port_bit = phy_port; 1361 #ifdef BCM_GREYHOUND2_SUPPORT 1362 if (SOC_IS_GREYHOUND2(unit)) { 1363 port_bit = (port_bit >= 58) ? (port_bit + GREYHOUND2_PHY_PORT_OFFSET) 1364 : port_bit; 1365 } 1366 #endif /* BCM_GREYHOUND2_SUPPORT */ 1367 PHY_PORT_TO_LINKSCAN_PORT_XLATE(unit, port_bit); 1368 1369 #ifdef BCM_SCORPION_SUPPORT 1370 if (SOC_IS_SC_CQ(unit) || SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit) || 1371 SOC_IS_KATANAX(unit)) { 1372 /* 1373 * SC/CQ devices omit the CMIC port from the PHY counting. All 1374 * "port bitmaps" are shifted by 1. 1375 */ 1376 if (port == CMIC_PORT(unit)) { 1377 /* This should not be triggered */ 1378 return SOC_E_PORT; 1379 } 1380 if (!SOC_IS_KATANAX(unit)) { 1381 port_bit -= 1; 1382 } 1383 } 1384 #endif 1385 1386 bus_map_array_size = COUNTOF(bus_map_reg); 1387 #if defined (BCM_CMICM_SUPPORT) 1388 if (soc_feature(unit, soc_feature_cmicm)) { 1389 protocol_map = protocol_map_reg_cmicm; 1390 int_sel_map = int_sel_map_reg_cmicm; 1391 bus_map = bus_map_reg_cmicm; 1392 bus_map_array_size = COUNTOF(bus_map_reg_cmicm); 1393 #if defined (BCM_CMICDV2_SUPPORT) 1394 if (soc_feature(unit, soc_feature_cmicd_v2)) { 1395 bus_map = bus_map_reg_cmicdv2; 1396 bus_map_array_size = COUNTOF(bus_map_reg_cmicdv2); 1397 } 1398 #endif /* BCM_CMICDV2_SUPPORT */ 1399 #if defined (BCM_CMICDV3_SUPPORT) 1400 if (soc_feature(unit, soc_feature_cmicd_v3)) { 1401 bus_map = bus_map_reg_cmicdv3; 1402 bus_map_array_size = COUNTOF(bus_map_reg_cmicdv3); 1403 } 1404 #endif /* BCM_CMICDV3_SUPPORT */ 1405 } 1406 #endif 1407 1408 /* 1409 * Check If Hardware Linkscan should use Clause 45 mode 1410 */ 1411 if ((IS_XE_PORT(unit, port) || IS_CE_PORT(unit, port) || 1412 IS_HG_PORT(unit, port) || IS_GE_PORT(unit, port)) && 1413 _soc_linkscan_phy_flags_test(unit, port, PHY_FLAGS_C45)) { 1414 reg = protocol_map[port_bit / 32]; 1415 if (SOC_REG_IS_VALID(unit, reg)) { 1416 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 1417 rval = soc_pci_read(unit, addr); 1418 rval |= 1 << (port_bit % 32); 1419 soc_pci_write(unit, addr, rval); 1420 } 1421 } 1422 1423 /* 1424 * Select the appropriate MDIO bus 1425 */ 1426 phy_addr = _soc_linkscan_port_to_phyaddr(unit, port); 1427 1428 if (SOC_IS_TD_TT(unit) || SOC_IS_METROLITE(unit)) { 1429 bus_sel = ((phy_addr & 0x300) >> 6) | 1430 ((phy_addr & 0x60) >> 5) ; 1431 } else if (SOC_IS_TRX(unit)) { 1432 bus_sel = (phy_addr & 0x60) >> 5; /* bus 0, 1, and 2 */ 1433 } else { 1434 bus_sel = (phy_addr & 0x40) >> 6; /* bus 0 and 1 */ 1435 } 1436 1437 #if defined (BCM_CMICDV3_SUPPORT) 1438 if (soc_feature(unit, soc_feature_cmicd_v3)) { 1439 if ((port_bit / 8) < bus_map_array_size) { 1440 reg = bus_map[port_bit / 8]; 1441 } else { 1442 return SOC_E_INTERNAL; 1443 } 1444 field = bus_map_9_0_field[port_bit % 8]; 1445 1446 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 1447 rval = soc_pci_read(unit, addr); 1448 soc_reg_field_set(unit, bus_map[0], &rval, field, bus_sel); 1449 soc_pci_write(unit, addr, rval); 1450 1451 } else 1452 #endif /* BCM_CMICDV3_SUPPORT */ 1453 if (SOC_REG_IS_VALID(unit, bus_map[0])) { 1454 if ((port_bit / 10) < bus_map_array_size) { 1455 reg = bus_map[port_bit / 10]; 1456 } else { 1457 return SOC_E_INTERNAL; 1458 } 1459 field = bus_map_9_0_field[port_bit % 10]; 1460 if (SOC_REG_IS_VALID(unit, reg)) { 1461 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 1462 rval = soc_pci_read(unit, addr); 1463 soc_reg_field_set(unit, bus_map[0], &rval, field, bus_sel); 1464 soc_pci_write(unit, addr, rval); 1465 } 1466 } else { 1467 reg = INVALIDr; 1468 if (bus_sel == 1) { 1469 if ((port_bit / 32) < COUNTOF(port_type_map_reg)) { 1470 reg = port_type_map_reg[port_bit / 32]; 1471 } else { 1472 return SOC_E_INTERNAL; 1473 } 1474 } else if ((bus_sel == 2) && !SOC_IS_SHADOW(unit)) { 1475 if ((port_bit / 32) < COUNTOF(port_type_map_bus2_reg)) { 1476 reg = port_type_map_bus2_reg[port_bit / 32]; 1477 } else { 1478 return SOC_E_INTERNAL; 1479 } 1480 } 1481 if (SOC_REG_IS_VALID(unit, reg)) { 1482 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 1483 rval = soc_pci_read(unit, addr); 1484 rval |= 1 << (port_bit % 32); 1485 soc_pci_write(unit, addr, rval); 1486 } 1487 } 1488 1489 /* 1490 * Check If Hardware Linkscan should use internal phy 1491 */ 1492 embedded_phy_port = 0; 1493 if (soc_feature(unit, soc_feature_gphy)) { 1494 if (SOC_IS_HURRICANE2(unit)) { 1495 if ((phy_port < 18)) { 1496 embedded_phy_port = 1; 1497 } 1498 } 1499 #ifdef BCM_HURRICANE3_SUPPORT 1500 else if (SOC_IS_HURRICANE3(unit)) { 1501 if (soc_feature(unit, soc_feature_wh2)) { 1502 uint8 is_gphy = 0; 1503 1504 (void)soc_wolfhound2_gphy_get(unit, port, &is_gphy); 1505 embedded_phy_port = (is_gphy) ? 1 : 0; 1506 } else { 1507 if (((phy_port >= 10) && (phy_port <= 17)) || 1508 ((phy_port >= 26) && (phy_port <= 33))) { 1509 embedded_phy_port = 1; 1510 } 1511 } 1512 } 1513 #endif /* BCM_HURRICANE3_SUPPORT */ 1514 } 1515 reg = int_sel_map[port_bit / 32]; 1516 if (SOC_REG_IS_VALID(unit, reg)) { 1517 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 1518 rval = soc_pci_read(unit, addr); 1519 if (!_soc_linkscan_phy_flags_test(unit, port, PHY_FLAGS_EXTERNAL_PHY) || 1520 _soc_linkscan_phy_flags_test(unit, port, PHY_FLAGS_REPEATER) || 1521 embedded_phy_port) { 1522 rval |= 1 << (port_bit % 32); 1523 soc_pci_write(unit, addr, rval); 1524 } else { 1525 rval &= ~(1<< (port_bit % 32)); 1526 soc_pci_write(unit, addr, rval); 1527 1528 #ifdef BCM_RAVEN_SUPPORT 1529 if (SOC_IS_RAVEN(unit)) { 1530 /* Assume: 1531 * - CMIC related processing time is negligible 1532 * - MIIM interface is running at 2.5MHz 1533 * - Each register read is 65 bits (32 preamble, 32 payload, 1 idle) 1534 */ 1535 (soc->hw_linkscan_delay_ns) += 400 * 65; 1536 } 1537 #endif 1538 } 1539 } 1540 1541 /* Re-initialize the phy port map for the unit */ 1542 /* Use MDIO address re-mapping for hardware linkscan */ 1543 assert(port_bit >= 0); 1544 assert(port_bit / 4 < sizeof(phy_map_reg) / sizeof(phy_map_reg[0])); 1545 1546 /* 1547 * COVERITY 1548 * 1549 * assert validates the input 1550 */ 1551 /* coverity[overrun-local : FALSE] */ 1552 reg = phy_map_reg[port_bit / 4]; 1553 field = phy_map_3_0_field[port_bit % 4]; 1554 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 1555 rval = soc_pci_read(unit, addr); 1556 soc_reg_field_set(unit, phy_map_reg[0], &rval, field, 1557 PHY_ADDR(unit, port) & 0x1f); 1558 soc_pci_write(unit, addr, rval); 1559 1560 1561 #if defined (BCM_CMICM_SUPPORT) 1562 if (soc_feature(unit, soc_feature_cmicm)) { 1563 READ_CMIC_MIIM_SCAN_CTRLr(unit, &rval); 1564 soc_reg_field_set(unit, CMIC_MIIM_SCAN_CTRLr, &rval, 1565 MIIM_ADDR_MAP_ENABLEf, 1); 1566 WRITE_CMIC_MIIM_SCAN_CTRLr(unit, rval); 1567 } else 1568 #endif 1569 { 1570 READ_CMIC_CONFIGr(unit, &rval); 1571 soc_reg_field_set(unit, CMIC_CONFIGr, &rval, MIIM_ADDR_MAP_ENABLEf, 1); 1572 WRITE_CMIC_CONFIGr(unit, rval); 1573 } 1574 1575 /* 1576 * Configure remote/local faults to trigger link interrupt. 1577 * The configuration is included in Portmod internally. 1578 */ 1579 if (!soc_feature(unit, soc_feature_portmod)) { 1580 _soc_linkscan_fault_status_set(unit, port); 1581 } 1582 1583 return SOC_E_NONE; 1584 } 1585 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1586 1587 1588 #if defined (BCM_ESW_SUPPORT) 1589 STATIC int 1590 _soc_linkscan_hw_link_get(int unit, soc_pbmp_t *hw_link) 1591 { 1592 uint32 link_stat = 0; 1593 #ifdef BCM_GREYHOUND2_SUPPORT 1594 uint32 scan_stat = 0; 1595 #endif /* BCM_GREYHOUND2_SUPPORT */ 1596 uint32 link_pbmp = 0; 1597 SHR_BITDCL pb[_SHR_BITDCLSIZE(SOC_CMIC_PHY_PORT_MAX)] = {0}; 1598 #ifdef BCM_GREYHOUND2_SUPPORT 1599 SHR_BITDCL ps[_SHR_BITDCLSIZE(SOC_CMIC_PHY_PORT_MAX)] = {0}; 1600 #endif /* BCM_GREYHOUND2_SUPPORT */ 1601 soc_port_t port_bit, phy_port, port; 1602 int num_phy_port = 0; 1603 1604 if (NULL == hw_link) { 1605 return SOC_E_PARAM; 1606 } 1607 1608 #if defined (BCM_CMICX_SUPPORT) 1609 if (soc_feature(unit, soc_feature_cmicx)) { 1610 #if CMICX_HW_LINKSCAN 1611 SOC_PBMP_CLEAR(*hw_link); 1612 return soc_cmicx_linkscan_hw_link_get(unit, hw_link); 1613 #endif 1614 return SOC_E_NONE; 1615 } 1616 #endif 1617 1618 sal_memset(pb, 0, sizeof(SHR_BITDCL) * _SHR_BITDCLSIZE(SOC_CMIC_PHY_PORT_MAX)); 1619 #ifdef BCM_GREYHOUND2_SUPPORT 1620 sal_memset(ps, 0, sizeof(SHR_BITDCL) * _SHR_BITDCLSIZE(SOC_CMIC_PHY_PORT_MAX)); 1621 1622 if (SOC_IS_GREYHOUND2(unit)) { 1623 READ_CMIC_MIIM_SCAN_PORTS_0r(unit, &scan_stat); 1624 SOC_BITWORD_SET(ps, 0, scan_stat); 1625 READ_CMIC_MIIM_SCAN_PORTS_1r(unit, &scan_stat); 1626 SOC_BITWORD_SET(ps, 1, scan_stat); 1627 READ_CMIC_MIIM_SCAN_PORTS_2r(unit, &scan_stat); 1628 SOC_BITWORD_SET(ps, 2, scan_stat); 1629 } 1630 #endif /* BCM_GREYHOUND2_SUPPORT */ 1631 1632 /* 1633 * Read CMIC link status to determine which ports that 1634 * actually need to be scanned. 1635 */ 1636 #if defined (BCM_CMICM_SUPPORT) 1637 if (soc_feature(unit, soc_feature_cmicm)) { 1638 READ_CMIC_MIIM_LINK_STATUS_0r(unit, &link_stat); 1639 } else 1640 #endif 1641 { 1642 READ_CMIC_LINK_STATr(unit, &link_stat); 1643 } 1644 #if defined(BCM_FIREBOLT_SUPPORT) 1645 if (soc_feature(unit, soc_feature_status_link_fail)) { 1646 uint32 intsel_reg; 1647 1648 READ_CMIC_MIIM_INT_SEL_MAPr(unit, &intsel_reg); 1649 link_stat ^= intsel_reg; 1650 } 1651 #endif /* BCM_FIREBOLT_SUPPORT */ 1652 1653 #if defined (BCM_CMICM_SUPPORT) 1654 if (soc_feature(unit, soc_feature_cmicm)) { 1655 link_pbmp = soc_reg_field_get(unit, CMIC_MIIM_LINK_STATUS_0r, 1656 link_stat, PORT_BITMAPf); 1657 } else 1658 #endif 1659 { 1660 link_pbmp = soc_reg_field_get(unit, CMIC_LINK_STATr, 1661 link_stat, PORT_BITMAPf); 1662 } 1663 #if defined (BCM_GOLDWING_SUPPORT) 1664 if (SOC_IS_GOLDWING(unit)) { 1665 /* (MSB) 15-14-19-18-17-16-13-12-11-10-9-8-7-6-5-4-3-2-1-0 (LSB) */ 1666 link_pbmp = (link_pbmp & 0x00003FFF) | 1667 ((link_pbmp & 0x000C0000) >> 4) | 1668 ((link_pbmp & 0x0003C000) << 2); 1669 } 1670 #endif /* BCM_GOLDWING_SUPPORT */ 1671 1672 #if defined (BCM_SCORPION_SUPPORT) 1673 if (SOC_IS_SC_CQ(unit)) { 1674 /* CMIC port not included in link status */ 1675 link_pbmp <<= 1; 1676 } 1677 #endif /* BCM_SCORPION_SUPPORT */ 1678 1679 SOC_BITWORD_SET(pb, 0, link_pbmp); 1680 1681 #if defined (BCM_RAPTOR_SUPPORT) || defined (BCM_TRIUMPH_SUPPORT) || defined (BCM_KATANA_SUPPORT) 1682 /* Check for more than 32 ports per unit */ 1683 #if defined (BCM_CMICM_SUPPORT) 1684 if (soc_feature(unit, soc_feature_cmicm) && 1685 SOC_REG_IS_VALID(unit, CMIC_MIIM_LINK_STATUS_1r) ) { 1686 READ_CMIC_MIIM_LINK_STATUS_1r(unit, &link_stat); 1687 SOC_BITWORD_SET(pb, 1, 1688 soc_reg_field_get(unit, CMIC_MIIM_LINK_STATUS_1r, 1689 link_stat, PORT_BITMAPf)); 1690 } else 1691 #endif 1692 if ((SOC_IS_TR_VL(unit) && !SOC_IS_ENDURO(unit) && !SOC_IS_HURRICANE(unit)) || 1693 soc_feature(unit, soc_feature_register_hi)) { 1694 READ_CMIC_LINK_STAT_HIr(unit, &link_stat); 1695 SOC_BITWORD_SET(pb, 1, 1696 soc_reg_field_get(unit, CMIC_LINK_STAT_HIr, 1697 link_stat, PORT_BITMAPf)); 1698 } 1699 #endif 1700 #if defined (BCM_TRIDENT_SUPPORT) 1701 #if defined (BCM_CMICM_SUPPORT) 1702 if (soc_feature(unit, soc_feature_cmicm) && 1703 SOC_REG_IS_VALID(unit, CMIC_MIIM_LINK_STATUS_2r) ) { 1704 READ_CMIC_MIIM_LINK_STATUS_2r(unit, &link_stat); 1705 link_pbmp = soc_reg_field_get(unit, CMIC_MIIM_LINK_STATUS_2r, 1706 link_stat, PORT_BITMAPf); 1707 SOC_BITWORD_SET(pb, 2, link_pbmp); 1708 } else 1709 #endif 1710 { 1711 if (SOC_REG_IS_VALID(unit, CMIC_LINK_STAT_HI_2r)) { 1712 READ_CMIC_LINK_STAT_HI_2r(unit, &link_stat); 1713 link_pbmp = soc_reg_field_get(unit, CMIC_LINK_STAT_HI_2r, 1714 link_stat, PORT_BITMAPf); 1715 SOC_BITWORD_SET(pb, 2, link_pbmp); 1716 } 1717 } 1718 #endif /* BCM_TRIDENT_SUPPORT */ 1719 1720 #if defined (BCM_CMICM_SUPPORT) 1721 if (soc_feature(unit, soc_feature_cmicm) && 1722 SOC_REG_IS_VALID(unit, CMIC_MIIM_LINK_STATUS_3r)) { 1723 READ_CMIC_MIIM_LINK_STATUS_3r(unit, &link_stat); 1724 link_pbmp = soc_reg_field_get(unit, CMIC_MIIM_LINK_STATUS_3r, 1725 link_stat, PORT_BITMAPf); 1726 SOC_BITWORD_SET(pb, 3, link_pbmp); 1727 } 1728 1729 #if defined (BCM_CMICDV2_SUPPORT) 1730 if (soc_feature(unit, soc_feature_cmicd_v2) && 1731 SOC_REG_IS_VALID(unit, CMIC_MIIM_LINK_STATUS_4r)) { 1732 READ_CMIC_MIIM_LINK_STATUS_4r(unit, &link_stat); 1733 link_pbmp = soc_reg_field_get(unit, CMIC_MIIM_LINK_STATUS_4r, 1734 link_stat, PORT_BITMAPf); 1735 SOC_BITWORD_SET(pb, 4, link_pbmp); 1736 } 1737 1738 if (soc_feature(unit, soc_feature_cmicd_v2) && 1739 SOC_REG_IS_VALID(unit, CMIC_MIIM_LINK_STATUS_5r)) { 1740 READ_CMIC_MIIM_LINK_STATUS_5r(unit, &link_stat); 1741 link_pbmp = soc_reg_field_get(unit, CMIC_MIIM_LINK_STATUS_5r, 1742 link_stat, PORT_BITMAPf); 1743 SOC_BITWORD_SET(pb, 5, link_pbmp); 1744 } 1745 1746 #if defined (BCM_CMICDV4_SUPPORT) 1747 if (soc_feature(unit, soc_feature_cmicd_v4) && 1748 SOC_REG_IS_VALID(unit, CMIC_MIIM_LINK_STATUS_6r)) { 1749 READ_CMIC_MIIM_LINK_STATUS_6r(unit, &link_stat); 1750 link_pbmp = soc_reg_field_get(unit, CMIC_MIIM_LINK_STATUS_6r, 1751 link_stat, PORT_BITMAPf); 1752 SOC_BITWORD_SET(pb, 6, link_pbmp); 1753 } 1754 1755 if (soc_feature(unit, soc_feature_cmicd_v4) && 1756 SOC_REG_IS_VALID(unit, CMIC_MIIM_LINK_STATUS_7r)) { 1757 READ_CMIC_MIIM_LINK_STATUS_7r(unit, &link_stat); 1758 link_pbmp = soc_reg_field_get(unit, CMIC_MIIM_LINK_STATUS_7r, 1759 link_stat, PORT_BITMAPf); 1760 SOC_BITWORD_SET(pb, 7, link_pbmp); 1761 } 1762 1763 if (soc_feature(unit, soc_feature_cmicd_v4) && 1764 SOC_REG_IS_VALID(unit, CMIC_MIIM_LINK_STATUS_8r)) { 1765 READ_CMIC_MIIM_LINK_STATUS_8r(unit, &link_stat); 1766 link_pbmp = soc_reg_field_get(unit, CMIC_MIIM_LINK_STATUS_8r, 1767 link_stat, PORT_BITMAPf); 1768 SOC_BITWORD_SET(pb, 8, link_pbmp); 1769 } 1770 1771 if (soc_feature(unit, soc_feature_cmicd_v4) && 1772 SOC_REG_IS_VALID(unit, CMIC_MIIM_LINK_STATUS_9r)) { 1773 READ_CMIC_MIIM_LINK_STATUS_9r(unit, &link_stat); 1774 link_pbmp = soc_reg_field_get(unit, CMIC_MIIM_LINK_STATUS_9r, 1775 link_stat, PORT_BITMAPf); 1776 SOC_BITWORD_SET(pb, 9, link_pbmp); 1777 } 1778 #endif /* BCM_CMICDV4_SUPPORT */ 1779 #endif /* BCM_CMICDV2_SUPPORT */ 1780 #endif /*BCM_CMICM_SUPPORT*/ 1781 if (soc_feature(unit, soc_feature_logical_port_num)) { 1782 1783 #ifdef BCM_TOMAHAWK_SUPPORT 1784 if (SOC_IS_TOMAHAWK(unit)) { 1785 num_phy_port = NUM_PIPE(unit) * (soc_mem_index_count (unit, 1786 ING_IDB_TO_DEVICE_PORT_NUMBER_MAPPING_TABLEm)); 1787 } else 1788 #endif /* BCM_TOMAHAWK_SUPPORT */ 1789 #ifdef BCM_TRIDENT3_SUPPORT 1790 if (SOC_IS_TRIDENT3X(unit)) { 1791 num_phy_port = NUM_PIPE(unit) * (soc_mem_index_count (unit, 1792 ING_IDB_TO_DEVICE_PORT_NUMBER_MAPPING_TABLEm)); 1793 } else 1794 #endif /* BCM_TRIDENT3_SUPPORT */ 1795 #ifdef BCM_TOMAHAWK2_SUPPORT 1796 if (SOC_IS_TOMAHAWK2(unit)) { 1797 num_phy_port = NUM_PIPE(unit) * (soc_mem_index_count (unit, 1798 ING_PHY_TO_IDB_PORT_MAPm)); 1799 } else 1800 #endif /* BCM_TOMAHAWK2_SUPPORT */ 1801 { 1802 num_phy_port = soc_mem_index_count 1803 (unit, ING_PHYSICAL_TO_LOGICAL_PORT_NUMBER_MAPPING_TABLEm); 1804 } 1805 1806 SOC_PBMP_CLEAR(*hw_link); 1807 SHR_BIT_ITER(pb, SOC_CMIC_PHY_PORT_MAX, port_bit) { 1808 if (SOC_IS_HURRICANE2(unit) || SOC_IS_HURRICANE3(unit) || 1809 SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit)) { 1810 phy_port = port_bit; 1811 #ifdef BCM_GREYHOUND2_SUPPORT 1812 /* 1813 * Use CMIC_MIIM_SCAN_PORTS bitmap to check the port link 1814 * status is valid or not due to the difference between 1815 * phy port allocation and hardware implementation. 1816 */ 1817 if (SOC_IS_GREYHOUND2(unit)) { 1818 if (SHR_BITGET(ps, phy_port)) { 1819 phy_port = (phy_port >= 65) ? 1820 (phy_port - GREYHOUND2_PHY_PORT_OFFSET) : 1821 phy_port; 1822 } else { 1823 continue; 1824 } 1825 } 1826 #endif /* BCM_GREYHOUND2_SUPPORT */ 1827 } else { 1828 phy_port = port_bit + 1; 1829 LINKSCAN_PORT_TO_PHY_PORT_XLATE(unit, phy_port); 1830 if (phy_port == -1) { 1831 continue; 1832 } 1833 } 1834 #ifdef BCM_TOMAHAWK2_SUPPORT 1835 if (SOC_IS_TOMAHAWK2(unit)) { 1836 if (phy_port > num_phy_port) { 1837 break; 1838 } 1839 } else 1840 #endif /* BCM_TOMAHAWK2_SUPPORT */ 1841 if (phy_port >= num_phy_port) { 1842 break; 1843 } 1844 /* 1845 * COVERITY 1846 * 1847 * The check above will protect any real cases so the 1848 * index does not exceed the declared size. 1849 */ 1850 /* coverity[overrun-local] */ 1851 port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 1852 if (port != -1) { 1853 SOC_PBMP_PORT_ADD(*hw_link, port); 1854 } 1855 } 1856 } else { 1857 SOC_PBMP_CLEAR(*hw_link); 1858 SHR_BIT_ITER(pb, SOC_CMIC_PHY_PORT_MAX, port_bit) { 1859 port = port_bit; 1860 /* coverity[overrun-local] */ 1861 SOC_PBMP_PORT_ADD(*hw_link, port); 1862 } 1863 } 1864 1865 return SOC_E_NONE; 1866 } 1867 #endif /* BCM_ESW_SUPPORT */ 1868 1869 /* 1870 * This function updates port phy address in CMIC external 1871 * phy address registers for hardware linkscan 1872 */ 1873 int 1874 soc_linkscan_hw_port_update(int unit, soc_port_t port) 1875 { 1876 #if defined(BCM_ESW_SUPPORT) 1877 STATIC const soc_reg_t port_type_map_reg[] = { 1878 CMIC_MIIM_PORT_TYPE_MAPr, 1879 CMIC_MIIM_PORT_TYPE_MAP_HIr 1880 }; 1881 STATIC const soc_reg_t port_type_map_bus2_reg[] = { 1882 CMIC_MIIM_PORT_TYPE_MAP_BUS2r, 1883 CMIC_MIIM_PORT_TYPE_MAP_BUS2_HIr 1884 }; 1885 STATIC const soc_reg_t bus_map_reg[] = { 1886 CMIC_MIIM_BUS_MAP_9_0r, CMIC_MIIM_BUS_MAP_19_10r, 1887 CMIC_MIIM_BUS_MAP_29_20r, CMIC_MIIM_BUS_MAP_39_30r, 1888 CMIC_MIIM_BUS_MAP_49_40r, CMIC_MIIM_BUS_MAP_59_50r, 1889 CMIC_MIIM_BUS_MAP_69_60r, CMIC_MIIM_BUS_MAP_79_70r 1890 }; 1891 1892 #if defined (BCM_CMICDV2_SUPPORT) 1893 STATIC const soc_reg_t bus_map_reg_cmicdv2[] = { 1894 CMIC_MIIM_BUS_SEL_MAP_9_0r, CMIC_MIIM_BUS_SEL_MAP_19_10r, 1895 CMIC_MIIM_BUS_SEL_MAP_29_20r, CMIC_MIIM_BUS_SEL_MAP_39_30r, 1896 CMIC_MIIM_BUS_SEL_MAP_49_40r, CMIC_MIIM_BUS_SEL_MAP_59_50r, 1897 CMIC_MIIM_BUS_SEL_MAP_69_60r, CMIC_MIIM_BUS_SEL_MAP_79_70r, 1898 CMIC_MIIM_BUS_SEL_MAP_89_80r, CMIC_MIIM_BUS_SEL_MAP_99_90r, 1899 CMIC_MIIM_BUS_SEL_MAP_109_100r, CMIC_MIIM_BUS_SEL_MAP_119_110r, 1900 CMIC_MIIM_BUS_SEL_MAP_129_120r, CMIC_MIIM_BUS_SEL_MAP_139_130r, 1901 CMIC_MIIM_BUS_SEL_MAP_149_140r, CMIC_MIIM_BUS_SEL_MAP_159_150r, 1902 CMIC_MIIM_BUS_SEL_MAP_169_160r, CMIC_MIIM_BUS_SEL_MAP_179_170r, 1903 CMIC_MIIM_BUS_SEL_MAP_189_180r, CMIC_MIIM_BUS_SEL_MAP_191_190r 1904 }; 1905 #endif 1906 #if defined (BCM_CMICDV3_SUPPORT) 1907 STATIC const soc_reg_t bus_map_reg_cmicdv3[] = { 1908 CMIC_MIIM_BUS_SEL_MAP_7_0r, CMIC_MIIM_BUS_SEL_MAP_15_8r, 1909 CMIC_MIIM_BUS_SEL_MAP_23_16r, CMIC_MIIM_BUS_SEL_MAP_31_24r, 1910 CMIC_MIIM_BUS_SEL_MAP_39_32r, CMIC_MIIM_BUS_SEL_MAP_47_40r, 1911 CMIC_MIIM_BUS_SEL_MAP_55_48r, CMIC_MIIM_BUS_SEL_MAP_63_56r, 1912 CMIC_MIIM_BUS_SEL_MAP_71_64r, CMIC_MIIM_BUS_SEL_MAP_79_72r, 1913 CMIC_MIIM_BUS_SEL_MAP_87_80r, CMIC_MIIM_BUS_SEL_MAP_95_88r, 1914 CMIC_MIIM_BUS_SEL_MAP_103_96r, CMIC_MIIM_BUS_SEL_MAP_111_104r, 1915 CMIC_MIIM_BUS_SEL_MAP_119_112r, CMIC_V3_MIIM_BUS_SEL_MAP_127_120r, 1916 CMIC_MIIM_BUS_SEL_MAP_135_128r, CMIC_MIIM_BUS_SEL_MAP_143_136r, 1917 CMIC_MIIM_BUS_SEL_MAP_151_144r, CMIC_MIIM_BUS_SEL_MAP_159_152r, 1918 CMIC_MIIM_BUS_SEL_MAP_167_160r, CMIC_MIIM_BUS_SEL_MAP_175_168r, 1919 CMIC_MIIM_BUS_SEL_MAP_183_176r, CMIC_MIIM_BUS_SEL_MAP_191_184r, 1920 CMIC_MIIM_BUS_SEL_MAP_199_192r, CMIC_MIIM_BUS_SEL_MAP_207_200r, 1921 CMIC_MIIM_BUS_SEL_MAP_215_208r, CMIC_MIIM_BUS_SEL_MAP_223_216r, 1922 CMIC_MIIM_BUS_SEL_MAP_231_224r, CMIC_MIIM_BUS_SEL_MAP_239_232r, 1923 CMIC_MIIM_BUS_SEL_MAP_247_240r, CMIC_MIIM_BUS_SEL_MAP_255_248r, 1924 CMIC_MIIM_BUS_SEL_MAP_263_256r, CMIC_MIIM_BUS_SEL_MAP_271_264r, 1925 CMIC_MIIM_BUS_SEL_MAP_279_272r, CMIC_MIIM_BUS_SEL_MAP_287_280r, 1926 CMIC_MIIM_BUS_SEL_MAP_295_288r, CMIC_MIIM_BUS_SEL_MAP_303_296r, 1927 CMIC_MIIM_BUS_SEL_MAP_311_304r, CMIC_MIIM_BUS_SEL_MAP_319_312r 1928 }; 1929 #endif 1930 1931 #if defined (BCM_CMICM_SUPPORT) 1932 STATIC const soc_reg_t bus_map_reg_cmicm[] = { 1933 CMIC_MIIM_BUS_SEL_MAP_9_0r, CMIC_MIIM_BUS_SEL_MAP_19_10r, 1934 CMIC_MIIM_BUS_SEL_MAP_29_20r, CMIC_MIIM_BUS_SEL_MAP_39_30r, 1935 CMIC_MIIM_BUS_SEL_MAP_49_40r, CMIC_MIIM_BUS_SEL_MAP_59_50r, 1936 CMIC_MIIM_BUS_SEL_MAP_69_60r, CMIC_MIIM_BUS_SEL_MAP_79_70r, 1937 CMIC_MIIM_BUS_SEL_MAP_89_80r, CMIC_MIIM_BUS_SEL_MAP_99_90r, 1938 CMIC_MIIM_BUS_SEL_MAP_109_100r, CMIC_MIIM_BUS_SEL_MAP_119_110r, 1939 CMIC_MIIM_BUS_SEL_MAP_127_120r 1940 }; 1941 #endif /* End of BCM_CMICM_SUPPORT */ 1942 1943 STATIC const soc_reg_t *bus_map = bus_map_reg; 1944 STATIC const soc_field_t bus_map_9_0_field[] = { 1945 PORT_0_BUS_NUMf, PORT_1_BUS_NUMf, PORT_2_BUS_NUMf, PORT_3_BUS_NUMf, 1946 PORT_4_BUS_NUMf, PORT_5_BUS_NUMf, PORT_6_BUS_NUMf, PORT_7_BUS_NUMf, 1947 PORT_8_BUS_NUMf, PORT_9_BUS_NUMf 1948 }; 1949 STATIC const soc_reg_t phy_map_reg[] = { 1950 CMIC_MIIM_EXT_PHY_ADDR_MAP_3_0r, CMIC_MIIM_EXT_PHY_ADDR_MAP_7_4r, 1951 CMIC_MIIM_EXT_PHY_ADDR_MAP_11_8r, CMIC_MIIM_EXT_PHY_ADDR_MAP_15_12r, 1952 CMIC_MIIM_EXT_PHY_ADDR_MAP_19_16r, CMIC_MIIM_EXT_PHY_ADDR_MAP_23_20r, 1953 CMIC_MIIM_EXT_PHY_ADDR_MAP_27_24r, CMIC_MIIM_EXT_PHY_ADDR_MAP_31_28r, 1954 CMIC_MIIM_EXT_PHY_ADDR_MAP_35_32r, CMIC_MIIM_EXT_PHY_ADDR_MAP_39_36r, 1955 CMIC_MIIM_EXT_PHY_ADDR_MAP_43_40r, CMIC_MIIM_EXT_PHY_ADDR_MAP_47_44r, 1956 CMIC_MIIM_EXT_PHY_ADDR_MAP_51_48r, CMIC_MIIM_EXT_PHY_ADDR_MAP_55_52r, 1957 CMIC_MIIM_EXT_PHY_ADDR_MAP_59_56r, CMIC_MIIM_EXT_PHY_ADDR_MAP_63_60r, 1958 CMIC_MIIM_EXT_PHY_ADDR_MAP_67_64r, CMIC_MIIM_EXT_PHY_ADDR_MAP_71_68r, 1959 CMIC_MIIM_EXT_PHY_ADDR_MAP_75_72r, CMIC_MIIM_EXT_PHY_ADDR_MAP_79_76r, 1960 CMIC_MIIM_EXT_PHY_ADDR_MAP_83_80r, CMIC_MIIM_EXT_PHY_ADDR_MAP_87_84r, 1961 CMIC_MIIM_EXT_PHY_ADDR_MAP_91_88r, CMIC_MIIM_EXT_PHY_ADDR_MAP_95_92r, 1962 CMIC_MIIM_EXT_PHY_ADDR_MAP_99_96r, 1963 CMIC_MIIM_EXT_PHY_ADDR_MAP_103_100r, 1964 CMIC_MIIM_EXT_PHY_ADDR_MAP_107_104r, 1965 CMIC_MIIM_EXT_PHY_ADDR_MAP_111_108r, 1966 CMIC_MIIM_EXT_PHY_ADDR_MAP_115_112r, 1967 CMIC_MIIM_EXT_PHY_ADDR_MAP_119_116r, 1968 CMIC_MIIM_EXT_PHY_ADDR_MAP_123_120r, 1969 CMIC_MIIM_EXT_PHY_ADDR_MAP_127_124r, 1970 #if defined(BCM_CMICDV2_SUPPORT) 1971 CMIC_MIIM_EXT_PHY_ADDR_MAP_131_128r, 1972 CMIC_MIIM_EXT_PHY_ADDR_MAP_135_132r, 1973 CMIC_MIIM_EXT_PHY_ADDR_MAP_139_136r, 1974 CMIC_MIIM_EXT_PHY_ADDR_MAP_143_140r, 1975 CMIC_MIIM_EXT_PHY_ADDR_MAP_147_144r, 1976 CMIC_MIIM_EXT_PHY_ADDR_MAP_151_148r, 1977 CMIC_MIIM_EXT_PHY_ADDR_MAP_155_152r, 1978 CMIC_MIIM_EXT_PHY_ADDR_MAP_159_156r, 1979 CMIC_MIIM_EXT_PHY_ADDR_MAP_163_160r, 1980 CMIC_MIIM_EXT_PHY_ADDR_MAP_167_164r, 1981 CMIC_MIIM_EXT_PHY_ADDR_MAP_171_168r, 1982 CMIC_MIIM_EXT_PHY_ADDR_MAP_175_172r, 1983 CMIC_MIIM_EXT_PHY_ADDR_MAP_179_176r, 1984 CMIC_MIIM_EXT_PHY_ADDR_MAP_183_180r, 1985 CMIC_MIIM_EXT_PHY_ADDR_MAP_187_184r, 1986 CMIC_MIIM_EXT_PHY_ADDR_MAP_191_188r, 1987 #endif 1988 #if defined(BCM_CMICDV3_SUPPORT) 1989 CMIC_MIIM_EXT_PHY_ADDR_MAP_195_192r, 1990 CMIC_MIIM_EXT_PHY_ADDR_MAP_199_196r, 1991 CMIC_MIIM_EXT_PHY_ADDR_MAP_203_200r, 1992 CMIC_MIIM_EXT_PHY_ADDR_MAP_207_204r, 1993 CMIC_MIIM_EXT_PHY_ADDR_MAP_211_208r, 1994 CMIC_MIIM_EXT_PHY_ADDR_MAP_215_212r, 1995 CMIC_MIIM_EXT_PHY_ADDR_MAP_219_216r, 1996 CMIC_MIIM_EXT_PHY_ADDR_MAP_223_220r, 1997 CMIC_MIIM_EXT_PHY_ADDR_MAP_227_224r, 1998 CMIC_MIIM_EXT_PHY_ADDR_MAP_231_228r, 1999 CMIC_MIIM_EXT_PHY_ADDR_MAP_235_232r, 2000 CMIC_MIIM_EXT_PHY_ADDR_MAP_239_236r, 2001 CMIC_MIIM_EXT_PHY_ADDR_MAP_243_240r, 2002 CMIC_MIIM_EXT_PHY_ADDR_MAP_247_244r, 2003 CMIC_MIIM_EXT_PHY_ADDR_MAP_251_248r, 2004 CMIC_MIIM_EXT_PHY_ADDR_MAP_255_252r, 2005 CMIC_MIIM_EXT_PHY_ADDR_MAP_259_256r, 2006 CMIC_MIIM_EXT_PHY_ADDR_MAP_263_260r, 2007 CMIC_MIIM_EXT_PHY_ADDR_MAP_267_264r, 2008 CMIC_MIIM_EXT_PHY_ADDR_MAP_271_268r, 2009 CMIC_MIIM_EXT_PHY_ADDR_MAP_275_272r, 2010 CMIC_MIIM_EXT_PHY_ADDR_MAP_279_276r, 2011 CMIC_MIIM_EXT_PHY_ADDR_MAP_283_280r, 2012 CMIC_MIIM_EXT_PHY_ADDR_MAP_287_284r, 2013 CMIC_MIIM_EXT_PHY_ADDR_MAP_291_288r, 2014 CMIC_MIIM_EXT_PHY_ADDR_MAP_295_292r, 2015 CMIC_MIIM_EXT_PHY_ADDR_MAP_299_296r, 2016 CMIC_MIIM_EXT_PHY_ADDR_MAP_303_300r, 2017 CMIC_MIIM_EXT_PHY_ADDR_MAP_307_304r, 2018 CMIC_MIIM_EXT_PHY_ADDR_MAP_311_308r, 2019 CMIC_MIIM_EXT_PHY_ADDR_MAP_315_312r, 2020 CMIC_MIIM_EXT_PHY_ADDR_MAP_319_316r, 2021 #endif 2022 }; 2023 STATIC const soc_field_t phy_map_3_0_field[] = { 2024 PHY_ID_0f, PHY_ID_1f, PHY_ID_2f, PHY_ID_3f 2025 }; 2026 soc_reg_t reg; 2027 soc_field_t field; 2028 int addr; 2029 uint32 rval; 2030 int bus_sel; 2031 soc_port_t phy_port, port_bit; 2032 int phy_addr; 2033 int bus_map_array_size; 2034 2035 if (SOC_IS_TRIDENT3X(unit)) { 2036 return SOC_E_NONE; 2037 } 2038 2039 if (SOC_IS_ESW(unit)) { 2040 2041 /* hold MIIM lock */ 2042 MIIM_LOCK(unit); 2043 2044 if (soc_feature(unit, soc_feature_logical_port_num)) { 2045 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 2046 } else { 2047 phy_port = port; 2048 } 2049 2050 port_bit = phy_port; 2051 #ifdef BCM_GREYHOUND2_SUPPORT 2052 if (SOC_IS_GREYHOUND2(unit)) { 2053 port_bit = (port_bit >= 58) ? (port_bit + GREYHOUND2_PHY_PORT_OFFSET) 2054 : port_bit; 2055 } 2056 #endif /* BCM_GREYHOUND2_SUPPORT */ 2057 PHY_PORT_TO_LINKSCAN_PORT_XLATE(unit, port_bit); 2058 2059 #ifdef BCM_SCORPION_SUPPORT 2060 if (SOC_IS_SC_CQ(unit) || SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit) || 2061 SOC_IS_KATANAX(unit)) { 2062 /* 2063 * SC/CQ devices omit the CMIC port from the PHY counting. All 2064 * "port bitmaps" are shifted by 1. 2065 */ 2066 if (port == CMIC_PORT(unit)) { 2067 /* This should not be triggered */ 2068 2069 /* Release MIIM lock */ 2070 MIIM_UNLOCK(unit); 2071 return SOC_E_PORT; 2072 } 2073 if (!SOC_IS_KATANAX(unit)) { 2074 port_bit -= 1; 2075 } 2076 } 2077 #endif 2078 2079 bus_map_array_size = COUNTOF(bus_map_reg); 2080 #if defined (BCM_CMICM_SUPPORT) 2081 if (soc_feature(unit, soc_feature_cmicm)) { 2082 bus_map = bus_map_reg_cmicm; 2083 bus_map_array_size = COUNTOF(bus_map_reg_cmicm); 2084 #if defined (BCM_CMICDV2_SUPPORT) 2085 if (soc_feature(unit, soc_feature_cmicd_v2)) { 2086 bus_map = bus_map_reg_cmicdv2; 2087 bus_map_array_size = COUNTOF(bus_map_reg_cmicdv2); 2088 } 2089 #endif /* BCM_CMICDV2_SUPPORT */ 2090 #if defined (BCM_CMICDV3_SUPPORT) 2091 if (soc_feature(unit, soc_feature_cmicd_v3)) { 2092 bus_map = bus_map_reg_cmicdv3; 2093 bus_map_array_size = COUNTOF(bus_map_reg_cmicdv3); 2094 } 2095 #endif /* BCM_CMICDV3_SUPPORT */ 2096 } 2097 #endif 2098 2099 /* 2100 * Select the appropriate MDIO bus 2101 */ 2102 phy_addr = _soc_linkscan_port_to_phyaddr(unit, port); 2103 2104 if (SOC_IS_TD_TT(unit) || SOC_IS_METROLITE(unit)) { 2105 bus_sel = ((phy_addr & 0x300) >> 6) | 2106 ((phy_addr & 0x60) >> 5) ; 2107 } else if (SOC_IS_TRX(unit)) { 2108 bus_sel = (phy_addr & 0x60) >> 5; /* bus 0, 1, and 2 */ 2109 } else { 2110 bus_sel = (phy_addr & 0x40) >> 6; /* bus 0 and 1 */ 2111 } 2112 2113 #if defined (BCM_CMICDV3_SUPPORT) 2114 if (soc_feature(unit, soc_feature_cmicd_v3)) { 2115 if ((port_bit / 8) < bus_map_array_size) { 2116 reg = bus_map[port_bit / 8]; 2117 } else { 2118 return SOC_E_INTERNAL; 2119 } 2120 field = bus_map_9_0_field[port_bit % 8]; 2121 2122 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 2123 rval = soc_pci_read(unit, addr); 2124 soc_reg_field_set(unit, bus_map[0], &rval, field, bus_sel); 2125 soc_pci_write(unit, addr, rval); 2126 2127 } else 2128 #endif /* BCM_CMICDV3_SUPPORT */ 2129 if (SOC_REG_IS_VALID(unit, bus_map[0])) { 2130 if ((port_bit / 10) < bus_map_array_size) { 2131 reg = bus_map[port_bit / 10]; 2132 } else { 2133 return SOC_E_INTERNAL; 2134 } 2135 field = bus_map_9_0_field[port_bit % 10]; 2136 if (SOC_REG_IS_VALID(unit, reg)) { 2137 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 2138 rval = soc_pci_read(unit, addr); 2139 soc_reg_field_set(unit, bus_map[0], &rval, field, bus_sel); 2140 soc_pci_write(unit, addr, rval); 2141 } 2142 } else { 2143 reg = INVALIDr; 2144 if (bus_sel == 1) { 2145 if ((port_bit / 32) < COUNTOF(port_type_map_reg)) { 2146 reg = port_type_map_reg[port_bit / 32]; 2147 } else { 2148 return SOC_E_INTERNAL; 2149 } 2150 } else if ((bus_sel == 2) && !SOC_IS_SHADOW(unit)) { 2151 if ((port_bit / 32) < COUNTOF(port_type_map_bus2_reg)) { 2152 reg = port_type_map_bus2_reg[port_bit / 32]; 2153 } else { 2154 return SOC_E_INTERNAL; 2155 } 2156 } 2157 if (SOC_REG_IS_VALID(unit, reg)) { 2158 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 2159 rval = soc_pci_read(unit, addr); 2160 rval |= 1 << (port_bit % 32); 2161 soc_pci_write(unit, addr, rval); 2162 } 2163 } 2164 2165 /* Re-initialize the phy port map for the unit */ 2166 /* Use MDIO address re-mapping for hardware linkscan */ 2167 assert(port_bit >= 0); 2168 assert(port_bit / 4 < sizeof(phy_map_reg) / sizeof(phy_map_reg[0])); 2169 2170 /* 2171 * COVERITY 2172 * 2173 * assert validates the input 2174 */ 2175 /* coverity[overrun-local : FALSE] */ 2176 reg = phy_map_reg[port_bit / 4]; 2177 field = phy_map_3_0_field[port_bit % 4]; 2178 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0); 2179 rval = soc_pci_read(unit, addr); 2180 soc_reg_field_set(unit, phy_map_reg[0], &rval, field, 2181 PHY_ADDR(unit, port) & 0x1f); 2182 soc_pci_write(unit, addr, rval); 2183 2184 2185 #if defined (BCM_CMICM_SUPPORT) 2186 if (soc_feature(unit, soc_feature_cmicm)) { 2187 READ_CMIC_MIIM_SCAN_CTRLr(unit, &rval); 2188 soc_reg_field_set(unit, CMIC_MIIM_SCAN_CTRLr, &rval, 2189 MIIM_ADDR_MAP_ENABLEf, 1); 2190 WRITE_CMIC_MIIM_SCAN_CTRLr(unit, rval); 2191 } else 2192 #endif 2193 #if defined (BCM_CMICX_SUPPORT) 2194 if (soc_feature(unit, soc_feature_cmicx)) { 2195 2196 } else 2197 #endif 2198 { 2199 READ_CMIC_CONFIGr(unit, &rval); 2200 soc_reg_field_set(unit, CMIC_CONFIGr, &rval, MIIM_ADDR_MAP_ENABLEf, 1); 2201 WRITE_CMIC_CONFIGr(unit, rval); 2202 } 2203 2204 /* Release MIIM lock */ 2205 MIIM_UNLOCK(unit); 2206 } 2207 #endif /* defined(BCM_ESW_SUPPORT) */ 2208 return SOC_E_NONE; 2209 } 2210 2211 int 2212 soc_linkscan_hw_init(int unit) 2213 { 2214 #if defined(BCM_XGS3_SWITCH_SUPPORT) 2215 #ifdef BCM_XGS3_SWITCH_SUPPORT 2216 int automedium = 0; 2217 uint32 rval = 0; 2218 #endif 2219 2220 if (SOC_IS_XGS3_SWITCH(unit)) { 2221 soc_port_t port; 2222 pbmp_t phy_port_pbmp; 2223 #ifdef BCM_CMICX_SUPPORT 2224 if (soc_feature(unit, soc_feature_cmicx)) { 2225 if (!(SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM)) { 2226 #if CMICX_HW_LINKSCAN 2227 SOC_IF_ERROR_RETURN(soc_cmicx_linkscan_hw_init(unit)); 2228 #endif 2229 return SOC_E_NONE; 2230 } else { 2231 /* CMICx supported and BCMSIM/PLISIM true */ 2232 return SOC_E_NONE; 2233 } 2234 } 2235 else 2236 #endif 2237 { 2238 SOC_PBMP_ASSIGN(phy_port_pbmp, PBMP_PORT_ALL(unit)); 2239 PBMP_ITER(phy_port_pbmp, port) { 2240 /* 2241 * COVERITY 2242 * 2243 * The iterator above will protect any real cases so the 2244 * port index does not exceed the declared size. 2245 */ 2246 /* coverity[overrun-call] */ 2247 SOC_IF_ERROR_RETURN 2248 (_soc_linkscan_hw_port_init(unit, port)); 2249 } 2250 } 2251 #ifdef BCM_XGS3_SWITCH_SUPPORT 2252 PBMP_ITER(PBMP_PORT_ALL(unit), port) { 2253 automedium |= soc_property_port_get(unit, port, 2254 spn_PHY_AUTOMEDIUM, 0); 2255 } 2256 if (!automedium) { 2257 /* 2258 * Setting the Auto Scan Address for HW linkscan 2259 * Bit 2 of 0x01 register (MII_STATUS for Cu and Fiber) 2260 */ 2261 if (soc_feature(unit, soc_feature_cmicm)) { 2262 READ_CMIC_MIIM_AUTO_SCAN_ADDRESSr(unit, &rval); 2263 soc_reg_field_set(unit, CMIC_MIIM_AUTO_SCAN_ADDRESSr, &rval, 2264 MIIM_LINK_STATUS_BIT_POSITIONf, 0x2); 2265 if (SOC_REG_FIELD_VALID(unit, CMIC_MIIM_AUTO_SCAN_ADDRESSr, 2266 CLAUSE_22_REGADRf)) { 2267 soc_reg_field_set(unit, CMIC_MIIM_AUTO_SCAN_ADDRESSr, &rval, 2268 CLAUSE_22_REGADRf, 0x1); 2269 } 2270 if (SOC_REG_FIELD_VALID(unit, CMIC_MIIM_AUTO_SCAN_ADDRESSr, 2271 CLAUSE_45_REGADRf)) { 2272 soc_reg_field_set(unit, CMIC_MIIM_AUTO_SCAN_ADDRESSr, &rval, 2273 CLAUSE_45_REGADRf, 0x1); 2274 } 2275 if (SOC_REG_FIELD_VALID(unit, CMIC_MIIM_AUTO_SCAN_ADDRESSr, 2276 CLAUSE_45_DTYPEf)) { 2277 soc_reg_field_set(unit, CMIC_MIIM_AUTO_SCAN_ADDRESSr, &rval, 2278 CLAUSE_45_DTYPEf, 0x1); 2279 } 2280 WRITE_CMIC_MIIM_AUTO_SCAN_ADDRESSr(unit, rval); 2281 } else if (SOC_IS_HAWKEYE(unit) || (SOC_IS_TR_VL(unit) && 2282 !(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 2283 SOC_IS_GREYHOUND2(unit)))) { 2284 READ_CMIC_MIIM_AUTO_SCAN_ADDRESSr(unit, &rval); 2285 soc_reg_field_set(unit, CMIC_MIIM_AUTO_SCAN_ADDRESSr, &rval, 2286 MIIM_LINK_STATUS_BIT_POSITIONf, 0x2); 2287 soc_reg_field_set(unit, CMIC_MIIM_AUTO_SCAN_ADDRESSr, &rval, 2288 MIIM_DEVICE_ADDRESSf, 0x1); 2289 WRITE_CMIC_MIIM_AUTO_SCAN_ADDRESSr(unit, rval); 2290 } else { 2291 if (SOC_REG_IS_VALID(unit, CMIC_MIIM_ADDRESSr)) { 2292 if (soc_reg_field_valid(unit, CMIC_MIIM_AUTO_SCAN_ADDRESSr, 2293 CLAUSE_22_REGADRf)) { 2294 READ_CMIC_MIIM_ADDRESSr(unit, &rval); 2295 soc_reg_field_set(unit, CMIC_MIIM_AUTO_SCAN_ADDRESSr, 2296 &rval, CLAUSE_22_REGADRf, 0x1); 2297 WRITE_CMIC_MIIM_ADDRESSr(unit, rval); 2298 } 2299 } 2300 } 2301 } 2302 #endif 2303 } 2304 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 2305 2306 return SOC_E_NONE; 2307 } 2308 2309 int 2310 soc_linkscan_hw_link_get(int unit, soc_pbmp_t *hw_link) 2311 { 2312 int rv; 2313 2314 rv = SOC_E_UNAVAIL; 2315 2316 #if defined (BCM_ESW_SUPPORT) 2317 if (SOC_IS_ESW(unit)) { 2318 rv = _soc_linkscan_hw_link_get(unit, hw_link); 2319 } 2320 #endif /* BCM_ESW_SUPPORT */ 2321 2322 return rv; 2323 } 2324 2325 int 2326 soc_linkscan_hw_link_cache_get(int unit, soc_pbmp_t *hw_link) 2327 { 2328 int rv; 2329 rv = SOC_E_UNAVAIL; 2330 2331 #if defined (BCM_ESW_SUPPORT) 2332 if (SOC_IS_ESW(unit)) { 2333 #ifdef BCM_CMICX_SUPPORT 2334 if(soc_feature(unit, soc_feature_cmicx)) { 2335 rv = soc_cmicx_linkscan_hw_link_cache_get(unit, hw_link); 2336 } 2337 #endif /* BCM_CMICX_SUPPORT */ 2338 } 2339 #endif /* BCM_ESW_SUPPORT */ 2340 return rv; 2341 }