openbcm

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

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 }