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

miim.c (106213B)


      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  * MII Management (MDIO) bus access routines for reading and writing PHY
      8  * registers.
      9  *
     10  * BCM5690 has an internal MDIO bus in addition to the external one.
     11  * The internal bus is accessed by setting bit 7 in the PHY ID.
     12  */
     13 
     14 #include <shared/bsl.h>
     15 
     16 #include <sal/core/libc.h>
     17 #include <sal/core/boot.h>
     18 
     19 #include <soc/mem.h>
     20 #include <soc/debug.h>
     21 #include <soc/cm.h>
     22 #include <soc/drv.h>
     23 #include <soc/error.h>
     24 #include <soc/cmic.h>
     25 #include <soc/phyreg.h>
     26 #include <soc/linkctrl.h>
     27 #ifdef BCM_CMICM_SUPPORT
     28 #include <soc/cmicm.h>
     29 #endif
     30 
     31 #ifdef PORTMOD_SUPPORT
     32 #include <soc/portmod/portmod.h>
     33 #endif /* PORTMOD_SUPPORT*/
     34 
     35 #ifdef BCM_CMICX_SUPPORT
     36 #include <soc/cmicx_miim.h>
     37 #endif
     38 
     39 #define MIIM_POLL_TIMEOUT  250
     40 
     41 #if defined(BCM_SAND_SUPPORT)
     42 
     43 int
     44 soc_dcmn_miim_operation(int unit, int is_write, int clause, uint32 phy_id,
     45                   uint32 phy_reg_addr, uint16 *phy_data)
     46 {
     47     int rv = SOC_E_NONE;
     48     int clause45;
     49     int miim_intr_retry_cnt = MIIM_INTR_RETRY_COUNT;
     50     uint32 reg_val, real_phy_id, real_bus_id, internal_select, lsrv;
     51 
     52     clause45 = (45 == clause);
     53 
     54     /* Pause link scanning */
     55     rv = soc_linkctrl_linkscan_pause(unit);
     56     if (rv != SOC_E_NONE) {
     57         LOG_ERROR(BSL_LS_SOC_COMMON,
     58                   (BSL_META_U(unit,
     59                               "soc_linkctrl_linkscan_pause failed\n")));
     60         return rv;
     61     }
     62 
     63     /* hold MIIM lock */
     64     MIIM_LOCK(unit);
     65 
     66     /*  write reg_addr and c45 extention address or if c22: just reg addr */
     67     reg_val = 0;
     68     if (clause45){
     69         soc_reg_field_set(unit, CMIC_MIIM_ADDRESSr, &reg_val, CLAUSE_45_REGADRf, SOC_PHY_CLAUSE45_REGAD(phy_reg_addr));
     70         soc_reg_field_set(unit, CMIC_MIIM_ADDRESSr, &reg_val, CLAUSE_45_DTYPEf,  SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr));
     71     } else {
     72         soc_reg_field_set(unit, CMIC_MIIM_ADDRESSr, &reg_val, CLAUSE_22_REGADRf, phy_reg_addr);
     73     }
     74     WRITE_CMIC_MIIM_ADDRESSr(unit, reg_val);
     75 
     76     /* write the parameters */
     77     reg_val = 0;
     78     internal_select = (phy_id & 0x80) ? 1 : 0;
     79     real_phy_id = phy_id & ~(PHY_ID_BUS_UPPER_MASK | PHY_ID_BUS_LOWER_MASK);
     80     real_phy_id &= ~(0x80); /*clear internal / external bit*/ 
     81     real_bus_id = PHY_ID_BUS_NUM(phy_id);
     82 
     83     if (clause45){
     84     LOG_DEBUG(BSL_LS_SOC_MIIM,
     85              (BSL_META_U(unit,
     86                          "soc_dcmn_miim_operation cl45 %s: "
     87                          "(id=0x%02x readr=0x%x dtype=0x%x data=0x%04x clause45=%d, real_phy_id=%d, real_bus_id=%d)\n"),
     88               is_write ? "write" : "read ", phy_id, SOC_PHY_CLAUSE45_REGAD(phy_reg_addr), SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr), *phy_data, clause45,
     89               real_phy_id,real_bus_id));
     90     } else {
     91     LOG_DEBUG(BSL_LS_SOC_MIIM,
     92              (BSL_META_U(unit,
     93                          "soc_dcmn_miim_operation cl22 %s: "
     94                          "(id=0x%02x addr=0x%02x data=0x%04x clause45=%d, real_phy_id=%d, real_bus_id=%d)\n"),
     95               is_write ? "write" : "read ", phy_id, phy_reg_addr, *phy_data, clause45,real_phy_id,real_bus_id));
     96     }
     97 
     98     soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &reg_val, INTERNAL_SELf, internal_select);
     99     soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &reg_val, C45_SELf, clause45);
    100     soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &reg_val, PHY_IDf, real_phy_id);
    101     if(is_write) {
    102         soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &reg_val, PHY_DATAf, *phy_data);
    103     } else {
    104         soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &reg_val, PHY_DATAf, 0x0);
    105     }
    106     soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &reg_val, BUS_IDf, real_bus_id);
    107     WRITE_CMIC_MIIM_PARAMr(unit, reg_val);
    108 
    109     /*  start the access */
    110     READ_CMIC_SCHAN_CTRLr(unit, &reg_val);
    111     if(is_write) {
    112         /*MIIM_WR_STARTf*/
    113         WRITE_CMIC_SCHAN_CTRLr(unit, 0x91);
    114     } else {
    115         /*MIIM_RD_STARTf*/
    116         WRITE_CMIC_SCHAN_CTRLr(unit, 0x90);
    117     }
    118 
    119 
    120     /* Wait for completion using either the interrupt or polling method */
    121 
    122     if (SOC_CONTROL(unit)->miimIntrEnb) {
    123         soc_intr_enable(unit, IRQ_MIIM_OP_DONE);
    124 
    125         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
    126                          SOC_CONTROL(unit)->miimTimeout) != 0) {
    127             if ((soc_pci_read(unit, SOC_REG_INFO(unit,CMIC_SCHAN_CTRLr).offset) &
    128                 SC_MIIM_OP_DONE_TST) == 0) {
    129                 /* MIIM HW operation not complete */
    130                 rv = SOC_E_TIMEOUT;
    131             } else {
    132                 /* MIIM HW operation complete but no intr received yet
    133                  * Retry for MIIM Intr for busy system
    134                  * before declaring timeout */
    135                 rv = SOC_E_TIMEOUT;
    136                 while (miim_intr_retry_cnt) {
    137                     if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
    138                                      MIIM_INTR_RETRY_TIMEOUT) == 0) {
    139                         rv = SOC_E_NONE;
    140                         break;
    141                     }
    142                     miim_intr_retry_cnt--;
    143                 }
    144             }
    145         } else {
    146             LOG_DEBUG(BSL_LS_SOC_MIIM,
    147                         (BSL_META_U(unit,
    148                                     "  Interrupt received\n")));
    149         }
    150 
    151         soc_intr_disable(unit, IRQ_MIIM_OP_DONE);     
    152 
    153     } else {
    154         soc_timeout_t to;
    155 
    156         soc_timeout_init(&to, SOC_CONTROL(unit)->miimTimeout, 2500);
    157 
    158         while ((soc_pci_read(unit, SOC_REG_INFO(unit,CMIC_SCHAN_CTRLr).offset) &
    159                 SC_MIIM_OP_DONE_TST) == 0) {
    160             if (soc_timeout_check(&to)) {
    161                 rv = SOC_E_TIMEOUT;
    162                 break;
    163             }
    164         }
    165         
    166         if (rv == SOC_E_NONE) {
    167             LOG_DEBUG(BSL_LS_SOC_MIIM,
    168                         (BSL_META_U(unit,
    169                                     "  Done in %d polls\n"), to.polls));
    170         }
    171 
    172         WRITE_CMIC_SCHAN_CTRLr(unit, SC_MIIM_OP_DONE_CLR);
    173         
    174     }
    175 
    176     if (rv == SOC_E_TIMEOUT) {
    177         if(is_write) {
    178             LOG_ERROR(BSL_LS_SOC_COMMON,
    179                       (BSL_META_U(unit,
    180                                   "MiimTimeOut:soc_dcmn_miim_operation write, "
    181                                   "timeout (id=0x%02x addr=0x%02x data=0x%04x)\n"),
    182                        phy_id, phy_reg_addr, *phy_data));
    183         } else /*read*/{
    184             LOG_ERROR(BSL_LS_SOC_COMMON,
    185                       (BSL_META_U(unit,
    186                                   "MiimTimeOut:soc_dcmn_miim_operation read, "
    187                                   "timeout (id=0x%02x addr=0x%02x)\n"),
    188                        phy_id, phy_reg_addr));
    189         }
    190         SOC_CONTROL(unit)->stat.err_mii_tmo++;
    191     }
    192 
    193     /* read data */
    194     if(SOC_E_NONE == rv && !is_write) {
    195         *phy_data = (uint16)soc_pci_read(unit, SOC_REG_INFO(unit,CMIC_MIIM_READ_DATAr).offset);
    196         LOG_VERBOSE(BSL_LS_SOC_MIIM,
    197                      (BSL_META_U(unit,
    198                                  "soc_dcmn_miim_operation read data: %d \n"),*phy_data)); 
    199     }
    200 
    201     /* Release linkscan pause and MIIM lock */
    202     MIIM_UNLOCK(unit);
    203 
    204     lsrv = soc_linkctrl_linkscan_continue(unit);
    205     if(SOC_E_NONE != lsrv) {
    206         LOG_ERROR(BSL_LS_SOC_COMMON,
    207                   (BSL_META_U(unit,
    208                               "soc_linkctrl_linkscan_continue failed\n")));
    209         rv = lsrv;
    210     }
    211 
    212     return rv;
    213 }
    214 
    215 #if defined(BCM_CMICM_SUPPORT)
    216 
    217 #define SOC_DCMN_MIIM_FORCE_CL45_BIT    (21)
    218 
    219 int
    220 soc_dcmn_cmicm_miim_operation(int unit, int is_write, int clause, uint32 phy_id,
    221                   uint32 phy_reg_addr, uint16 *phy_data)
    222 {
    223     int rv = SOC_E_NONE;
    224     int clause45, cmc;
    225     uint32 reg_val, real_phy_id, real_bus_id, internal_select, lsrv;
    226     int miim_intr_retry_cnt = MIIM_INTR_RETRY_COUNT;
    227 
    228     cmc = SOC_PCI_CMC(unit);
    229 
    230     clause45 = (45 == clause);
    231 
    232     
    233     SHR_BITCLR(&phy_reg_addr, SOC_DCMN_MIIM_FORCE_CL45_BIT);
    234 
    235     /* Pause link scanning */
    236     rv = soc_linkctrl_linkscan_pause(unit);
    237     if (rv != SOC_E_NONE) {
    238         LOG_ERROR(BSL_LS_SOC_COMMON,
    239                   (BSL_META_U(unit,
    240                               "soc_linkctrl_linkscan_pause failed\n")));
    241         return rv;
    242     }
    243 
    244     MIIM_LOCK(unit);
    245 
    246     /*  write reg_addr and c45 extention address or if c22: just reg addr */
    247     reg_val = 0;
    248     if (clause45){
    249         soc_reg_field_set(unit, CMIC_CMC0_MIIM_ADDRESSr, &reg_val, CLAUSE_45_REGADRf, SOC_PHY_CLAUSE45_REGAD(phy_reg_addr));
    250         soc_reg_field_set(unit, CMIC_CMC0_MIIM_ADDRESSr, &reg_val, CLAUSE_45_DTYPEf,  SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr));
    251     } else {
    252         /* CLAUSE_22_REGADRf does not exist in CMICD register spec*/
    253         reg_val = phy_reg_addr & 0x1f;
    254     }
    255     soc_pci_write(unit, CMIC_CMCx_MIIM_ADDRESS_OFFSET(cmc), reg_val);
    256 
    257     /* write the parameters */
    258     reg_val = 0;
    259     internal_select = (phy_id & 0x80) ? 1 : 0;
    260     real_phy_id = phy_id & ~(PHY_ID_BUS_UPPER_MASK | PHY_ID_BUS_LOWER_MASK);
    261     real_phy_id &= ~(0x80); /*clear internal / external bit*/ 
    262     real_bus_id = PHY_ID_BUS_NUM(phy_id);
    263 
    264     if (clause45){
    265         LOG_DEBUG(BSL_LS_SOC_MIIM,
    266                  (BSL_META_U(unit,
    267                              "soc_dcmn_cmicm_miim_operation cl45 %s: "
    268                              "(id=0x%02x readr=0x%x dtype=0x%x data=0x%04x clause45=%d, real_phy_id=%d, real_bus_id=%d)\n"),
    269                   is_write ? "write" : "read ", phy_id, SOC_PHY_CLAUSE45_REGAD(phy_reg_addr), SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr), *phy_data, clause45,
    270                   real_phy_id,real_bus_id));
    271     } else {
    272         LOG_DEBUG(BSL_LS_SOC_MIIM,
    273                  (BSL_META_U(unit,
    274                              "soc_dcmn_cmicm_miim_operation cl22 %s: "
    275                              "(id=0x%02x addr=0x%02x data=0x%04x clause45=%d, real_phy_id=%d, real_bus_id=%d)\n"),
    276                   is_write ? "write" : "read ", phy_id, phy_reg_addr, *phy_data, clause45,real_phy_id,real_bus_id));
    277     } 
    278 
    279 
    280     soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &reg_val, INTERNAL_SELf, internal_select);
    281     soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &reg_val, C45_SELf, clause45);
    282     soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &reg_val, PHY_IDf, real_phy_id);
    283     if(is_write) {
    284         soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &reg_val, PHY_DATAf, *phy_data);
    285     } else {
    286         soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &reg_val, PHY_DATAf, 0x0);
    287     }
    288     soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &reg_val, BUS_IDf, real_bus_id);
    289     soc_pci_write(unit, CMIC_CMCx_MIIM_PARAM_OFFSET(cmc), reg_val);
    290 
    291     /*  start the access */
    292     if(is_write) {
    293         soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 1);
    294     } else {
    295         soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 2);
    296     }
    297 
    298 
    299     /* Wait for completion using either the interrupt or polling method */
    300 
    301     if (SOC_CONTROL(unit)->miimIntrEnb) {
    302 
    303         soc_cmicm_intr0_enable(unit, IRQ_CMCx_MIIM_OP_DONE);
    304 
    305         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
    306                          SOC_CONTROL(unit)->miimTimeout) != 0) {
    307             if ((soc_pci_read(unit, CMIC_CMCx_MIIM_STAT_OFFSET(cmc)) &
    308                 CMIC_MIIM_OPN_DONE) == 0) {
    309                 /* MIIM HW operation not complete */
    310                 rv = SOC_E_TIMEOUT;
    311             } else {
    312                 /* MIIM HW operation complete but no intr received yet
    313                  * Retry for MIIM Intr for busy system
    314                  * before declaring timeout */
    315                 rv = SOC_E_TIMEOUT;
    316                 while (miim_intr_retry_cnt) {
    317                     if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
    318                                      MIIM_INTR_RETRY_TIMEOUT) == 0) {
    319                         rv = SOC_E_NONE;
    320                         break;
    321                     }
    322                     miim_intr_retry_cnt--;
    323                 }
    324             }
    325         } else {
    326             LOG_DEBUG(BSL_LS_SOC_MIIM,
    327                         (BSL_META_U(unit,
    328                                     "  Interrupt received\n")));
    329         }
    330 
    331         soc_cmicm_intr0_disable(unit, IRQ_CMCx_MIIM_OP_DONE);
    332 
    333     } else {
    334         soc_timeout_t to;
    335 
    336         soc_timeout_init(&to, SOC_CONTROL(unit)->miimTimeout, 2500);
    337 
    338         while ((soc_pci_read(unit, CMIC_CMCx_MIIM_STAT_OFFSET(cmc)) &
    339                 CMIC_MIIM_OPN_DONE) == 0) {
    340             if (soc_timeout_check(&to)) {
    341                 rv = SOC_E_TIMEOUT;
    342                 break;
    343             }
    344         }
    345         
    346         if (rv == SOC_E_NONE) {
    347             LOG_DEBUG(BSL_LS_SOC_MIIM,
    348                         (BSL_META_U(unit,
    349                                     "  Done in %d polls\n"), to.polls));
    350         }
    351 
    352         soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 0);
    353         
    354     }
    355 
    356     if (rv == SOC_E_TIMEOUT) {
    357         if(is_write) {
    358             LOG_ERROR(BSL_LS_SOC_COMMON,
    359                       (BSL_META_U(unit,
    360                                   "MiimTimeOut:soc_dcmn_miim_operation write, "
    361                                   "timeout (id=0x%02x addr=0x%02x data=0x%04x)\n"),
    362                        phy_id, phy_reg_addr, *phy_data));
    363         } else /*read*/{
    364             LOG_ERROR(BSL_LS_SOC_COMMON,
    365                       (BSL_META_U(unit,
    366                                   "MiimTimeOut:soc_dcmn_miim_operation read, "
    367                                   "timeout (id=0x%02x addr=0x%02x)\n"),
    368                        phy_id, phy_reg_addr));
    369         }
    370         SOC_CONTROL(unit)->stat.err_mii_tmo++;
    371     }
    372 
    373     /* read data */
    374     if(SOC_E_NONE == rv && !is_write) {
    375         *phy_data = (uint16)soc_pci_read(unit, CMIC_CMCx_MIIM_READ_DATA_OFFSET(cmc));
    376         LOG_VERBOSE(BSL_LS_SOC_MIIM,
    377                      (BSL_META_U(unit,
    378                                  "soc_dcmn_miim_operation read data: %d \n"),*phy_data)); 
    379 
    380     }
    381 
    382     /* Release linkscan pause and MIIM lock */
    383     MIIM_UNLOCK(unit);
    384 
    385     lsrv = soc_linkctrl_linkscan_continue(unit);
    386     if(SOC_E_NONE != lsrv) {
    387         LOG_ERROR(BSL_LS_SOC_COMMON,
    388                   (BSL_META_U(unit,
    389                               "soc_linkctrl_linkscan_continue failed\n")));
    390         rv = lsrv;
    391     }
    392 
    393 
    394     return rv;
    395 }
    396 
    397 #endif /*BCM_CMICM_SUPPORT*/
    398 
    399 /*
    400  * Function:
    401  *      soc_dcmn_miim_write
    402  * Purpose:
    403  *      Interface to write a value to a MIIM register.
    404  * Parameters:
    405  *      unit - StrataSwitch Unit #.
    406  *      phy_id - Phy ID to write (MIIM address)
    407  *      phy_reg_addr - PHY register to write
    408  *      phy_wr_data - Data to write.
    409  * Returns:
    410  *      SOC_E_XXX
    411  */
    412 
    413 /*user defined function for external phy*/
    414 #ifdef USER_DEFINED_EXT_MDIO_FUNCTION
    415 extern int _user_defined_ext_mdio_write(int unit, int clause, uint32 phy_id,
    416                    uint32 phy_reg_addr, uint16 phy_wr_data);
    417 #endif 
    418 
    419 int 
    420 soc_dcmn_miim_write(int unit, int clause, uint32 phy_id,
    421                    uint32 phy_reg_addr, uint16 phy_wr_data)
    422 {
    423 #ifdef USER_DEFINED_EXT_MDIO_FUNCTION
    424     uint32 internal_select;
    425 #endif 
    426 
    427 #ifdef USER_DEFINED_EXT_MDIO_FUNCTION
    428     internal_select = (phy_id & 0x80) ? 1 : 0;
    429     if (!internal_select) {
    430         return _user_defined_ext_mdio_write(unit, clause, phy_id, phy_reg_addr, phy_wr_data);
    431     }
    432 #endif 
    433 
    434 #ifdef BCM_CMICX_SUPPORT
    435     if (soc_feature(unit, soc_feature_cmicx)) {
    436         return soc_cmicx_miim_operation(unit, TRUE, clause, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, phy_id,
    437                           phy_reg_addr, &phy_wr_data);
    438     } else
    439 #endif /* BCM_CMICX_SUPPORT */
    440 #if defined(BCM_CMICM_SUPPORT)
    441     if(soc_feature(unit, soc_feature_cmicm)) {
    442         return soc_dcmn_cmicm_miim_operation(unit, TRUE, clause, phy_id,
    443                           phy_reg_addr, &phy_wr_data);
    444     } else 
    445 #endif
    446     {
    447         return soc_dcmn_miim_operation(unit, TRUE, clause, phy_id,
    448                           phy_reg_addr, &phy_wr_data);
    449     }
    450 }
    451 
    452 
    453 int 
    454 soc_dcmn_miim_cl22_write(int unit, uint32 phy_id,
    455                    uint32 phy_reg_addr, uint16 phy_wr_data)
    456 {
    457     return soc_dcmn_miim_write(unit, 22, phy_id, phy_reg_addr, phy_wr_data);
    458 }
    459 
    460 int 
    461 soc_dcmn_miim_cl45_write(int unit, uint32 phy_id,
    462                    uint32 phy_reg_addr, uint16 phy_wr_data)
    463 {
    464     return soc_dcmn_miim_write(unit, 45, phy_id, phy_reg_addr, phy_wr_data);
    465 }
    466 
    467 
    468 
    469 /*
    470  * Function:
    471  *      soc_dcmn_miim_read
    472  * Purpose:
    473  *      Interface to read a value from a MIIM register.
    474  * Parameters:
    475  *      unit - StrataSwitch Unit #.
    476  *      phy_id - Phy ID to write (MIIM address)
    477  *      phy_reg_addr - PHY register to write
    478  *      phy_rd_data - Data read.
    479  * Returns:
    480  *      SOC_E_XXX
    481  */
    482 /*user defined function for external phy*/
    483 #ifdef USER_DEFINED_EXT_MDIO_FUNCTION
    484 extern int _user_defined_ext_mdio_read(int unit,  int clause, uint32 phy_id,
    485                   uint32 phy_reg_addr, uint16 *phy_rd_data);
    486 #endif 
    487 
    488 int
    489 soc_dcmn_miim_read(int unit, int clause, uint32 phy_id,
    490                   uint32 phy_reg_addr, uint16 *phy_rd_data)
    491 {
    492 #ifdef USER_DEFINED_EXT_MDIO_FUNCTION
    493     uint32 internal_select;
    494 #endif
    495  
    496 
    497 #ifdef USER_DEFINED_EXT_MDIO_FUNCTION
    498     internal_select = (phy_id & 0x80) ? 1 : 0;
    499     if (!internal_select) {
    500         return _user_defined_ext_mdio_read(unit, clause, phy_id, phy_reg_addr, phy_rd_data);
    501     }
    502 #endif 
    503 
    504 #ifdef BCM_CMICX_SUPPORT
    505     if (soc_feature(unit, soc_feature_cmicx)) {
    506         return soc_cmicx_miim_operation(unit, FALSE, clause, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, phy_id,
    507                         phy_reg_addr, phy_rd_data);
    508     } else
    509 #endif /* BCM_CMICX_SUPPORT */
    510 #if defined(BCM_CMICM_SUPPORT)
    511     if(soc_feature(unit, soc_feature_cmicm)) {
    512         return soc_dcmn_cmicm_miim_operation(unit, FALSE, clause, phy_id,
    513                           phy_reg_addr, phy_rd_data);
    514     } else 
    515 #endif
    516     {
    517         return soc_dcmn_miim_operation(unit, FALSE, clause, phy_id,
    518                           phy_reg_addr, phy_rd_data);
    519     }
    520 }
    521 
    522 
    523 int
    524 soc_dcmn_miim_cl22_read(int unit, uint32 phy_id,
    525                   uint32 phy_reg_addr, uint16 *phy_rd_data)
    526 {
    527     return soc_dcmn_miim_read(unit, 22, phy_id, phy_reg_addr, phy_rd_data);
    528 }
    529 
    530 int
    531 soc_dcmn_miim_cl45_read(int unit, uint32 phy_id,
    532                   uint32 phy_reg_addr, uint16 *phy_rd_data)
    533 {
    534     return soc_dcmn_miim_read(unit, 45, phy_id, phy_reg_addr, phy_rd_data);
    535 }
    536 
    537 #endif /*BCM_SAND_SUPPORT */
    538 
    539 
    540 
    541 #if defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT)
    542 /*
    543  */
    544 
    545 /*
    546  * Function:
    547  *      soc_rcpu_miim_write
    548  * Purpose:
    549  *      Write a value to a MIIM register throuth RCPU packets.
    550  * Parameters:
    551  *      unit - StrataSwitch Unit #.
    552  *      phy_id - Phy ID to write (MIIM address)
    553  *      phy_reg_addr - PHY register to write
    554  *      phy_wr_data - Data to write.
    555  * Returns:
    556  *      SOC_E_XXX
    557  * Notes:
    558  *      Temporarily disables auto link scan if it was enabled.  The MIIM
    559  *      registers are locked during the operation to prevent multiple
    560  *      tasks from trying to access PHY registers simultaneously.
    561  *      If remote interrupt packet is enabled for RCPU MIIM access, the register
    562  *      CMIC_INTR_PKT_PACING_DELAY should be programmed properly to allow
    563  *      continuous generation of interrupt packets.
    564  */
    565 int 
    566 soc_rcpu_miim_write(int unit, uint16 phy_id,
    567                uint8 phy_reg_addr, uint16 phy_wr_data)
    568 {
    569     int                 rv = SOC_E_NONE;
    570     int                 clause45;
    571     uint32              phy_param;
    572     int miim_intr_retry_cnt = MIIM_INTR_RETRY_COUNT;
    573 
    574     assert(!sal_int_context());
    575 
    576     LOG_VERBOSE(BSL_LS_SOC_MIIM,
    577              (BSL_META_U(unit,
    578                          "soc_rcpu_miim_write: id=0x%02x addr=0x%02x data=0x%04x\n"),
    579               phy_id, phy_reg_addr, phy_wr_data));
    580 
    581     if(!soc_feature(unit, soc_feature_cmicm)) {
    582         return SOC_E_UNAVAIL;
    583     }
    584 
    585     clause45 = soc_feature(unit, soc_feature_phy_cl45);
    586 
    587 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_CMICM_SUPPORT)
    588     /*
    589      * Trident Switch And Later
    590      * internal select bit 25
    591      * BUS_ID  bit 22-24
    592      * C45_SEL bit 21
    593      */
    594     if (SOC_IS_TD_TT(unit) || soc_feature(unit, soc_feature_cmicm)) {
    595 
    596         uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
    597 
    598         /* set 5-bit PHY MDIO address */
    599         phy_param = (uint32)phy_wr_data |
    600                     (((uint32)phy_id & 0x1f) << MIIM_PARAM_ID_OFFSET);
    601 
    602         /* select internal MDIO bus if set */
    603         if (phy_id & 0x80) { /* Internal/External select */
    604 #if defined(BCM_CMICDV3_SUPPORT)
    605             /*
    606              * Apache and Tomahawk2 Switches And Later
    607              * internal select bit 26
    608              * BUS_ID  bit 22-25
    609              * C45_SEL bit 21
    610              * See CMIC_CMC0_MIIM_PARAM register.
    611              */
    612             if (soc_feature(unit, soc_feature_cmicd_v3)) {
    613                 phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 10));
    614             } else
    615 #endif /* BCM_CMICDV3_SUPPORT */
    616             {
    617                 phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 9));
    618             }
    619         }
    620 
    621         /* set MDIO bus number */
    622         phy_param |= (bus_sel << (MIIM_PARAM_ID_OFFSET + 6));
    623     } else
    624 #endif
    625 
    626 #ifdef BCM_TRX_SUPPORT
    627     
    628     if (SOC_IS_TRX(unit)) {
    629         int bus_sel = (phy_id & 0x60) >> 5;
    630     
    631         phy_param = (uint32)phy_wr_data |
    632                     (((uint32)phy_id & 0x1f) << MIIM_PARAM_ID_OFFSET);
    633 
    634         if (phy_id & 0x80) { /* Internal/External select */
    635             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 7));
    636         }
    637         if (bus_sel == 1) {
    638             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 6));
    639         } else if (bus_sel == 2) {
    640             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 8));
    641         }
    642     } else
    643 #endif /* BCM_TRX_SUPPORT */
    644     {
    645         phy_param = ((uint32)phy_id << MIIM_PARAM_ID_OFFSET |
    646                      (uint32)phy_wr_data);
    647     }
    648 
    649     /* Pause link scanning - and hold MIIM lock */
    650     if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
    651        soc_linkscan_pause(unit);
    652     }
    653     MIIM_LOCK(unit);
    654 
    655     /* Write parameter register and tell CMIC to start */
    656 
    657     /* Clause 45 support changes Clause 22 access method */
    658     if (clause45) {
    659         soc_pci_write(unit, CMIC_RPE_MIIM_ADDRESS_OFFSET, phy_reg_addr);
    660     } else {
    661         phy_param |= (uint32)phy_reg_addr << MIIM_PARAM_REG_ADDR_OFFSET;
    662     }
    663 
    664     soc_pci_write(unit, CMIC_RPE_MIIM_PARAM_OFFSET, phy_param);
    665     soc_pci_write(unit, CMIC_RPE_MIIM_CTRL_OFFSET, 1);
    666 
    667     /* Wait for completion using either the interrupt or polling method */
    668     if (SOC_CONTROL(unit)->miimIntrEnb) {
    669         soc_cmicm_rcpu_intr0_enable(unit, IRQ_RCPU_MIIM_OP_DONE);
    670 
    671         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
    672                          SOC_CONTROL(unit)->miimTimeout) != 0) {
    673             if ((soc_pci_read(unit, CMIC_RPE_MIIM_STAT_OFFSET) &
    674                                     CMIC_MIIM_OPN_DONE) == 0) {
    675                 /* MIIM HW operation not complete */
    676                 rv = SOC_E_TIMEOUT;
    677             } else {
    678                 /* MIIM HW operation complete but no intr received yet
    679                  * Retry for MIIM Intr for busy system
    680                  * before declaring timeout */
    681                 rv = SOC_E_TIMEOUT;
    682                 while (miim_intr_retry_cnt) {
    683                     if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
    684                                      MIIM_INTR_RETRY_TIMEOUT) == 0) {
    685                         rv = SOC_E_NONE;
    686                         break;
    687                     }
    688                     miim_intr_retry_cnt--;
    689                 }
    690             }
    691         } else {
    692             LOG_DEBUG(BSL_LS_SOC_MIIM,
    693                         (BSL_META_U(unit,
    694                                     "  Interrupt received\n")));
    695         }
    696 
    697         soc_cmicm_rcpu_intr0_disable(unit, IRQ_RCPU_MIIM_OP_DONE);
    698     } else {
    699         soc_timeout_t to;
    700 
    701         soc_timeout_init(&to, SOC_CONTROL(unit)->miimTimeout, 250);
    702 
    703         while ((soc_pci_read(unit, CMIC_RPE_MIIM_STAT_OFFSET) &
    704                                    CMIC_MIIM_OPN_DONE) == 0) {
    705             if (soc_timeout_check(&to)) {
    706                 rv = SOC_E_TIMEOUT;
    707                 break;
    708             }
    709         }
    710 
    711         if (rv == SOC_E_NONE) {
    712             LOG_DEBUG(BSL_LS_SOC_MIIM,
    713                         (BSL_META_U(unit,
    714                                     "  Done in %d polls\n"), to.polls));
    715         }
    716 
    717         soc_pci_write(unit, CMIC_RPE_MIIM_CTRL_OFFSET, 0);
    718     }
    719     if (rv == SOC_E_TIMEOUT) {
    720         LOG_ERROR(BSL_LS_SOC_COMMON,
    721                   (BSL_META_U(unit,
    722                               "MiimTimeOut:soc_rcpu_miim_write, "
    723                               "timeout (id=0x%02x addr=0x%02x data=0x%04x)\n"),
    724                    phy_id, phy_reg_addr, phy_wr_data));
    725         SOC_CONTROL(unit)->stat.err_mii_tmo++;
    726     }
    727 
    728     /* Release linkscan pause and MIIM lock */
    729 
    730     MIIM_UNLOCK(unit);
    731 
    732     if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
    733        soc_linkscan_continue(unit);
    734     }
    735 
    736     return rv;
    737 
    738 }
    739 /*
    740  * Function:
    741  *      soc_rcpu_miim_read
    742  * Purpose:
    743  *      Read a value from an MII register.
    744  * Parameters:
    745  *      unit - StrataSwitch Unit #.
    746  *      phy_id - Phy ID to write (MIIM address)
    747  *      phy_reg_addr - PHY register to write
    748  *      phy_rd_data - 16bit data to write into
    749  * Returns:
    750  *      SOC_E_XXX
    751  * Notes:
    752  *      Temporarily disables auto link scan if it was enabled.  The MIIM
    753  *      registers are locked during the operation to prevent multiple
    754  *      tasks from trying to access PHY registers simultaneously.
    755  *      If remote interrupt packet is enabled for RCPU MIIM access, the register
    756  *      CMIC_INTR_PKT_PACING_DELAY should be programmed properly to allow
    757  *      continuous generation of interrupt packets. 
    758  */
    759 
    760 int
    761 soc_rcpu_miim_read(int unit, uint16 phy_id,
    762               uint8 phy_reg_addr, uint16 *phy_rd_data)
    763 {
    764     int                 rv = SOC_E_NONE;
    765     int                 clause45;
    766     uint32              phy_param;
    767     int miim_intr_retry_cnt = MIIM_INTR_RETRY_COUNT;
    768 
    769     assert(!sal_int_context());
    770     assert(phy_rd_data);
    771 
    772     LOG_VERBOSE(BSL_LS_SOC_MIIM,
    773              (BSL_META_U(unit,
    774                          "soc_rcpu_miim_read: id=0x%02x addr=0x%02x  "),
    775               phy_id, phy_reg_addr));
    776 
    777     if(!soc_feature(unit, soc_feature_cmicm)) {
    778         return SOC_E_UNAVAIL;
    779     }
    780 
    781 
    782     clause45 = soc_feature(unit, soc_feature_phy_cl45);
    783 
    784     /* 
    785      * Trident Switch And Katana
    786      * internal select bit 25
    787      * BUS_ID  bit 22-24
    788      * C45_SEL bit 21
    789      */
    790     if (SOC_IS_TD_TT(unit) || SOC_IS_KATANA(unit) || SOC_IS_TRIUMPH3(unit)) {
    791         
    792         uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
    793         
    794         /* set 5-bit PHY MDIO address */ 
    795         phy_param = (((uint32)phy_id & 0x1f) << MIIM_PARAM_ID_OFFSET);
    796 
    797         /* select internal MDIO bus if set */
    798         if (phy_id & 0x80) { /* Internal/External select */
    799 #if defined(BCM_CMICDV3_SUPPORT)
    800             /*
    801              * Apache and Tomahawk2 Switches And Later
    802              * internal select bit 26
    803              * BUS_ID  bit 22-25
    804              * C45_SEL bit 21
    805              * See CMIC_CMC0_MIIM_PARAM register.
    806              */
    807             if (soc_feature(unit, soc_feature_cmicd_v3)) {
    808                 phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 10));
    809             } else
    810 #endif /* BCM_CMICDV3_SUPPORT */
    811             {
    812                 phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 9));
    813             }
    814         }
    815   
    816         /* set MDIO bus number */
    817         phy_param |= (bus_sel << (MIIM_PARAM_ID_OFFSET + 6));
    818     } else 
    819 #ifdef BCM_TRX_SUPPORT
    820     
    821     if (SOC_IS_TRX(unit)) {
    822         int bus_sel = (phy_id & 0x60) >> 5;
    823 
    824         phy_param = (((uint32)phy_id & 0x1f) << MIIM_PARAM_ID_OFFSET);
    825 
    826         if (phy_id & 0x80) { /* Internal/External select */
    827             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 7));
    828         }
    829         if (bus_sel == 1) {
    830             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 6));
    831         } else if (bus_sel == 2) {
    832             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 8));
    833         }
    834     } else
    835 #endif /* BCM_TRX_SUPPORT */
    836     {
    837         phy_param = (uint32)phy_id << MIIM_PARAM_ID_OFFSET;
    838     }
    839 
    840     /* Pause link scanning - and hold MIIM lock */
    841     if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
    842        soc_linkscan_pause(unit);
    843     }
    844     MIIM_LOCK(unit);
    845 
    846     /* Write parameter register and tell CMIC to start */
    847 
    848     /* Clause 45 support changes Clause 22 access method */
    849     if (clause45) {
    850         soc_pci_write(unit, CMIC_RPE_MIIM_ADDRESS_OFFSET, phy_reg_addr);
    851     } else {
    852         phy_param |= (uint32)phy_reg_addr << MIIM_PARAM_REG_ADDR_OFFSET;
    853     }
    854 
    855     soc_pci_write(unit, CMIC_RPE_MIIM_PARAM_OFFSET, phy_param);
    856     soc_pci_write(unit, CMIC_RPE_MIIM_CTRL_OFFSET, 2);
    857 
    858     /* Wait for completion using either the interrupt or polling method */
    859     if (SOC_CONTROL(unit)->miimIntrEnb) {
    860         soc_cmicm_rcpu_intr0_enable(unit, IRQ_RCPU_MIIM_OP_DONE);
    861 
    862         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
    863                          SOC_CONTROL(unit)->miimTimeout) != 0) {
    864             if ((soc_pci_read(unit, CMIC_RPE_MIIM_STAT_OFFSET) &
    865                                     CMIC_MIIM_OPN_DONE) == 0) {
    866                 /* MIIM HW operation not complete */
    867                 rv = SOC_E_TIMEOUT;
    868             } else {
    869                 /* MIIM HW operation complete but no intr received yet
    870                  * Retry for MIIM Intr for busy system
    871                  * before declaring timeout */
    872                 rv = SOC_E_TIMEOUT;
    873                 while (miim_intr_retry_cnt) {
    874                     if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
    875                                      MIIM_INTR_RETRY_TIMEOUT) == 0) {
    876                         rv = SOC_E_NONE;
    877                         break;
    878                     }
    879                     miim_intr_retry_cnt--;
    880                 }
    881             }
    882         } else {
    883             LOG_DEBUG(BSL_LS_SOC_MIIM,
    884                         (BSL_META_U(unit,
    885                                     "  Interrupt received\n")));
    886         }
    887 
    888         soc_cmicm_rcpu_intr0_disable(unit, IRQ_RCPU_MIIM_OP_DONE);
    889     } else {
    890         soc_timeout_t to;
    891 
    892         soc_timeout_init(&to, SOC_CONTROL(unit)->miimTimeout, 250);
    893 
    894         while ((soc_pci_read(unit, CMIC_RPE_MIIM_STAT_OFFSET) &
    895                                      CMIC_MIIM_OPN_DONE) == 0) {
    896             if (soc_timeout_check(&to)) {
    897                 rv = SOC_E_TIMEOUT;
    898                 break;
    899             }
    900         }
    901 
    902         if (rv == SOC_E_NONE) {
    903             LOG_DEBUG(BSL_LS_SOC_MIIM,
    904                         (BSL_META_U(unit,
    905                                     "  Done in %d polls\n"), to.polls));
    906         }
    907 
    908         soc_pci_write(unit, CMIC_RPE_MIIM_CTRL_OFFSET, 0);
    909     }
    910 
    911     if (rv == SOC_E_TIMEOUT) {
    912         LOG_ERROR(BSL_LS_SOC_COMMON,
    913                   (BSL_META_U(unit,
    914                               "MiimTimeOut:soc_rcpu_miim_read, "
    915                               "timeout (id=0x%02x addr=0x%02x)\n"),
    916                    phy_id, phy_reg_addr));
    917         SOC_CONTROL(unit)->stat.err_mii_tmo++;
    918     } else {
    919         *phy_rd_data = (uint16)soc_pci_read(unit, CMIC_RPE_MIIM_READ_DATA_OFFSET);
    920 
    921         LOG_VERBOSE(BSL_LS_SOC_MIIM,
    922                  (BSL_META_U(unit,
    923                              "data=0x%04x\n"), *phy_rd_data));
    924     }
    925 
    926     /* Release linkscan pause and MIIM lock */
    927 
    928     MIIM_UNLOCK(unit);
    929 
    930     if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
    931        soc_linkscan_continue(unit);
    932     }
    933 
    934     return rv;
    935 
    936 }
    937 /*
    938  * Function:
    939  *      soc_rcpu_miimc45_write
    940  * Purpose:
    941  *      Write a value to a MIIM register.
    942  * Parameters:
    943  *      unit - StrataSwitch Unit #.
    944  *      phy_id - Phy ID to write (MIIM address)
    945  *      phy_devad - Device type (PMA/PMD, PCS, PHY XS)
    946  *      phy_reg_addr - PHY register to write
    947  *      phy_wr_data - Data to write.
    948  * Returns:
    949  *      SOC_E_XXX
    950  * Notes:
    951  *      Temporarily disables auto link scan if it was enabled.  The MIIM
    952  *      registers are locked during the operation to prevent multiple
    953  *      tasks from trying to access PHY registers simultaneously.
    954  *      If remote interrupt packet is enabled for RCPU MIIM access, the register
    955  *      CMIC_INTR_PKT_PACING_DELAY should be programmed properly to allow
    956  *      continuous generation of interrupt packets.
    957  */
    958 
    959 int 
    960 soc_rcpu_miimc45_write(int unit, uint16 phy_id, uint8 phy_devad,
    961                   uint16 phy_reg_addr, uint16 phy_wr_data)
    962 {
    963     int                 rv = SOC_E_NONE;
    964     uint32              phy_param;
    965     uint32              phy_miim_addr;
    966     int miim_intr_retry_cnt = MIIM_INTR_RETRY_COUNT;
    967 
    968     assert(!sal_int_context());
    969 
    970     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)) {
    971         return SOC_E_NONE;
    972     }
    973 
    974     LOG_VERBOSE(BSL_LS_SOC_MIIM,
    975              (BSL_META_U(unit,
    976                          "soc_miimc45_write: id=0x%02x phy_devad=0x%02x "
    977                          "addr=0x%02x data=0x%04x\n"),
    978               phy_id, phy_devad, phy_reg_addr, phy_wr_data));
    979 
    980     if (!soc_feature(unit, soc_feature_phy_cl45) ||
    981         !soc_feature(unit, soc_feature_cmicm)) {
    982         return SOC_E_UNAVAIL;
    983     }
    984 
    985     /* Pause link scanning - and hold MIIM lock */
    986     if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
    987        soc_linkscan_pause(unit);
    988     }
    989     MIIM_LOCK(unit);
    990 
    991     /* Write parameter registers and tell CMIC to start */
    992     phy_param = 0;
    993     soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param,
    994                            MIIM_CYCLEf, MIIM_CYCLE_AUTO);
    995     if (phy_id & 0x80) {
    996         phy_id &= (~0x80);
    997             soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr,
    998                               &phy_param, INTERNAL_SELf, 1);
    999     }
   1000 
   1001     if (soc_feature(unit, soc_feature_mdio_enhanced)) {
   1002         soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param, C45_SELf, 1);
   1003 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_CMICM_SUPPORT)
   1004         if (SOC_IS_TD_TT(unit) || soc_feature(unit, soc_feature_cmicm)) {
   1005             uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
   1006             soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param,
   1007                               BUS_IDf, bus_sel);
   1008             phy_id &= ~(PHY_ID_BUS_UPPER_MASK | PHY_ID_BUS_LOWER_MASK);
   1009         } else
   1010 #endif
   1011 #if defined(BCM_TRX_SUPPORT)
   1012         if (SOC_IS_TRX(unit)) {
   1013             soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param, 
   1014                               BUS0_1_SELf, ((phy_id & 0x20) ? 1 : 0));
   1015             phy_id &= (~0x20);
   1016 
   1017             soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param, 
   1018                               BUS2_SELf, ((phy_id & 0x40) ? 1 : 0));
   1019             phy_id &= (~0x40);
   1020         } else 
   1021 #endif /* BCM_TRX_SUPPORT */
   1022         {
   1023             soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param, HG_SELf,
   1024                               ((phy_id & 0x40) ? 1 : 0));
   1025             phy_id &= (~0x40);
   1026         }
   1027     }
   1028 
   1029     soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param, PHY_IDf, phy_id);
   1030     soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param,
   1031                       PHY_DATAf, phy_wr_data);
   1032     phy_miim_addr = 0;
   1033     soc_reg_field_set(unit, CMIC_RPE_MIIM_ADDRESSr, &phy_miim_addr,
   1034                       CLAUSE_45_DTYPEf, phy_devad);
   1035     soc_reg_field_set(unit, CMIC_RPE_MIIM_ADDRESSr, &phy_miim_addr,
   1036                       CLAUSE_45_REGADRf, phy_reg_addr);
   1037 
   1038     soc_pci_write(unit, CMIC_RPE_MIIM_ADDRESS_OFFSET, phy_miim_addr);
   1039     soc_pci_write(unit, CMIC_RPE_MIIM_PARAM_OFFSET, phy_param);
   1040     soc_pci_write(unit, CMIC_RPE_MIIM_CTRL_OFFSET, 1);
   1041 
   1042     /* Wait for completion using either the interrupt or polling method */
   1043     if (SOC_CONTROL(unit)->miimIntrEnb) {
   1044         soc_cmicm_rcpu_intr0_enable(unit, IRQ_RCPU_MIIM_OP_DONE);
   1045 
   1046         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   1047                          SOC_CONTROL(unit)->miimTimeout) != 0) {
   1048             if ((soc_pci_read(unit, CMIC_RPE_MIIM_STAT_OFFSET) &
   1049                                     CMIC_MIIM_OPN_DONE) == 0) {
   1050                 /* MIIM HW operation not complete */
   1051                 rv = SOC_E_TIMEOUT;
   1052             } else {
   1053                 /* MIIM HW operation complete but no intr received yet
   1054                  * Retry for MIIM Intr for busy system
   1055                  * before declaring timeout */
   1056                 rv = SOC_E_TIMEOUT;
   1057                 while (miim_intr_retry_cnt) {
   1058                     if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   1059                                      MIIM_INTR_RETRY_TIMEOUT) == 0) {
   1060                         rv = SOC_E_NONE;
   1061                         break;
   1062                     }
   1063                     miim_intr_retry_cnt--;
   1064                 }
   1065             }
   1066         } else {
   1067             LOG_DEBUG(BSL_LS_SOC_MIIM,
   1068                         (BSL_META_U(unit,
   1069                                     "  Interrupt received\n")));
   1070         }
   1071 
   1072         soc_cmicm_rcpu_intr0_disable(unit, IRQ_RCPU_MIIM_OP_DONE);
   1073     } else {
   1074         soc_timeout_t to;
   1075 
   1076         soc_timeout_init(&to, SOC_CONTROL(unit)->miimTimeout, 250);
   1077 
   1078         while ((soc_pci_read(unit, CMIC_RPE_MIIM_STAT_OFFSET) &
   1079                                    CMIC_MIIM_OPN_DONE) == 0) {
   1080             if (soc_timeout_check(&to)) {
   1081                 rv = SOC_E_TIMEOUT;
   1082                 break;
   1083             }
   1084         }
   1085 
   1086         if (rv == SOC_E_NONE) {
   1087             LOG_DEBUG(BSL_LS_SOC_MIIM,
   1088                         (BSL_META_U(unit,
   1089                                     "  Done in %d polls\n"), to.polls));
   1090         }
   1091 
   1092         soc_pci_write(unit, CMIC_RPE_MIIM_CTRL_OFFSET, 0);
   1093     }
   1094 
   1095     if (rv == SOC_E_TIMEOUT) {
   1096         LOG_ERROR(BSL_LS_SOC_COMMON,
   1097                   (BSL_META_U(unit,
   1098                               "MiimTimeOut:soc_miimc45_write, "
   1099                               "timeout (id=0x%02x addr=0x%02x data=0x%04x)\n"),
   1100                    phy_id, phy_reg_addr, phy_wr_data));
   1101         SOC_CONTROL(unit)->stat.err_mii_tmo++;
   1102     }
   1103 
   1104     /* Release linkscan pause and MIIM lock */
   1105     MIIM_UNLOCK(unit);
   1106 
   1107     if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
   1108        soc_linkscan_continue(unit);
   1109     }
   1110 
   1111     return rv;
   1112 
   1113 }
   1114 /*
   1115  * Function:
   1116  *      soc_rcpu_miimc45_read
   1117  * Purpose:
   1118  *      Read a value from an MII register.
   1119  * Parameters:
   1120  *      unit - StrataSwitch Unit #.
   1121  *      phy_id - Phy ID to write (MIIM address)
   1122  *      phy_devad - Device type (PMA/PMD, PCS, PHY XS)
   1123  *      phy_reg_addr - PHY register to write
   1124  *      phy_rd_data - 16bit data to write into
   1125  * Returns:
   1126  *      SOC_E_XXX
   1127  * Notes:
   1128  *      Temporarily disables auto link scan if it was enabled.  The MIIM
   1129  *      registers are locked during the operation to prevent multiple
   1130  *      tasks from trying to access PHY registers simultaneously.
   1131  *      If remote interrupt packet is enabled for RCPU MIIM access, the register
   1132  *      CMIC_INTR_PKT_PACING_DELAY should be programmed properly to allow
   1133  *      continuous generation of interrupt packets.
   1134  */
   1135 
   1136 int
   1137 soc_rcpu_miimc45_read(int unit, uint16 phy_id, uint8 phy_devad,
   1138                  uint16 phy_reg_addr, uint16 *phy_rd_data)
   1139 {
   1140     int                 rv = SOC_E_NONE;    
   1141     uint32              phy_param, phy_miim_addr;
   1142     int miim_intr_retry_cnt = MIIM_INTR_RETRY_COUNT;
   1143 
   1144     assert(!sal_int_context());
   1145     assert(phy_rd_data);
   1146 
   1147     LOG_VERBOSE(BSL_LS_SOC_MIIM,
   1148              (BSL_META_U(unit,
   1149                          "soc_rcpu_miimc45_read: id=0x%02x "
   1150                          "phy_devad=0x%02x addr=0x%02x\n"),
   1151               phy_id, phy_devad, phy_reg_addr));
   1152 
   1153     if (!soc_feature(unit, soc_feature_cmicm)|| 
   1154         !soc_feature(unit, soc_feature_phy_cl45)) {
   1155         return SOC_E_UNAVAIL;
   1156     }
   1157 
   1158     /* Pause link scanning - and hold MIIM lock */
   1159     if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
   1160        soc_linkscan_pause(unit);
   1161     }
   1162     MIIM_LOCK(unit);
   1163 
   1164     /* Write parameter registers and tell CMIC to start */
   1165     phy_param = 0;
   1166 
   1167     soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param,
   1168                             MIIM_CYCLEf, MIIM_CYCLE_AUTO);
   1169 
   1170     if (phy_id & 0x80) {
   1171         phy_id &= (~0x80);
   1172         soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr,
   1173                           &phy_param, INTERNAL_SELf, 1);
   1174 
   1175         if (soc_feature(unit, soc_feature_mdio_enhanced)) {
   1176             soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr,
   1177                               &phy_param, C45_SELf, 1);
   1178 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_CMICM_SUPPORT)
   1179             if (SOC_IS_TD_TT(unit) || soc_feature(unit, soc_feature_cmicm)) {
   1180                 uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
   1181                 soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param,
   1182                                   BUS_IDf, bus_sel);
   1183                 phy_id &= ~(PHY_ID_BUS_UPPER_MASK | PHY_ID_BUS_LOWER_MASK);
   1184             } else
   1185 #endif
   1186 #if defined(BCM_TRX_SUPPORT)
   1187             if (SOC_IS_TRX(unit)) {
   1188                 soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param,
   1189                                   BUS0_1_SELf, ((phy_id & 0x20) ? 1 : 0));
   1190                 phy_id &= (~0x20);
   1191 
   1192                 soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param,
   1193                                   BUS2_SELf, ((phy_id & 0x40) ? 1 : 0));
   1194                 phy_id &= (~0x40);
   1195             } else
   1196 #endif
   1197             {
   1198                 soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param, HG_SELf,
   1199                                   ((phy_id & 0x40) ? 1 : 0));
   1200                 phy_id &= (~0x40);
   1201             }
   1202         }
   1203 
   1204         soc_reg_field_set(unit, CMIC_RPE_MIIM_PARAMr, &phy_param, PHY_IDf, phy_id);
   1205         phy_miim_addr = 0;
   1206         soc_reg_field_set(unit, CMIC_RPE_MIIM_ADDRESSr, &phy_miim_addr,
   1207                           CLAUSE_45_DTYPEf, phy_devad);
   1208         soc_reg_field_set(unit, CMIC_RPE_MIIM_ADDRESSr, &phy_miim_addr,
   1209                           CLAUSE_45_REGADRf, phy_reg_addr);
   1210 
   1211         soc_pci_write(unit, CMIC_RPE_MIIM_ADDRESS_OFFSET, phy_miim_addr);
   1212         soc_pci_write(unit, CMIC_RPE_MIIM_PARAM_OFFSET, phy_param);
   1213         soc_pci_write(unit, CMIC_RPE_MIIM_CTRL_OFFSET, 2);
   1214 
   1215         /* Wait for completion using either the interrupt or polling method */
   1216         if (SOC_CONTROL(unit)->miimIntrEnb) {
   1217             soc_cmicm_rcpu_intr0_enable(unit, IRQ_RCPU_MIIM_OP_DONE);
   1218             if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   1219                              SOC_CONTROL(unit)->miimTimeout) != 0) {
   1220                 if ((soc_pci_read(unit, CMIC_RPE_MIIM_STAT_OFFSET) &
   1221                                         CMIC_MIIM_OPN_DONE) == 0) {
   1222                     /* MIIM HW operation not complete */
   1223                     rv = SOC_E_TIMEOUT;
   1224                 } else {
   1225                     /* MIIM HW operation complete but no intr received yet
   1226                      * Retry for MIIM Intr for busy system
   1227                      * before declaring timeout */
   1228                     rv = SOC_E_TIMEOUT;
   1229                     while (miim_intr_retry_cnt) {
   1230                         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   1231                                          MIIM_INTR_RETRY_TIMEOUT) == 0) {
   1232                             rv = SOC_E_NONE;
   1233                             break;
   1234                         }
   1235                         miim_intr_retry_cnt--;
   1236                     }
   1237                 }
   1238             } else {
   1239                 LOG_DEBUG(BSL_LS_SOC_MIIM,
   1240                             (BSL_META_U(unit,
   1241                                         "  Interrupt received\n")));
   1242             }
   1243 
   1244             soc_cmicm_rcpu_intr0_disable(unit, IRQ_RCPU_MIIM_OP_DONE);
   1245         } else {
   1246             soc_timeout_t to;
   1247 
   1248             soc_timeout_init(&to, SOC_CONTROL(unit)->miimTimeout, 250);
   1249 
   1250             while ((soc_pci_read(unit, CMIC_RPE_MIIM_STAT_OFFSET) &
   1251                                          CMIC_MIIM_OPN_DONE) == 0) {
   1252                 if (soc_timeout_check(&to)) {
   1253                     rv = SOC_E_TIMEOUT;
   1254                     break;
   1255                 }
   1256             }
   1257 
   1258             if (rv == SOC_E_NONE) {
   1259                 LOG_DEBUG(BSL_LS_SOC_MIIM,
   1260                             (BSL_META_U(unit,
   1261                                         "  Done in %d polls\n"), to.polls));
   1262             }
   1263 
   1264             soc_pci_write(unit, CMIC_RPE_MIIM_CTRL_OFFSET, 0);
   1265         }
   1266 
   1267         if (rv == SOC_E_TIMEOUT) {
   1268             LOG_ERROR(BSL_LS_SOC_COMMON,
   1269                       (BSL_META_U(unit,
   1270                                   "MiimTimeOut:soc_rcpu_miimc45_read, "
   1271                                   "timeout (id=0x%02x addr=0x%02x)\n"),
   1272                        phy_id, phy_reg_addr));
   1273             SOC_CONTROL(unit)->stat.err_mii_tmo++;
   1274         } else {
   1275             *phy_rd_data = (uint16)soc_pci_read(unit, CMIC_RPE_MIIM_READ_DATA_OFFSET);
   1276 
   1277             LOG_VERBOSE(BSL_LS_SOC_MIIM,
   1278                      (BSL_META_U(unit,
   1279                                  "soc_rcpu_miimc45_read: read data=0x%04x\n"), *phy_rd_data));
   1280         }
   1281 
   1282         /* Release linkscan pause and MIIM lock */
   1283         MIIM_UNLOCK(unit);
   1284 
   1285         if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
   1286            soc_linkscan_continue(unit);
   1287         }
   1288     }
   1289 
   1290     return rv;
   1291 
   1292 }
   1293 #endif /* defined(BCM_RCPU_SUPPORT) && defined(BCM_CMICM_SUPPORT) */
   1294 
   1295 /*
   1296  * Function:
   1297  *      soc_esw_miim_write
   1298  * Purpose:
   1299  *      New interface to write a value to a MIIM register.
   1300  * Parameters:
   1301  *      unit - StrataSwitch Unit #.
   1302  *      phy_id - Phy ID to write (MIIM address)
   1303  *      phy_reg_addr - PHY register to write
   1304  *      phy_wr_data - Data to write.
   1305  * Returns:
   1306  *      SOC_E_XXX
   1307  * Notes:
   1308  * Added to have the same interface for PHY register access among 
   1309  * ESW
   1310  */
   1311 int 
   1312 soc_esw_miim_write(int unit, uint32 phy_id,
   1313                    uint32 phy_reg_addr, uint16 phy_wr_data)
   1314 {
   1315     return soc_miim_write(unit, (uint16)phy_id,
   1316                           (uint16)phy_reg_addr, phy_wr_data);
   1317 }
   1318 
   1319 /*
   1320  * Function:
   1321  *      soc_esw_miim_read
   1322  * Purpose:
   1323  *      New interface to read a value from a MIIM register.
   1324  * Parameters:
   1325  *      unit - StrataSwitch Unit #.
   1326  *      phy_id - Phy ID to write (MIIM address)
   1327  *      phy_reg_addr - PHY register to write
   1328  *      phy_rd_data - Data read.
   1329  * Returns:
   1330  *      SOC_E_XXX
   1331  * Notes:
   1332  * Added to have the same interface for PHY register access among 
   1333  * ESW
   1334  */
   1335 int
   1336 soc_esw_miim_read(int unit, uint32 phy_id,
   1337                   uint32 phy_reg_addr, uint16 *phy_rd_data)
   1338 {
   1339     return soc_miim_read(unit, (uint16)phy_id, 
   1340                          (uint16)phy_reg_addr, phy_rd_data);
   1341 }
   1342 
   1343 /*
   1344  * Function:
   1345  *      soc_miim_modify
   1346  * Purpose:
   1347  *      Modify a value from an MII register.
   1348  * Parameters:
   1349  *      unit - StrataSwitch Unit #.
   1350  *      phy_id - Phy ID to write (MIIM address)
   1351  *      phy_reg_addr - PHY register to write
   1352  *      phy_rd_data - 16bit data to write into
   1353  *      phy_rd_mask - 16bit mask to indicate the bits to modify.
   1354  * Returns:
   1355  *      SOC_E_XXX
   1356  * Notes:
   1357  */
   1358 
   1359 int
   1360 soc_miim_modify(int unit, uint16 phy_id, uint16 phy_reg_addr, 
   1361                 uint16 phy_rd_data, uint16 phy_rd_mask)
   1362 {
   1363     uint16  tmp, otmp;
   1364 
   1365     phy_rd_data = phy_rd_data & phy_rd_mask;
   1366 
   1367     SOC_IF_ERROR_RETURN
   1368         (soc_miim_read(unit, phy_id, phy_reg_addr, &tmp));
   1369     otmp = tmp;
   1370     tmp &= ~(phy_rd_mask);
   1371     tmp |= phy_rd_data;
   1372 
   1373     if (otmp != tmp) {
   1374         SOC_IF_ERROR_RETURN
   1375             (soc_miim_write(unit, phy_id, phy_reg_addr, tmp));
   1376     }
   1377     return SOC_E_NONE;
   1378 }
   1379 
   1380 /*
   1381  * Function:
   1382  *      soc_esw_miimc45_write
   1383  * Purpose:
   1384  *      Write a value from an MII register.
   1385  * Parameters:
   1386  *      unit - StrataSwitch Unit #.
   1387  *      phy_id - Phy ID to write (MIIM address)
   1388  *      phy_reg_addr - PHY register to write (Encoded with PMA/PMD, PCS, PHY XS)
   1389  *      phy_rd_data - 16bit data to write into
   1390  * Returns:
   1391  *      SOC_E_XXX
   1392  * Notes:
   1393  */
   1394 int
   1395 soc_esw_miimc45_write(int unit, uint32 phy_id,
   1396                      uint32 phy_reg_addr, uint16 phy_wr_data)
   1397 {
   1398     uint8  dev_addr;
   1399     uint16 reg_addr;
   1400 
   1401     dev_addr = SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr);
   1402     reg_addr = SOC_PHY_CLAUSE45_REGAD(phy_reg_addr);
   1403  
   1404     return soc_miimc45_write(unit, (uint16)phy_id, dev_addr,
   1405                             reg_addr, phy_wr_data);
   1406 }
   1407 
   1408 /*
   1409  * Function:
   1410  *      soc_esw_miimc45_write
   1411  * Purpose:
   1412  *      Write a value from an MII register.
   1413  * Parameters:
   1414  *      unit - StrataSwitch Unit #.
   1415  *      phy_id - Phy ID to write (MIIM address)
   1416  *      phy_reg_addr - PHY register to write (Encoded with PMA/PMD, PCS, PHY XS)
   1417  *      phy_rd_data - 16bit data to write into
   1418  * Returns:
   1419  *      SOC_E_XXX
   1420  * Notes:
   1421  */
   1422 int
   1423 soc_esw_miimc45_read(int unit, uint32 phy_id,
   1424                     uint32 phy_reg_addr, uint16 *phy_rd_data)
   1425 {
   1426     uint8  dev_addr;
   1427     uint16 reg_addr;
   1428 
   1429     dev_addr   = SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr);
   1430     reg_addr   = SOC_PHY_CLAUSE45_REGAD(phy_reg_addr);
   1431  
   1432     return soc_miimc45_read(unit, (uint16)phy_id, dev_addr,
   1433                           reg_addr, phy_rd_data);
   1434 }
   1435 
   1436 /*
   1437  * Function:
   1438  *      soc_esw_miimc45_data_write
   1439  * Purpose:
   1440  *      Write a value to the present MII register without a address cycle.
   1441  * Parameters:
   1442  *      unit - StrataSwitch Unit #.
   1443  *      phy_id - Phy ID to write (MIIM address)
   1444  *      phy_devad - Device type (PMA/PMD, PCS, PHY XS)
   1445  *      phy_wr_data - 16 bit data for write
   1446  * Returns:
   1447  *      SOC_E_XXX
   1448  * Notes:
   1449  */
   1450 int
   1451 soc_esw_miimc45_data_write(int unit, uint32 phy_id,
   1452                            uint8 phy_devad, uint16 phy_wr_data)
   1453 {
   1454     uint8  dev_addr;
   1455     uint16 reg_addr;
   1456 
   1457     dev_addr = (phy_devad & ~MIIM_CYCLE_C45_MASK) | MIIM_CYCLE_C45_WR;
   1458     reg_addr = 0;
   1459 
   1460     return soc_miimc45_write(unit, (uint16)phy_id, dev_addr,
   1461                              reg_addr, phy_wr_data);
   1462 }
   1463 
   1464 /*
   1465  * Function:
   1466  *      soc_esw_miimc45_data_read
   1467  * Purpose:
   1468  *      Read a value from the present MII register without a address cycle.
   1469  * Parameters:
   1470  *      unit - StrataSwitch Unit #.
   1471  *      phy_id - Phy ID to write (MIIM address)
   1472  *      phy_devad - Device type (PMA/PMD, PCS, PHY XS)
   1473  *      phy_rd_data - point to 16 bit data buffer
   1474  * Returns:
   1475  *      SOC_E_XXX
   1476  * Notes:
   1477  */
   1478 int
   1479 soc_esw_miimc45_data_read(int unit, uint32 phy_id,
   1480                           uint8 phy_devad, uint16 *phy_rd_data)
   1481 {
   1482     uint8  dev_addr;
   1483     uint16 reg_addr;
   1484 
   1485     dev_addr = (phy_devad & ~MIIM_CYCLE_C45_MASK) | MIIM_CYCLE_C45_RD;
   1486     reg_addr = 0;
   1487 
   1488     return soc_miimc45_read(unit, (uint16)phy_id, dev_addr,
   1489                             reg_addr, phy_rd_data);
   1490 }
   1491 
   1492 /*
   1493  * Function:
   1494  *      soc_esw_miimc45_addr_write
   1495  * Purpose:
   1496  *      Write the address register with a new address to access.
   1497  * Parameters:
   1498  *      unit - StrataSwitch Unit #.
   1499  *      phy_id - Phy ID to write (MIIM address)
   1500  *      phy_devad - Device type (PMA/PMD, PCS, PHY XS)
   1501  *      phy_rd_data - 16 bit register address
   1502  * Returns:
   1503  *      SOC_E_XXX
   1504  * Notes:
   1505  */
   1506 int
   1507 soc_esw_miimc45_addr_write(int unit, uint32 phy_id,
   1508                            uint8 phy_devad, uint16 phy_ad_data)
   1509 {
   1510     uint8  dev_addr;
   1511     uint16 reg_addr;
   1512 
   1513     dev_addr = (phy_devad & ~MIIM_CYCLE_C45_MASK) | MIIM_CYCLE_C45_WR_AD;
   1514     reg_addr = phy_ad_data;
   1515 
   1516     return soc_miimc45_write(unit, (uint16)phy_id, dev_addr,
   1517                              reg_addr, 0);
   1518 }
   1519 
   1520 /*
   1521  * Function:
   1522  *      soc_esw_miimc45_post_read
   1523  * Purpose:
   1524  *      Read a value from the present MII register and increase register addr.
   1525  * Parameters:
   1526  *      unit - StrataSwitch Unit #.
   1527  *      phy_id - Phy ID to write (MIIM address)
   1528  *      phy_devad - Device type (PMA/PMD, PCS, PHY XS)
   1529  *      phy_rd_data - point to 16 bit data buffer
   1530  * Returns:
   1531  *      SOC_E_XXX
   1532  * Notes:
   1533  */
   1534 int
   1535 soc_esw_miimc45_post_read(int unit, uint32 phy_id,
   1536                           uint8 phy_devad, uint16 *phy_rd_data)
   1537 {
   1538     uint8  dev_addr;
   1539     uint16 reg_addr;
   1540 
   1541     dev_addr = (phy_devad & ~MIIM_CYCLE_C45_MASK) | MIIM_CYCLE_C45_RD_ADINC;
   1542     reg_addr = 0;
   1543 
   1544     return soc_miimc45_read(unit, (uint16)phy_id, dev_addr,
   1545                             reg_addr, phy_rd_data);
   1546 }
   1547 
   1548 /*
   1549  * Function:
   1550  *      soc_miimc45_modify
   1551  * Purpose:
   1552  *      Modify a value from an MII register.
   1553  * Parameters:
   1554  *      unit - StrataSwitch Unit #.
   1555  *      phy_id - Phy ID to write (MIIM address)
   1556  *      phy_devad - Device type (PMA/PMD, PCS, PHY XS)
   1557  *      phy_reg_addr - PHY register to write
   1558  *      phy_rd_data - 16bit data to write into
   1559  *      phy_rd_mask - 16bit mask to indicate the bits to modify.
   1560  * Returns:
   1561  *      SOC_E_XXX
   1562  * Notes:
   1563  */
   1564 
   1565 int
   1566 soc_miimc45_modify(int unit, uint16 phy_id, uint8 phy_devad,
   1567                  uint16 phy_reg_addr, uint16 phy_rd_data, uint16 phy_rd_mask)
   1568 {
   1569     uint16  tmp = 0, otmp;
   1570 
   1571     phy_rd_data = phy_rd_data & phy_rd_mask;
   1572 
   1573     SOC_IF_ERROR_RETURN
   1574         (soc_miimc45_read(unit, phy_id, phy_devad, phy_reg_addr, &tmp));
   1575     otmp = tmp;
   1576     tmp &= ~(phy_rd_mask);
   1577     tmp |= phy_rd_data;
   1578 
   1579     if (otmp != tmp) {
   1580         SOC_IF_ERROR_RETURN
   1581             (soc_miimc45_write(unit, phy_id, phy_devad, phy_reg_addr, tmp));
   1582     }
   1583     return SOC_E_NONE;
   1584 }
   1585 
   1586 /*
   1587  * Customer specific MDIO wrapper support
   1588  *
   1589  * Some customers of the SDK wish to wrap the underlying MDIO access
   1590  * routines (both clause 22 and clasue 45) with customer specific
   1591  * functions that may provide an alternate access method, some predicate
   1592  * controls on whether actual operations occur, or some translation
   1593  * mechanisms.
   1594  *
   1595  * The method discussed here is an interim mechanism that is sufficient
   1596  * for release to selected customers.  A more extensible long term
   1597  * mechanism will be defined in a future SDK release.  This method will
   1598  * work for Enterprise Switch (XGS) operations but may not work for
   1599  * other device families.
   1600  *
   1601  * 1. Replace the file $SDK/soc/common/miim.c with this file.
   1602  *    It moves the basic miim access functions to the end of the file
   1603  *    and provides mechanism to rename them to _soc_miim*.
   1604  * 2. Compile the entire SDK with the following defines on the command line:
   1605  *    -Dsoc_miim_read=cust_miim_read
   1606  *    -Dsoc_miim_write=cust_miim_write
   1607  *    -Dsoc_miimc45_read=cust_miimc45_read
   1608  *    -Dsoc_miimc45_write=cust_miic45_write
   1609  * 3. Provide implementation of the cust_miim* functions.
   1610  *    They are defined identically to the soc_miim* functions below:
   1611  *    int cust_miim_write(int unit, uint8 phy_id,
   1612  *                uint8 phy_reg_addr, uint16 phy_wr_data)
   1613  *    int cust_miim_read(int unit, uint8 phy_id,
   1614  *               uint8 phy_reg_addr, uint16 *phy_rd_data)
   1615  *    int cust_miimc45_write(int unit, uint8 phy_id, uint8 phy_devad,
   1616  *                   uint16 phy_reg_addr, uint16 phy_wr_data)
   1617  *    int cust_miimc45_read(int unit, uint8 phy_id, uint8 phy_devad,
   1618  *                  uint16 phy_reg_addr, uint16 *phy_rd_data)
   1619  * 4. If the cust_miim* functions need to access the original defintions
   1620  *    of the soc_miim* functions, they need to refer to them as _soc_miim*
   1621  *    and provide extern definitions of those functions:
   1622  *    extern int _soc_miim_write(int unit, uint8 phy_id,
   1623  *                       uint8 phy_reg_addr, uint16 phy_wr_data);
   1624  *    extern int _soc_miim_read(int unit, uint8 phy_id,
   1625  *                      uint8 phy_reg_addr, uint16 *phy_rd_data);
   1626  *    extern int _soc_miimc45_write(int unit, uint8 phy_id, uint8 phy_devad,
   1627  *                          uint16 phy_reg_addr, uint16 phy_wr_data);
   1628  *    extern int _soc_miimc45_read(int unit, uint8 phy_id, uint8 phy_devad,
   1629  *                         uint16 phy_reg_addr, uint16 *phy_rd_data);
   1630  */
   1631 #ifdef soc_miim_read
   1632     #undef soc_miim_read
   1633     #define soc_miim_read _soc_miim_read
   1634 #endif
   1635 #ifdef soc_miim_write
   1636     #undef soc_miim_write
   1637     #define soc_miim_write _soc_miim_write
   1638 #endif
   1639 #ifdef soc_miimc45_read
   1640     #undef soc_miimc45_read
   1641     #define soc_miimc45_read _soc_miimc45_read
   1642 #endif
   1643 #ifdef soc_miimc45_write
   1644     #undef soc_miimc45_write
   1645     #define soc_miimc45_write _soc_miimc45_write
   1646 #endif
   1647 
   1648 /*
   1649  * Function:
   1650  *      soc_miim_write
   1651  * Purpose:
   1652  *      Write a value to a MIIM register.
   1653  * Parameters:
   1654  *      unit - StrataSwitch Unit #.
   1655  *      phy_id - Phy ID to write (MIIM address)
   1656  *      phy_reg_addr - PHY register to write
   1657  *      phy_wr_data - Data to write.
   1658  * Returns:
   1659  *      SOC_E_XXX
   1660  * Notes:
   1661  *      Temporarily disables auto link scan if it was enabled.  The MIIM
   1662  *      registers are locked during the operation to prevent multiple
   1663  *      tasks from trying to access PHY registers simultaneously.
   1664  */
   1665 
   1666 int 
   1667 soc_miim_write(int unit, uint16 phy_id,
   1668                uint8 phy_reg_addr, uint16 phy_wr_data)
   1669 {
   1670     int                 rv = SOC_E_NONE;
   1671 #if defined(BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)
   1672     int                 clause45;
   1673     uint32              phy_param;
   1674     int miim_intr_retry_cnt = MIIM_INTR_RETRY_COUNT;
   1675 #ifdef BCM_CMICM_SUPPORT
   1676     int cmc = SOC_PCI_CMC(unit);
   1677 #endif
   1678 #endif
   1679 
   1680 #if defined(BCM_ESW_SUPPORT) || defined (BCM_DFE_SUPPORT)
   1681     assert(!sal_int_context());
   1682 
   1683     LOG_VERBOSE(BSL_LS_SOC_MIIM,
   1684              (BSL_META_U(unit,
   1685                          "soc_miim_write: id=0x%02x addr=0x%02x data=0x%04x\n"),
   1686               phy_id, phy_reg_addr, phy_wr_data));
   1687 
   1688     clause45 = soc_feature(unit, soc_feature_phy_cl45);
   1689 
   1690 #ifdef BCM_CMICX_SUPPORT
   1691     if (soc_feature(unit, soc_feature_cmicx)) {
   1692         return soc_cmicx_miim_operation(unit, TRUE, SOC_CLAUSE_22, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, phy_id,
   1693                         phy_reg_addr, &phy_wr_data);
   1694     }
   1695 #endif /* BCM_CMICX_SUPPORT */
   1696 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_CMICM_SUPPORT)
   1697     /*
   1698      * Trident Switch And Later
   1699      * internal select bit 25
   1700      * BUS_ID  bit 22-24
   1701      * C45_SEL bit 21
   1702      */
   1703     if (SOC_IS_TD_TT(unit) || soc_feature(unit, soc_feature_cmicm)) {
   1704 
   1705         uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
   1706 
   1707         /* set 5-bit PHY MDIO address */
   1708         phy_param = (uint32)phy_wr_data |
   1709                     (((uint32)phy_id & 0x1f) << MIIM_PARAM_ID_OFFSET);
   1710 
   1711         /* select internal MDIO bus if set */
   1712         if (phy_id & 0x80) { /* Internal/External select */
   1713 #if defined(BCM_CMICDV3_SUPPORT)
   1714             /*
   1715              * Apache and Tomahawk2 Switches And Later
   1716              * internal select bit 26
   1717              * BUS_ID  bit 22-25
   1718              * C45_SEL bit 21
   1719              * See CMIC_CMC0_MIIM_PARAM register.
   1720              */
   1721             if (soc_feature(unit, soc_feature_cmicd_v3)) {
   1722                 phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 10));
   1723             } else 
   1724 #endif /* BCM_CMICDV3_SUPPORT */
   1725             {
   1726                 phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 9));
   1727             }
   1728         }
   1729 
   1730         /* set MDIO bus number */
   1731         phy_param |= (bus_sel << (MIIM_PARAM_ID_OFFSET + 6));
   1732     } else
   1733 #endif
   1734 #ifdef BCM_SHADOW_SUPPORT
   1735     if (SOC_IS_SHADOW(unit)) {
   1736 
   1737         uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
   1738 
   1739         /* set 5-bit PHY MDIO address */
   1740         phy_param = (uint32)phy_wr_data |
   1741                     (((uint32)phy_id & 0x1f) << MIIM_PARAM_ID_OFFSET);
   1742 
   1743         /* select internal MDIO bus if set */
   1744         if (phy_id & 0x80) { /* Internal/External select */
   1745             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 9));
   1746         }
   1747 
   1748         /* set MDIO bus number */
   1749         phy_param |= (bus_sel << (MIIM_PARAM_ID_OFFSET + 6));
   1750     } else
   1751 #endif /* BCM_SHADOW_SUPPORT */
   1752 
   1753 #ifdef BCM_TRX_SUPPORT
   1754     
   1755     if (SOC_IS_TRX(unit)) {
   1756         int bus_sel = (phy_id & 0x60) >> 5;
   1757     
   1758         phy_param = (uint32)phy_wr_data |
   1759                     (((uint32)phy_id & 0x1f) << MIIM_PARAM_ID_OFFSET);
   1760 
   1761         if (phy_id & 0x80) { /* Internal/External select */
   1762             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 7));
   1763         }
   1764         if (bus_sel == 1) {
   1765             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 6));
   1766         } else if (bus_sel == 2) {
   1767             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 8));
   1768         }
   1769     } else
   1770 #endif /* BCM_TRX_SUPPORT */
   1771     {
   1772         phy_param = ((uint32)phy_id << MIIM_PARAM_ID_OFFSET |
   1773                      (uint32)phy_wr_data);
   1774     }
   1775 
   1776     if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
   1777        soc_linkscan_pause(unit);
   1778     }
   1779     MIIM_LOCK(unit);
   1780 
   1781     /* Write parameter register and tell CMIC to start */
   1782 
   1783     /* Clause 45 support changes Clause 22 access method */
   1784     if (clause45) {
   1785 #ifdef BCM_CMICM_SUPPORT
   1786         if(soc_feature(unit, soc_feature_cmicm)) {
   1787             soc_pci_write(unit, CMIC_CMCx_MIIM_ADDRESS_OFFSET(cmc), phy_reg_addr);
   1788         } else
   1789 #endif
   1790         {
   1791             WRITE_CMIC_MIIM_ADDRESSr(unit, phy_reg_addr);
   1792         }
   1793     } else {
   1794         phy_param |= (uint32)phy_reg_addr << MIIM_PARAM_REG_ADDR_OFFSET;
   1795     }
   1796 
   1797 #ifdef BCM_CMICM_SUPPORT
   1798     if(soc_feature(unit, soc_feature_cmicm)) {
   1799         soc_pci_write(unit, CMIC_CMCx_MIIM_PARAM_OFFSET(cmc), phy_param);
   1800         soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 1);
   1801     } else
   1802 #endif
   1803     {
   1804         soc_pci_write(unit, CMIC_MIIM_PARAM, phy_param);
   1805         soc_pci_write(unit, CMIC_SCHAN_CTRL, SC_MIIM_WR_START_SET);
   1806     }
   1807 
   1808     /* Wait for completion using either the interrupt or polling method */
   1809 
   1810     if (SOC_CONTROL(unit)->miimIntrEnb) {
   1811 #ifdef BCM_CMICM_SUPPORT
   1812         if(soc_feature(unit, soc_feature_cmicm)) {
   1813             soc_cmicm_intr0_enable(unit, IRQ_CMCx_MIIM_OP_DONE);
   1814         } else
   1815 #endif
   1816         {
   1817             soc_intr_enable(unit, IRQ_MIIM_OP_DONE);
   1818         }
   1819         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   1820                          SOC_CONTROL(unit)->miimTimeout) != 0) {
   1821 #ifdef BCM_CMICM_SUPPORT
   1822             if(soc_feature(unit, soc_feature_cmicm)) {
   1823                 if ((soc_pci_read(unit, CMIC_CMCx_MIIM_STAT_OFFSET(cmc)) &
   1824                                              CMIC_MIIM_OPN_DONE) == 0) {
   1825                     /* MIIM HW operation not complete */
   1826                     rv = SOC_E_TIMEOUT;
   1827                 } else {
   1828                     /* MIIM HW operation complete but no intr received yet
   1829                      * Retry for MIIM Intr for busy system
   1830                      * before declaring timeout */
   1831                     rv = SOC_E_TIMEOUT;
   1832                     while (miim_intr_retry_cnt) {
   1833                         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   1834                                          MIIM_INTR_RETRY_TIMEOUT) == 0) {
   1835                             rv = SOC_E_NONE;
   1836                             break;
   1837                         }
   1838                         miim_intr_retry_cnt--;
   1839                     }
   1840                 }
   1841             } else
   1842 #endif
   1843             {
   1844                 if ((soc_pci_read(unit, CMIC_SCHAN_CTRL) & SC_MIIM_OP_DONE_TST) == 0) {
   1845                     /* MIIM HW operation not complete */
   1846                     rv = SOC_E_TIMEOUT;
   1847                 } else {
   1848                     /* MIIM HW operation complete but no intr received yet
   1849                      * Retry for MIIM Intr for busy system
   1850                      * before declaring timeout */
   1851                     rv = SOC_E_TIMEOUT;
   1852                     while (miim_intr_retry_cnt) {
   1853                         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   1854                                          MIIM_INTR_RETRY_TIMEOUT) == 0) {
   1855                             rv = SOC_E_NONE;
   1856                             break;
   1857                         }
   1858                         miim_intr_retry_cnt--;
   1859                     }
   1860                 }
   1861             }
   1862         } else {
   1863             LOG_DEBUG(BSL_LS_SOC_MIIM,
   1864                         (BSL_META_U(unit,
   1865                                     "  Interrupt received\n")));
   1866         }
   1867 
   1868 #ifdef BCM_CMICM_SUPPORT
   1869         if(soc_feature(unit, soc_feature_cmicm)) {
   1870             soc_cmicm_intr0_disable(unit, IRQ_CMCx_MIIM_OP_DONE);
   1871         } else
   1872 #endif
   1873         {
   1874             soc_intr_disable(unit, IRQ_MIIM_OP_DONE);
   1875         }
   1876     } else {
   1877         soc_timeout_t to;
   1878 
   1879         soc_timeout_init(&to, SOC_CONTROL(unit)->miimTimeout, MIIM_POLL_TIMEOUT);
   1880 
   1881 #ifdef BCM_CMICM_SUPPORT
   1882         if(soc_feature(unit, soc_feature_cmicm)) {
   1883             while ((soc_pci_read(unit, CMIC_CMCx_MIIM_STAT_OFFSET(cmc)) &
   1884                                          CMIC_MIIM_OPN_DONE) == 0) {
   1885                 if (soc_timeout_check(&to)) {
   1886                     rv = SOC_E_TIMEOUT;
   1887                     break;
   1888                 }
   1889             }
   1890         } else
   1891 #endif
   1892         {
   1893             while ((soc_pci_read(unit, CMIC_SCHAN_CTRL) &
   1894                     SC_MIIM_OP_DONE_TST) == 0) {
   1895                 if (soc_timeout_check(&to)) {
   1896                     rv = SOC_E_TIMEOUT;
   1897                     break;
   1898                 }
   1899             }
   1900         }
   1901         if (rv == SOC_E_NONE) {
   1902             LOG_DEBUG(BSL_LS_SOC_MIIM,
   1903                         (BSL_META_U(unit,
   1904                                     "  Done in %d polls\n"), to.polls));
   1905             if (soc_feature(unit, soc_feature_wh2_miim_delay)) {
   1906                 sal_udelay(10);
   1907             }
   1908         }
   1909 #ifdef BCM_CMICM_SUPPORT
   1910         if(soc_feature(unit, soc_feature_cmicm)) {
   1911             soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 0);
   1912         } else
   1913 #endif
   1914         {
   1915             soc_pci_write(unit, CMIC_SCHAN_CTRL, SC_MIIM_OP_DONE_CLR);
   1916         }
   1917     }
   1918     if (rv == SOC_E_TIMEOUT) {
   1919         LOG_ERROR(BSL_LS_SOC_COMMON,
   1920                   (BSL_META_U(unit,
   1921                               "MiimTimeOut:soc_miim_write, "
   1922                               "timeout (id=0x%02x addr=0x%02x data=0x%04x)\n"),
   1923                    phy_id, phy_reg_addr, phy_wr_data));
   1924         SOC_CONTROL(unit)->stat.err_mii_tmo++;
   1925     }
   1926 
   1927     /* Release linkscan pause and MIIM lock */
   1928 
   1929     MIIM_UNLOCK(unit);
   1930 
   1931     if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
   1932        soc_linkscan_continue(unit);
   1933     }
   1934 #endif
   1935     return rv;
   1936 
   1937 }
   1938 
   1939 /*
   1940  * Function:
   1941  *      soc_miim_read
   1942  * Purpose:
   1943  *      Read a value from an MII register.
   1944  * Parameters:
   1945  *      unit - StrataSwitch Unit #.
   1946  *      phy_id - Phy ID to write (MIIM address)
   1947  *      phy_reg_addr - PHY register to write
   1948  *      phy_rd_data - 16bit data to write into
   1949  * Returns:
   1950  *      SOC_E_XXX
   1951  * Notes:
   1952  *      Temporarily disables auto link scan if it was enabled.  The MIIM
   1953  *      registers are locked during the operation to prevent multiple
   1954  *      tasks from trying to access PHY registers simultaneously.
   1955  */
   1956 
   1957 int
   1958 soc_miim_read(int unit, uint16 phy_id,
   1959               uint8 phy_reg_addr, uint16 *phy_rd_data)
   1960 {
   1961     int                 rv = SOC_E_NONE;
   1962 #if defined(BCM_ESW_SUPPORT) || defined(BCM_DFE_SUPPORT)
   1963     int                 clause45;
   1964     uint32              phy_param;
   1965     int miim_intr_retry_cnt = MIIM_INTR_RETRY_COUNT;
   1966 #ifdef BCM_CMICM_SUPPORT
   1967     int cmc = SOC_PCI_CMC(unit);
   1968 #endif
   1969 #endif
   1970 
   1971     assert(!sal_int_context());
   1972     assert(phy_rd_data);
   1973 
   1974 #if defined(BCM_ESW_SUPPORT) || defined(BCM_DFE_SUPPORT)
   1975     LOG_VERBOSE(BSL_LS_SOC_MIIM,
   1976              (BSL_META_U(unit,
   1977                          "soc_miim_read: id=0x%02x addr=0x%02x  "),
   1978               phy_id, phy_reg_addr));
   1979 
   1980     clause45 = soc_feature(unit, soc_feature_phy_cl45);
   1981 
   1982 #ifdef BCM_CMICX_SUPPORT
   1983     if (soc_feature(unit, soc_feature_cmicx)) {
   1984         return soc_cmicx_miim_operation(unit, FALSE, SOC_CLAUSE_22, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, phy_id,
   1985                         phy_reg_addr, phy_rd_data);
   1986     }
   1987 #endif /* BCM_CMICX_SUPPORT */
   1988 
   1989 #if defined (BCM_CMICDV3_SUPPORT)
   1990     /*
   1991      * Apache Switch And Later
   1992      * internal select bit 26
   1993      * BUS_ID  bit 22-25
   1994      * C45_SEL bit 21
   1995      */
   1996     if (soc_feature(unit, soc_feature_cmicd_v3)) {
   1997 
   1998         uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
   1999 
   2000         /* set 5-bit PHY MDIO address */
   2001         phy_param = (((uint32)phy_id & 0x1f) << MIIM_PARAM_ID_OFFSET);
   2002 
   2003         /* select internal MDIO bus if set */
   2004         if (phy_id & 0x80) { /* Internal/External select */
   2005             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 10));
   2006         }
   2007 
   2008         /* set MDIO bus number */
   2009         phy_param |= (bus_sel << (MIIM_PARAM_ID_OFFSET + 6));
   2010     } else
   2011 
   2012 #endif
   2013 
   2014 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_CMICM_SUPPORT)
   2015     /* 
   2016      * Trident Switch And Later
   2017      * internal select bit 25
   2018      * BUS_ID  bit 22-24
   2019      * C45_SEL bit 21
   2020      */
   2021     if (SOC_IS_TD_TT(unit) || soc_feature(unit, soc_feature_cmicm)) {
   2022         
   2023         uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
   2024         
   2025         /* set 5-bit PHY MDIO address */ 
   2026         phy_param = (((uint32)phy_id & 0x1f) << MIIM_PARAM_ID_OFFSET);
   2027 
   2028         /* select internal MDIO bus if set */
   2029         if (phy_id & 0x80) { /* Internal/External select */
   2030 #if defined(BCM_CMICDV3_SUPPORT)
   2031             /*
   2032              * Apache and Tomahawk2 Switches And Later
   2033              * internal select bit 26
   2034              * BUS_ID  bit 22-25
   2035              * C45_SEL bit 21
   2036              * See CMIC_CMC0_MIIM_PARAM register.
   2037              */
   2038             if (soc_feature(unit, soc_feature_cmicd_v3)) {
   2039                 phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 10));
   2040             } else
   2041 #endif /* BCM_CMICDV3_SUPPORT */
   2042             {
   2043                 phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 9));
   2044             }
   2045         }
   2046   
   2047         /* set MDIO bus number */
   2048         phy_param |= (bus_sel << (MIIM_PARAM_ID_OFFSET + 6));
   2049     } else
   2050 #endif
   2051 #ifdef BCM_SHADOW_SUPPORT
   2052     /* 
   2053      * Shadow device
   2054      * internal select bit 25
   2055      * BUS_ID  bit 22-24
   2056      * C45_SEL bit 21
   2057      */
   2058     if (SOC_IS_SHADOW(unit)) {
   2059         
   2060         uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
   2061         
   2062         /* set 5-bit PHY MDIO address */ 
   2063         phy_param = (((uint32)phy_id & 0x1f) << MIIM_PARAM_ID_OFFSET);
   2064 
   2065         /* select internal MDIO bus if set */
   2066         if (phy_id & 0x80) { /* Internal/External select */
   2067             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 9));
   2068         }
   2069   
   2070         /* set MDIO bus number */
   2071         phy_param |= (bus_sel << (MIIM_PARAM_ID_OFFSET + 6));
   2072     } else
   2073 #endif /* BCM_SHADOW_SUPPORT */
   2074 
   2075 
   2076 #ifdef BCM_TRX_SUPPORT
   2077     
   2078     if (SOC_IS_TRX(unit)) {
   2079         int bus_sel = (phy_id & 0x60) >> 5;
   2080 
   2081         phy_param = (((uint32)phy_id & 0x1f) << MIIM_PARAM_ID_OFFSET);
   2082 
   2083         if (phy_id & 0x80) { /* Internal/External select */
   2084             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 7));
   2085         }
   2086         if (bus_sel == 1) {
   2087             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 6));
   2088         } else if (bus_sel == 2) {
   2089             phy_param |= (1 << (MIIM_PARAM_ID_OFFSET + 8));
   2090         }
   2091     } else
   2092 #endif /* BCM_TRX_SUPPORT */
   2093     {
   2094         phy_param = (uint32)phy_id << MIIM_PARAM_ID_OFFSET;
   2095     }
   2096 
   2097     /* Pause link scanning - and hold MIIM lock */
   2098     if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
   2099        soc_linkscan_pause(unit);
   2100     }
   2101     MIIM_LOCK(unit);
   2102 
   2103     /* Write parameter register and tell CMIC to start */
   2104 
   2105     /* Clause 45 support changes Clause 22 access method */
   2106     if (clause45) {
   2107 #ifdef BCM_CMICM_SUPPORT
   2108         if(soc_feature(unit, soc_feature_cmicm)) {
   2109             soc_pci_write(unit, CMIC_CMCx_MIIM_ADDRESS_OFFSET(cmc), phy_reg_addr);
   2110         } else
   2111 #endif
   2112         {
   2113             WRITE_CMIC_MIIM_ADDRESSr(unit, phy_reg_addr);
   2114         }
   2115     } else {
   2116         phy_param |= (uint32)phy_reg_addr << MIIM_PARAM_REG_ADDR_OFFSET;
   2117     }
   2118 
   2119 #ifdef BCM_CMICM_SUPPORT
   2120     if(soc_feature(unit, soc_feature_cmicm)) {
   2121         soc_pci_write(unit, CMIC_CMCx_MIIM_PARAM_OFFSET(cmc), phy_param);
   2122         soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 2);
   2123     } else
   2124 #endif
   2125     {
   2126         soc_pci_write(unit, CMIC_MIIM_PARAM, phy_param);
   2127         soc_pci_write(unit, CMIC_SCHAN_CTRL, SC_MIIM_RD_START_SET);
   2128     }
   2129 
   2130     /* Wait for completion using either the interrupt or polling method */
   2131 
   2132     if (SOC_CONTROL(unit)->miimIntrEnb) {
   2133 #ifdef BCM_CMICM_SUPPORT
   2134         if(soc_feature(unit, soc_feature_cmicm)) {
   2135             soc_cmicm_intr0_enable(unit, IRQ_CMCx_MIIM_OP_DONE);
   2136         } else
   2137 #endif
   2138         {
   2139             soc_intr_enable(unit, IRQ_MIIM_OP_DONE);
   2140         }
   2141 
   2142         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   2143                          SOC_CONTROL(unit)->miimTimeout) != 0) {
   2144 #ifdef BCM_CMICM_SUPPORT
   2145             if(soc_feature(unit, soc_feature_cmicm)) {
   2146                 if ((soc_pci_read(unit, CMIC_CMCx_MIIM_STAT_OFFSET(cmc)) &
   2147                                              CMIC_MIIM_OPN_DONE) == 0) {
   2148                     /* MIIM HW operation not complete */
   2149                     rv = SOC_E_TIMEOUT;
   2150                 } else {
   2151                     /* MIIM HW operation complete but no intr received yet
   2152                      * Retry for MIIM Intr for busy system
   2153                      * before declaring timeout */
   2154                     rv = SOC_E_TIMEOUT;
   2155                     while (miim_intr_retry_cnt) {
   2156                         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   2157                                          MIIM_INTR_RETRY_TIMEOUT) == 0) {
   2158                             rv = SOC_E_NONE;
   2159                             break;
   2160                         }
   2161                         miim_intr_retry_cnt--;
   2162                     }
   2163                 }
   2164             } else
   2165 #endif
   2166             {
   2167                 if ((soc_pci_read(unit, CMIC_SCHAN_CTRL) & SC_MIIM_OP_DONE_TST) == 0) {
   2168                     /* MIIM HW operation not complete */
   2169                     rv = SOC_E_TIMEOUT;
   2170                 } else {
   2171                     /* MIIM HW operation complete but no intr received yet
   2172                      * Retry for MIIM Intr for busy system
   2173                      * before declaring timeout */
   2174                     rv = SOC_E_TIMEOUT;
   2175                     while (miim_intr_retry_cnt) {
   2176                         if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   2177                                          MIIM_INTR_RETRY_TIMEOUT) == 0) {
   2178                             rv = SOC_E_NONE;
   2179                             break;
   2180                         }
   2181                         miim_intr_retry_cnt--;
   2182                     }
   2183                 }
   2184             }
   2185         } else {
   2186             LOG_DEBUG(BSL_LS_SOC_MIIM,
   2187                         (BSL_META_U(unit,
   2188                                     "  Interrupt received\n")));
   2189         }
   2190 
   2191 #ifdef BCM_CMICM_SUPPORT
   2192         if(soc_feature(unit, soc_feature_cmicm)) {
   2193             soc_cmicm_intr0_disable(unit, IRQ_CMCx_MIIM_OP_DONE);
   2194         } else
   2195 #endif
   2196         {
   2197             soc_intr_disable(unit, IRQ_MIIM_OP_DONE);
   2198         }
   2199     } else {
   2200         soc_timeout_t to;
   2201 
   2202         soc_timeout_init(&to, SOC_CONTROL(unit)->miimTimeout, MIIM_POLL_TIMEOUT);
   2203 
   2204 #ifdef BCM_CMICM_SUPPORT
   2205         if(soc_feature(unit, soc_feature_cmicm)) {
   2206             while ((soc_pci_read(unit, CMIC_CMCx_MIIM_STAT_OFFSET(cmc)) &
   2207                                          CMIC_MIIM_OPN_DONE) == 0) {
   2208                 if (soc_timeout_check(&to)) {
   2209                     rv = SOC_E_TIMEOUT;
   2210                     break;
   2211                 }
   2212             }
   2213         } else
   2214 #endif
   2215         {
   2216             while ((soc_pci_read(unit, CMIC_SCHAN_CTRL) &
   2217                     SC_MIIM_OP_DONE_TST) == 0) {
   2218                 if (soc_timeout_check(&to)) {
   2219                     rv = SOC_E_TIMEOUT;
   2220                     break;
   2221                 }
   2222             }
   2223         }
   2224 
   2225         if (rv == SOC_E_NONE) {
   2226             LOG_DEBUG(BSL_LS_SOC_MIIM,
   2227                         (BSL_META_U(unit,
   2228                                     "  Done in %d polls\n"), to.polls));
   2229         }
   2230 #ifdef BCM_CMICM_SUPPORT
   2231         if(soc_feature(unit, soc_feature_cmicm)) {
   2232             soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 0);
   2233         } else
   2234 #endif
   2235         {
   2236             soc_pci_write(unit, CMIC_SCHAN_CTRL, SC_MIIM_OP_DONE_CLR);
   2237         }
   2238     }
   2239 
   2240     if (rv == SOC_E_TIMEOUT) {
   2241         LOG_ERROR(BSL_LS_SOC_COMMON,
   2242                   (BSL_META_U(unit,
   2243                               "MiimTimeOut:soc_miim_read, "
   2244                               "timeout (id=0x%02x addr=0x%02x)\n"),
   2245                    phy_id, phy_reg_addr));
   2246         SOC_CONTROL(unit)->stat.err_mii_tmo++;
   2247     } else {
   2248 #ifdef BCM_CMICM_SUPPORT
   2249         if(soc_feature(unit, soc_feature_cmicm)) {
   2250             *phy_rd_data = (uint16)soc_pci_read(unit, CMIC_CMCx_MIIM_READ_DATA_OFFSET(cmc));
   2251         } else
   2252 #endif
   2253         {
   2254             *phy_rd_data = (uint16)soc_pci_read(unit, CMIC_MIIM_READ_DATA);
   2255         }
   2256 
   2257         LOG_VERBOSE(BSL_LS_SOC_MIIM,
   2258                  (BSL_META_U(unit,
   2259                              "data=0x%04x\n"), *phy_rd_data));
   2260     }
   2261 
   2262     /* Release linkscan pause and MIIM lock */
   2263 
   2264     MIIM_UNLOCK(unit);
   2265 
   2266     if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
   2267        soc_linkscan_continue(unit);
   2268     }
   2269 #endif    
   2270     return rv;
   2271 
   2272 }
   2273 
   2274 /*
   2275  * Function:
   2276  *      __soc_miimc45_write
   2277  * Purpose:
   2278  *      Write a value to a MIIM register.
   2279  * Parameters:
   2280  *      unit - StrataSwitch Unit #.
   2281  *      phy_id - Phy ID to write (MIIM address)
   2282  *      phy_devad - Device type (PMA/PMD, PCS, PHY XS)
   2283  *      phy_reg_addr - PHY register to write
   2284  *      phy_wr_data - Data to write.
   2285  *      flags - flags altering the behavior of the function.
   2286  * Returns:
   2287  *      SOC_E_XXX
   2288  * Notes:
   2289  *      Temporarily disables auto link scan if it was enabled.  The MIIM
   2290  *      registers are locked during the operation to prevent multiple
   2291  *      tasks from trying to access PHY registers simultaneously.
   2292  */
   2293 
   2294 int 
   2295 __soc_miimc45_write(int unit, uint16 phy_id, uint8 phy_devad,
   2296                   uint16 phy_reg_addr, uint16 phy_wr_data, uint32 flags)
   2297 {
   2298     int                 rv = SOC_E_NONE;
   2299     assert(!sal_int_context());
   2300 
   2301     if ((SOC_WARM_BOOT(unit)) && (phy_devad != 0x1e) && !(flags & MIIM_WB_C45)) {
   2302         return SOC_E_NONE;
   2303     }
   2304 
   2305     LOG_VERBOSE(BSL_LS_SOC_MIIM,
   2306              (BSL_META_U(unit,
   2307                          "__soc_miimc45_write: id=0x%02x phy_devad=0x%02x "
   2308                          "addr=0x%02x data=0x%04x\n"),
   2309               phy_id, phy_devad, phy_reg_addr, phy_wr_data));
   2310 
   2311     if (!soc_feature(unit, soc_feature_phy_cl45)) {
   2312         return SOC_E_UNAVAIL;
   2313     }
   2314 #ifdef BCM_ESW_SUPPORT
   2315 
   2316     if ((SOC_IS_RELOADING(unit)) && (phy_devad != 0x1e) && !(flags & MIIM_WB_C45)) {
   2317         return SOC_E_NONE;
   2318     }
   2319 
   2320 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   2321     {
   2322         uint32          phy_param;
   2323         uint32          phy_miim_addr;
   2324         uint32          cycle_type;
   2325         int miim_intr_retry_cnt = MIIM_INTR_RETRY_COUNT;
   2326 #ifdef BCM_CMICM_SUPPORT
   2327         int cmc = SOC_PCI_CMC(unit);
   2328 #endif
   2329 #ifdef BCM_CMICX_SUPPORT
   2330         if (soc_feature(unit, soc_feature_cmicx)) {
   2331             return soc_cmicx_miim_operation(unit, TRUE, SOC_CLAUSE_45, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, phy_id,
   2332                         ((phy_devad << 16) | (phy_reg_addr & 0xFFFF)), &phy_wr_data);
   2333         }
   2334 #endif /* BCM_CMICX_SUPPORT */
   2335         /* Pause link scanning - and hold MIIM lock */
   2336         if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
   2337            soc_linkscan_pause(unit);
   2338         }
   2339         MIIM_LOCK(unit);
   2340 
   2341         /* Write parameter registers and tell CMIC to start */
   2342         phy_param = 0;
   2343         if (phy_devad & MIIM_CYCLE_C45_WR) {
   2344             cycle_type = MIIM_CYCLE_C45_REG_WR;
   2345         } else if (phy_devad & MIIM_CYCLE_C45_WR_AD) {
   2346             cycle_type = MIIM_CYCLE_C45_REG_AD;
   2347         } else {
   2348             cycle_type = MIIM_CYCLE_AUTO;
   2349         }
   2350         phy_devad &= ~MIIM_CYCLE_C45_MASK;
   2351 #ifdef BCM_CMICM_SUPPORT
   2352         if(soc_feature(unit, soc_feature_cmicm)) {
   2353             soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &phy_param,
   2354                               MIIM_CYCLEf, cycle_type);
   2355         } else 
   2356 #endif
   2357         {
   2358             soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param,
   2359                               MIIM_CYCLEf, cycle_type);
   2360         }
   2361         if (phy_id & 0x80) {
   2362             phy_id &= (~0x80);
   2363 #ifdef BCM_CMICM_SUPPORT
   2364             if(soc_feature(unit, soc_feature_cmicm)) {
   2365                 soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr,
   2366                                   &phy_param, INTERNAL_SELf, 1);
   2367             } else 
   2368 #endif
   2369             {
   2370                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr,
   2371                                   &phy_param, INTERNAL_SELf, 1);
   2372             }
   2373         }
   2374 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   2375         if (soc_feature(unit, soc_feature_mdio_enhanced)) {
   2376 #ifdef BCM_CMICM_SUPPORT
   2377             if(soc_feature(unit, soc_feature_cmicm)) {
   2378                 soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr,
   2379                                   &phy_param, C45_SELf, 1);
   2380             } else
   2381 #endif
   2382             {
   2383                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr,
   2384                                   &phy_param, C45_SELf, 1);
   2385             }
   2386 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_CMICM_SUPPORT)
   2387             if (SOC_IS_TD_TT(unit) || soc_feature(unit, soc_feature_cmicm)) {
   2388                 uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
   2389 #ifdef BCM_CMICM_SUPPORT
   2390                 if(soc_feature(unit, soc_feature_cmicm)) {
   2391                     soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &phy_param,
   2392                                       BUS_IDf, bus_sel);
   2393                 } else
   2394 #endif
   2395                 {
   2396                     soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param,
   2397                                       BUS_IDf, bus_sel);
   2398                 }
   2399                 phy_id &= ~(PHY_ID_BUS_UPPER_MASK | PHY_ID_BUS_LOWER_MASK);
   2400             } else
   2401 #endif
   2402 #if defined(BCM_SHADOW_SUPPORT)
   2403             if (SOC_IS_SHADOW(unit)) {
   2404                 uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
   2405                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param,
   2406                                   BUS_IDf, bus_sel);
   2407                 phy_id &= ~(PHY_ID_BUS_UPPER_MASK | PHY_ID_BUS_LOWER_MASK);
   2408             } else
   2409 #endif
   2410 #if defined(BCM_TRX_SUPPORT)
   2411             if (SOC_IS_TRX(unit)) {
   2412                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param, 
   2413                                   BUS0_1_SELf, ((phy_id & 0x20) ? 1 : 0));
   2414                 phy_id &= (~0x20);
   2415 
   2416                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param, 
   2417                                   BUS2_SELf, ((phy_id & 0x40) ? 1 : 0));
   2418                 phy_id &= (~0x40);
   2419             } else 
   2420 #endif /* BCM_TRX_SUPPORT */
   2421             {
   2422                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param, HG_SELf,
   2423                                   ((phy_id & 0x40) ? 1 : 0));
   2424                 phy_id &= (~0x40);
   2425             }
   2426         }
   2427 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   2428 
   2429 #ifdef BCM_CMICM_SUPPORT
   2430         if(soc_feature(unit, soc_feature_cmicm)) {
   2431             soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &phy_param, PHY_IDf, phy_id);
   2432             soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &phy_param,
   2433                               PHY_DATAf, phy_wr_data);
   2434             phy_miim_addr = 0;
   2435             soc_reg_field_set(unit, CMIC_CMC0_MIIM_ADDRESSr, &phy_miim_addr,
   2436                               CLAUSE_45_DTYPEf, phy_devad);
   2437             soc_reg_field_set(unit, CMIC_CMC0_MIIM_ADDRESSr, &phy_miim_addr,
   2438                               CLAUSE_45_REGADRf, phy_reg_addr);
   2439         } else
   2440 #endif
   2441         {
   2442             soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param, PHY_IDf, phy_id);
   2443             soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param,
   2444                               PHY_DATAf, phy_wr_data);
   2445             phy_miim_addr = 0;
   2446             soc_reg_field_set(unit, CMIC_MIIM_ADDRESSr, &phy_miim_addr,
   2447                               CLAUSE_45_DTYPEf, phy_devad);
   2448             soc_reg_field_set(unit, CMIC_MIIM_ADDRESSr, &phy_miim_addr,
   2449                               CLAUSE_45_REGADRf, phy_reg_addr);
   2450         }
   2451 #ifdef BCM_CMICM_SUPPORT
   2452         if(soc_feature(unit, soc_feature_cmicm)) {
   2453             soc_pci_write(unit, CMIC_CMCx_MIIM_ADDRESS_OFFSET(cmc), phy_miim_addr);
   2454             soc_pci_write(unit, CMIC_CMCx_MIIM_PARAM_OFFSET(cmc), phy_param);
   2455             soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 1);
   2456         } else
   2457 #endif
   2458         {
   2459             WRITE_CMIC_MIIM_ADDRESSr(unit, phy_miim_addr);
   2460             soc_pci_write(unit, CMIC_MIIM_PARAM, phy_param);
   2461             soc_pci_write(unit, CMIC_SCHAN_CTRL, SC_MIIM_WR_START_SET);
   2462         }
   2463 
   2464         /* Wait for completion using either the interrupt or polling method */
   2465 
   2466         if (SOC_CONTROL(unit)->miimIntrEnb) {
   2467 #ifdef BCM_CMICM_SUPPORT
   2468             if(soc_feature(unit, soc_feature_cmicm)) {
   2469                 soc_cmicm_intr0_enable(unit, IRQ_CMCx_MIIM_OP_DONE);
   2470             } else
   2471 #endif
   2472             {
   2473                 soc_intr_enable(unit, IRQ_MIIM_OP_DONE);
   2474             }
   2475 
   2476             if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   2477                              SOC_CONTROL(unit)->miimTimeout) != 0) {
   2478 #ifdef BCM_CMICM_SUPPORT
   2479                 if(soc_feature(unit, soc_feature_cmicm)) {
   2480                     if ((soc_pci_read(unit, CMIC_CMCx_MIIM_STAT_OFFSET(cmc)) &
   2481                                                  CMIC_MIIM_OPN_DONE) == 0) {
   2482                         /* MIIM HW operation not complete */
   2483                         rv = SOC_E_TIMEOUT;
   2484                     } else {
   2485                         /* MIIM HW operation complete but no intr received yet
   2486                          * Retry for MIIM Intr for busy system
   2487                          * before declaring timeout */
   2488                         rv = SOC_E_TIMEOUT;
   2489                         while (miim_intr_retry_cnt) {
   2490                             if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   2491                                              MIIM_INTR_RETRY_TIMEOUT) == 0) {
   2492                                 rv = SOC_E_NONE;
   2493                                 break;
   2494                             }
   2495                             miim_intr_retry_cnt--;
   2496                         }
   2497                     }
   2498                 } else
   2499 #endif
   2500                 {
   2501                     if ((soc_pci_read(unit, CMIC_SCHAN_CTRL) & SC_MIIM_OP_DONE_TST) == 0) {
   2502                         /* MIIM HW operation not complete */
   2503                         rv = SOC_E_TIMEOUT;
   2504                     } else {
   2505                         /* MIIM HW operation complete but no intr received yet
   2506                          * Retry for MIIM Intr for busy system
   2507                          * before declaring timeout */
   2508                         rv = SOC_E_TIMEOUT;
   2509                         while (miim_intr_retry_cnt) {
   2510                             if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   2511                                              MIIM_INTR_RETRY_TIMEOUT) == 0) {
   2512                                 rv = SOC_E_NONE;
   2513                                 break;
   2514                             }
   2515                             miim_intr_retry_cnt--;
   2516                         }
   2517                     }
   2518                 }
   2519             } else {
   2520                 LOG_DEBUG(BSL_LS_SOC_MIIM,
   2521                             (BSL_META_U(unit,
   2522                                         "  Interrupt received\n")));
   2523             }
   2524 
   2525 #ifdef BCM_CMICM_SUPPORT
   2526             if(soc_feature(unit, soc_feature_cmicm)) {
   2527                 soc_cmicm_intr0_disable(unit, IRQ_CMCx_MIIM_OP_DONE);
   2528             } else
   2529 #endif
   2530             {
   2531                 soc_intr_disable(unit, IRQ_MIIM_OP_DONE);
   2532             }
   2533         } else {
   2534             soc_timeout_t to;
   2535 
   2536             soc_timeout_init(&to, SOC_CONTROL(unit)->miimTimeout, MIIM_POLL_TIMEOUT);
   2537 
   2538 #ifdef BCM_CMICM_SUPPORT
   2539             if(soc_feature(unit, soc_feature_cmicm)) {
   2540                 while ((soc_pci_read(unit, CMIC_CMCx_MIIM_STAT_OFFSET(cmc)) &
   2541                                              CMIC_MIIM_OPN_DONE) == 0) {
   2542                     if (soc_timeout_check(&to)) {
   2543                         rv = SOC_E_TIMEOUT;
   2544                         break;
   2545                     }
   2546                 }
   2547             } else
   2548 #endif
   2549             {
   2550                 while ((soc_pci_read(unit, CMIC_SCHAN_CTRL) &
   2551                         SC_MIIM_OP_DONE_TST) == 0) {
   2552                     if (soc_timeout_check(&to)) {
   2553                         rv = SOC_E_TIMEOUT;
   2554                         break;
   2555                     }
   2556                 }
   2557             }
   2558 
   2559             if (rv == SOC_E_NONE) {
   2560                 LOG_DEBUG(BSL_LS_SOC_MIIM,
   2561                             (BSL_META_U(unit,
   2562                                         "  Done in %d polls\n"), to.polls));
   2563             }
   2564 #ifdef BCM_CMICM_SUPPORT
   2565             if(soc_feature(unit, soc_feature_cmicm)) {
   2566                 soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 0);
   2567             } else
   2568 #endif
   2569             {
   2570                 soc_pci_write(unit, CMIC_SCHAN_CTRL, SC_MIIM_OP_DONE_CLR);
   2571             }
   2572         }
   2573 
   2574         if (rv == SOC_E_TIMEOUT) {
   2575             LOG_ERROR(BSL_LS_SOC_COMMON,
   2576                       (BSL_META_U(unit,
   2577                                   "MiimTimeOut:__soc_miimc45_write, "
   2578                                   "timeout (id=0x%02x addr=0x%02x data=0x%04x)\n"),
   2579                        phy_id, phy_reg_addr, phy_wr_data));
   2580             SOC_CONTROL(unit)->stat.err_mii_tmo++;
   2581         }
   2582 
   2583         /* Release linkscan pause and MIIM lock */
   2584         MIIM_UNLOCK(unit);
   2585 
   2586         if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
   2587            soc_linkscan_continue(unit);
   2588         }
   2589     }
   2590 #endif
   2591 #endif
   2592     return rv;
   2593 
   2594 }
   2595 
   2596 /*
   2597  * Function:
   2598  *      soc_miimc45_write
   2599  * Purpose:
   2600  *      Write a value to a MIIM register.
   2601  * Parameters:
   2602  *      unit - StrataSwitch Unit #.
   2603  *      phy_id - Phy ID to write (MIIM address)
   2604  *      phy_devad - Device type (PMA/PMD, PCS, PHY XS)
   2605  *      phy_reg_addr - PHY register to write
   2606  *      phy_wr_data - Data to write.
   2607  * Returns:
   2608  *      SOC_E_XXX
   2609  * Notes:
   2610  *      Temporarily disables auto link scan if it was enabled.  The MIIM
   2611  *      registers are locked during the operation to prevent multiple
   2612  *      tasks from trying to access PHY registers simultaneously. This
   2613  *      is a wrapper around __soc_miimc45_write that should be used for
   2614  *      oridinary clause 45 writes that are disabled during warmboot.
   2615  */
   2616 
   2617 int
   2618 soc_miimc45_write(int unit, uint16 phy_id, uint8 phy_devad,
   2619                   uint16 phy_reg_addr, uint16 phy_wr_data)
   2620 {
   2621 
   2622     return __soc_miimc45_write(unit, phy_id, phy_devad,
   2623                   phy_reg_addr, phy_wr_data, 0);
   2624 }
   2625 
   2626 /*
   2627  * Function:
   2628  *      soc_esw_miimc45_wb_write
   2629  * Purpose:
   2630  *      Write a value from an MII register.
   2631  * Parameters:
   2632  *      unit - StrataSwitch Unit #.
   2633  *      phy_id - Phy ID to write (MIIM address)
   2634  *      phy_reg_addr - PHY register to write (Encoded with PMA/PMD, PCS, PHY XS)
   2635  *      phy_wr_data - 16bit data to write into
   2636  * Returns:
   2637  *      SOC_E_XXX
   2638  * Notes:
   2639  *      This is a wrapper around __soc_miimc45_write that should be used for
   2640  *      clause 45 writes that should succeed during warmboot.
   2641  */
   2642 int
   2643 soc_esw_miimc45_wb_write(int unit, uint32 phy_id,
   2644                      uint32 phy_reg_addr, uint16 phy_wr_data)
   2645 {
   2646     uint8  dev_addr;
   2647     uint16 reg_addr;
   2648 
   2649     dev_addr = SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr);
   2650     reg_addr = SOC_PHY_CLAUSE45_REGAD(phy_reg_addr);
   2651 
   2652     return __soc_miimc45_write(unit, (uint16)phy_id, dev_addr,
   2653                              reg_addr, phy_wr_data, MIIM_WB_C45);
   2654 }
   2655 
   2656 /*
   2657  * Function:
   2658  *      soc_miimc45_read
   2659  * Purpose:
   2660  *      Read a value from an MII register.
   2661  * Parameters:
   2662  *      unit - StrataSwitch Unit #.
   2663  *      phy_id - Phy ID to write (MIIM address)
   2664  *      phy_devad - Device type (PMA/PMD, PCS, PHY XS)
   2665  *      phy_reg_addr - PHY register to write
   2666  *      phy_rd_data - 16bit data to write into
   2667  * Returns:
   2668  *      SOC_E_XXX
   2669  * Notes:
   2670  *      Temporarily disables auto link scan if it was enabled.  The MIIM
   2671  *      registers are locked during the operation to prevent multiple
   2672  *      tasks from trying to access PHY registers simultaneously.
   2673  */
   2674 
   2675 int
   2676 soc_miimc45_read(int unit, uint16 phy_id, uint8 phy_devad,
   2677                  uint16 phy_reg_addr, uint16 *phy_rd_data)
   2678 {
   2679     int                 rv = SOC_E_NONE;
   2680     assert(!sal_int_context());
   2681     assert(phy_rd_data);
   2682 
   2683     LOG_VERBOSE(BSL_LS_SOC_MIIM,
   2684              (BSL_META_U(unit,
   2685                          "soc_miimc45_read: id=0x%02x "
   2686                          "phy_devad=0x%02x addr=0x%02x\n"),
   2687               phy_id, phy_devad, phy_reg_addr));
   2688 
   2689     if (!soc_feature(unit, soc_feature_phy_cl45)) {
   2690         return SOC_E_UNAVAIL;
   2691     }
   2692 #ifdef BCM_ESW_SUPPORT
   2693 
   2694 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   2695     {
   2696         uint32          phy_param;
   2697         uint32          phy_miim_addr;
   2698         uint32          cycle_type;
   2699         int miim_intr_retry_cnt = MIIM_INTR_RETRY_COUNT;
   2700 #ifdef BCM_CMICM_SUPPORT
   2701         int cmc = SOC_PCI_CMC(unit);
   2702 #endif
   2703 #ifdef BCM_CMICX_SUPPORT
   2704         if (soc_feature(unit, soc_feature_cmicx)) {
   2705             return soc_cmicx_miim_operation(unit, FALSE, SOC_CLAUSE_45, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, MIIM_INTERNAL_EXTERNAL_DELAY_INVALID, phy_id,
   2706                         ((phy_devad << 16) | (phy_reg_addr & 0xFFFF)), phy_rd_data);
   2707         }
   2708 #endif /* BCM_CMICX_SUPPORT */
   2709 
   2710         /* Pause link scanning - and hold MIIM lock */
   2711         if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
   2712            soc_linkscan_pause(unit);
   2713         }
   2714         MIIM_LOCK(unit);
   2715 
   2716         /* Write parameter registers and tell CMIC to start */
   2717         phy_param = 0;
   2718         if (phy_devad & MIIM_CYCLE_C45_RD) {
   2719             cycle_type = MIIM_CYCLE_C45_REG_RD;
   2720         } else if (phy_devad & MIIM_CYCLE_C45_RD_ADINC) {
   2721             cycle_type = MIIM_CYCLE_C45_REG_RD_ADINC;
   2722         } else {
   2723             cycle_type = MIIM_CYCLE_AUTO;
   2724         }
   2725         phy_devad &= ~MIIM_CYCLE_C45_MASK;
   2726 #ifdef BCM_CMICM_SUPPORT
   2727         if(soc_feature(unit, soc_feature_cmicm)) {
   2728             soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &phy_param,
   2729                               MIIM_CYCLEf, cycle_type);
   2730         } else 
   2731 #endif
   2732         {
   2733             soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param,
   2734                               MIIM_CYCLEf, cycle_type);
   2735         }
   2736         if (phy_id & 0x80) {
   2737             phy_id &= (~0x80);
   2738 #ifdef BCM_CMICM_SUPPORT
   2739             if(soc_feature(unit, soc_feature_cmicm)) {
   2740                 soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr,
   2741                                   &phy_param, INTERNAL_SELf, 1);
   2742             } else 
   2743 #endif
   2744             {
   2745                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr,
   2746                                   &phy_param, INTERNAL_SELf, 1);
   2747             }
   2748         }
   2749 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   2750         if (soc_feature(unit, soc_feature_mdio_enhanced)) {
   2751 #ifdef BCM_CMICM_SUPPORT
   2752             if(soc_feature(unit, soc_feature_cmicm)) {
   2753                 soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr,
   2754                                   &phy_param, C45_SELf, 1);
   2755             } else
   2756 #endif
   2757             {
   2758                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr,
   2759                                   &phy_param, C45_SELf, 1);
   2760             }
   2761 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_CMICM_SUPPORT)
   2762             if (SOC_IS_TD_TT(unit) || soc_feature(unit, soc_feature_cmicm)) {
   2763                 uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
   2764 #ifdef BCM_CMICM_SUPPORT
   2765                 if(soc_feature(unit, soc_feature_cmicm)) {
   2766                     soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &phy_param,
   2767                                       BUS_IDf, bus_sel);
   2768                 } else
   2769 #endif
   2770                 {
   2771                     soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param,
   2772                                       BUS_IDf, bus_sel);
   2773                 }
   2774                 phy_id &= ~(PHY_ID_BUS_UPPER_MASK | PHY_ID_BUS_LOWER_MASK);
   2775             } else
   2776 #endif
   2777 #if defined(BCM_SHADOW_SUPPORT)
   2778             if (SOC_IS_SHADOW(unit)) {
   2779                 uint32 bus_sel = PHY_ID_BUS_NUM(phy_id);
   2780                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param,
   2781                                   BUS_IDf, bus_sel);
   2782                 phy_id &= ~(PHY_ID_BUS_UPPER_MASK | PHY_ID_BUS_LOWER_MASK);
   2783             } else
   2784 #endif
   2785 #if defined(BCM_TRX_SUPPORT)
   2786             if (SOC_IS_TRX(unit)) {
   2787                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param,
   2788                                   BUS0_1_SELf, ((phy_id & 0x20) ? 1 : 0));
   2789                 phy_id &= (~0x20);
   2790 
   2791                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param,
   2792                                   BUS2_SELf, ((phy_id & 0x40) ? 1 : 0));
   2793                 phy_id &= (~0x40);
   2794             } else
   2795 #endif
   2796             {
   2797                 soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param, HG_SELf,
   2798                                   ((phy_id & 0x40) ? 1 : 0));
   2799                 phy_id &= (~0x40);
   2800             }
   2801         }
   2802 #endif
   2803 #ifdef BCM_CMICM_SUPPORT
   2804         if(soc_feature(unit, soc_feature_cmicm)) {
   2805             soc_reg_field_set(unit, CMIC_CMC0_MIIM_PARAMr, &phy_param, PHY_IDf, phy_id);
   2806             phy_miim_addr = 0;
   2807             soc_reg_field_set(unit, CMIC_CMC0_MIIM_ADDRESSr, &phy_miim_addr,
   2808                               CLAUSE_45_DTYPEf, phy_devad);
   2809             soc_reg_field_set(unit, CMIC_CMC0_MIIM_ADDRESSr, &phy_miim_addr,
   2810                               CLAUSE_45_REGADRf, phy_reg_addr);
   2811         } else
   2812 #endif
   2813         {
   2814             soc_reg_field_set(unit, CMIC_MIIM_PARAMr, &phy_param, PHY_IDf, phy_id);
   2815             phy_miim_addr = 0;
   2816             soc_reg_field_set(unit, CMIC_MIIM_ADDRESSr, &phy_miim_addr,
   2817                               CLAUSE_45_DTYPEf, phy_devad);
   2818             soc_reg_field_set(unit, CMIC_MIIM_ADDRESSr, &phy_miim_addr,
   2819                               CLAUSE_45_REGADRf, phy_reg_addr);
   2820         }
   2821 
   2822 #ifdef BCM_CMICM_SUPPORT
   2823         if(soc_feature(unit, soc_feature_cmicm)) {
   2824             soc_pci_write(unit, CMIC_CMCx_MIIM_ADDRESS_OFFSET(cmc), phy_miim_addr);
   2825             soc_pci_write(unit, CMIC_CMCx_MIIM_PARAM_OFFSET(cmc), phy_param);
   2826             soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 2);
   2827         } else
   2828 #endif
   2829         {
   2830             WRITE_CMIC_MIIM_ADDRESSr(unit, phy_miim_addr);
   2831             soc_pci_write(unit, CMIC_MIIM_PARAM, phy_param);
   2832             soc_pci_write(unit, CMIC_SCHAN_CTRL, SC_MIIM_RD_START_SET);
   2833         }
   2834 
   2835         /* Wait for completion using either the interrupt or polling method */
   2836 
   2837         if (SOC_CONTROL(unit)->miimIntrEnb) {
   2838 #ifdef BCM_CMICM_SUPPORT
   2839             if(soc_feature(unit, soc_feature_cmicm)) {
   2840                 soc_cmicm_intr0_enable(unit, IRQ_CMCx_MIIM_OP_DONE);
   2841             } else
   2842 #endif
   2843             {
   2844                 soc_intr_enable(unit, IRQ_MIIM_OP_DONE);
   2845             }
   2846 
   2847             if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   2848                              SOC_CONTROL(unit)->miimTimeout) != 0) {
   2849 #ifdef BCM_CMICM_SUPPORT
   2850                 if(soc_feature(unit, soc_feature_cmicm)) {
   2851                     if ((soc_pci_read(unit, CMIC_CMCx_MIIM_STAT_OFFSET(cmc)) &
   2852                                                  CMIC_MIIM_OPN_DONE) == 0) {
   2853                         /* MIIM HW operation not complete */
   2854                         rv = SOC_E_TIMEOUT;
   2855                     } else {
   2856                         /* MIIM HW operation complete but no intr received yet
   2857                          * Retry for MIIM Intr for busy system
   2858                          * before declaring timeout */
   2859                         rv = SOC_E_TIMEOUT;
   2860                         while (miim_intr_retry_cnt) {
   2861                             if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   2862                                              MIIM_INTR_RETRY_TIMEOUT) == 0) {
   2863                                 rv = SOC_E_NONE;
   2864                                 break;
   2865                             }
   2866                             miim_intr_retry_cnt--;
   2867                         }
   2868                     }
   2869                 } else
   2870 #endif
   2871                 {
   2872                     if ((soc_pci_read(unit, CMIC_SCHAN_CTRL) & SC_MIIM_OP_DONE_TST) == 0) {
   2873                         /* MIIM HW operation not complete */
   2874                         rv = SOC_E_TIMEOUT;
   2875                     } else {
   2876                         /* MIIM HW operation complete but no intr received yet
   2877                          * Retry for MIIM Intr for busy system
   2878                          * before declaring timeout */
   2879                         rv = SOC_E_TIMEOUT;
   2880                         while (miim_intr_retry_cnt) {
   2881                             if (sal_sem_take(SOC_CONTROL(unit)->miimIntr,
   2882                                              MIIM_INTR_RETRY_TIMEOUT) == 0) {
   2883                                 rv = SOC_E_NONE;
   2884                                 break;
   2885                             }
   2886                             miim_intr_retry_cnt--;
   2887                         }
   2888                     }
   2889                 }
   2890             } else {
   2891                 LOG_DEBUG(BSL_LS_SOC_MIIM,
   2892                             (BSL_META_U(unit,
   2893                                         "  Interrupt received\n")));
   2894             }
   2895 
   2896 #ifdef BCM_CMICM_SUPPORT
   2897             if(soc_feature(unit, soc_feature_cmicm)) {
   2898                 soc_cmicm_intr0_disable(unit, IRQ_CMCx_MIIM_OP_DONE);
   2899             } else
   2900 #endif
   2901             {
   2902                 soc_intr_disable(unit, IRQ_MIIM_OP_DONE);
   2903             }
   2904         } else {
   2905             soc_timeout_t to;
   2906 
   2907             soc_timeout_init(&to, SOC_CONTROL(unit)->miimTimeout, MIIM_POLL_TIMEOUT);
   2908 
   2909 #ifdef BCM_CMICM_SUPPORT
   2910             if(soc_feature(unit, soc_feature_cmicm)) {
   2911                 while ((soc_pci_read(unit, CMIC_CMCx_MIIM_STAT_OFFSET(cmc)) &
   2912                                              CMIC_MIIM_OPN_DONE) == 0) {
   2913                     if (soc_timeout_check(&to)) {
   2914                         rv = SOC_E_TIMEOUT;
   2915                         break;
   2916                     }
   2917                 }
   2918             } else
   2919 #endif
   2920             {
   2921                 while ((soc_pci_read(unit, CMIC_SCHAN_CTRL) &
   2922                         SC_MIIM_OP_DONE_TST) == 0) {
   2923                     if (soc_timeout_check(&to)) {
   2924                         rv = SOC_E_TIMEOUT;
   2925                         break;
   2926                     }
   2927                 }
   2928             }
   2929 
   2930             if (rv == SOC_E_NONE) {
   2931                 LOG_DEBUG(BSL_LS_SOC_MIIM,
   2932                             (BSL_META_U(unit,
   2933                                         "  Done in %d polls\n"), to.polls));
   2934             }
   2935 #ifdef BCM_CMICM_SUPPORT
   2936             if(soc_feature(unit, soc_feature_cmicm)) {
   2937                 soc_pci_write(unit, CMIC_CMCx_MIIM_CTRL_OFFSET(cmc), 0);
   2938             } else
   2939 #endif
   2940             {
   2941                 soc_pci_write(unit, CMIC_SCHAN_CTRL, SC_MIIM_OP_DONE_CLR);
   2942             }
   2943         }
   2944 
   2945         if (rv == SOC_E_TIMEOUT) {
   2946             LOG_ERROR(BSL_LS_SOC_COMMON,
   2947                       (BSL_META_U(unit,
   2948                                   "MiimTimeOut:soc_miimc45_read, "
   2949                                   "timeout (id=0x%02x addr=0x%02x)\n"),
   2950                        phy_id, phy_reg_addr));
   2951             SOC_CONTROL(unit)->stat.err_mii_tmo++;
   2952         } else {
   2953 #ifdef BCM_CMICM_SUPPORT
   2954             if(soc_feature(unit, soc_feature_cmicm)) {
   2955                 *phy_rd_data = (uint16)soc_pci_read(unit, CMIC_CMCx_MIIM_READ_DATA_OFFSET(cmc));
   2956             } else
   2957 #endif
   2958             {
   2959                 *phy_rd_data = (uint16)soc_pci_read(unit, CMIC_MIIM_READ_DATA);
   2960             }
   2961 
   2962             LOG_VERBOSE(BSL_LS_SOC_MIIM,
   2963                      (BSL_META_U(unit,
   2964                                  "soc_miimc45_read: read data=0x%04x\n"), *phy_rd_data));
   2965         }
   2966 
   2967         /* Release linkscan pause and MIIM lock */
   2968         MIIM_UNLOCK(unit);
   2969 
   2970         if (!soc_feature(unit, soc_feature_linkscan_continuous)) {
   2971            soc_linkscan_continue(unit);
   2972         }
   2973     }
   2974 #endif
   2975 #endif
   2976     return rv;
   2977 
   2978 }
   2979 
   2980 /*
   2981  * Function:
   2982  *      soc_sbus_mdio_write
   2983  * Purpose:
   2984  *      Write to an MII register via CMIC SBUS (S-channel) interface.
   2985  * Parameters:
   2986  *      unit - StrataSwitch Unit #.
   2987  *      phy_id - Phy ID to write (MIIM address)
   2988  *      phy_reg_addr - PHY register to write
   2989  *      phy_wr_data - 32-bit data to write
   2990  * Returns:
   2991  *      SOC_E_XXX
   2992  * Notes:
   2993  *      This function is simply a wrapper for a device-specific implmentation.
   2994  */
   2995 
   2996 int
   2997 soc_sbus_mdio_write(int unit, uint16 phy_id,
   2998                     uint32 phy_reg_addr, uint32 phy_wr_data)
   2999 {
   3000     soc_sbus_mdio_write_f sbus_write;
   3001 
   3002     sbus_write = SOC_FUNCTIONS(unit)->soc_sbus_mdio_write;
   3003     if (sbus_write != NULL) {
   3004         return sbus_write(unit, phy_id, phy_reg_addr, phy_wr_data);
   3005     }
   3006     return SOC_E_UNAVAIL;
   3007 }
   3008 
   3009 /*
   3010  * Function:
   3011  *      soc_sbus_mdio_read
   3012  * Purpose:
   3013  *      Read from an MII register via CMIC SBUS (S-channel) interface.
   3014  * Parameters:
   3015  *      unit - StrataSwitch Unit #.
   3016  *      phy_id - Phy ID to write (MIIM address)
   3017  *      phy_reg_addr - PHY register to write
   3018  *      phy_rd_data - 32-bit data to read into
   3019  * Returns:
   3020  *      SOC_E_XXX
   3021  * Notes:
   3022  *      This function is simply a wrapper for a device-specific implmentation.
   3023  */
   3024 
   3025 int
   3026 soc_sbus_mdio_read(int unit, uint16 phy_id,
   3027                    uint32 phy_reg_addr, uint32 *phy_rd_data)
   3028 {
   3029     soc_sbus_mdio_read_f sbus_read;
   3030 
   3031     sbus_read = SOC_FUNCTIONS(unit)->soc_sbus_mdio_read;
   3032     if (sbus_read != NULL) {
   3033         return sbus_read(unit, phy_id, phy_reg_addr, phy_rd_data);
   3034     }
   3035     return SOC_E_UNAVAIL;
   3036 }
   3037 
   3038 #ifdef PORTMOD_SUPPORT
   3039 /**
   3040  *  @brief generic function for register write for PM4X25,
   3041  *         PM4X10, PM 12X10
   3042  *  @param user_acc - user data. this function expect to get
   3043  *                  portmod_phy_op_data_t structure
   3044  *  @param core_address -  only 5 bits of PHY id used in case
   3045  *                       of sbus
   3046  *  @param reg_addr - the reigister addrress
   3047  *  @param val - the value to write to register. 16 bits value +
   3048  *             16 bits mask
   3049 
   3050  */
   3051 int
   3052 portmod_ext_phy_mdio_c45_reg_read( void* user_acc, uint32_t core_addr, uint32 reg_addr, uint32 *val)
   3053 {
   3054     int rv= SOC_E_NONE;
   3055     portmod_default_user_access_t *user_data = user_acc;
   3056     uint32 phy_id;
   3057     uint16 rd_data; 
   3058  
   3059     phy_id = core_addr;
   3060 
   3061     if(user_data == NULL){
   3062         return SOC_E_PARAM;
   3063     }
   3064 
   3065     if (SOC_IS_SAND(user_data->unit)) {
   3066         rv = soc_dcmn_miim_cl45_read(user_data->unit, phy_id, reg_addr, &rd_data);
   3067     } else {
   3068         rv = soc_esw_miimc45_read(user_data->unit, phy_id, reg_addr, &rd_data);
   3069     }
   3070     
   3071     *val = rd_data;
   3072     return rv;    
   3073  
   3074 }
   3075 
   3076 
   3077 /**
   3078  *  @brief generic function for register write for PM4X25,
   3079  *         PM4X10, PM 12X10
   3080  *  @param user_acc - user data. this function expect to get
   3081  *                  portmod_phy_op_data_t structure
   3082  *  @param core_address -  only 5 bits of PHY id used in case
   3083  *                       of sbus
   3084  *  @param reg_addr - the reigister addrress
   3085  *  @param val - the value to write to register. 16 bits value +
   3086  *             16 bits mask
   3087 
   3088  */
   3089 int
   3090 portmod_ext_phy_mdio_c45_reg_write( void* user_acc, uint32 core_addr, uint32 reg_addr, uint32 val)
   3091 {
   3092     int rv= SOC_E_NONE;
   3093     portmod_default_user_access_t *user_data = user_acc;
   3094     uint32 phy_id;
   3095     uint16 wr_data;    
   3096    
   3097     if(user_data == NULL){
   3098         return SOC_E_PARAM;
   3099     }
   3100 
   3101  
   3102     phy_id = core_addr;
   3103     wr_data = val;
   3104     
   3105     if (SOC_IS_SAND(user_data->unit)) {
   3106         rv = soc_dcmn_miim_cl45_write(user_data->unit, phy_id, reg_addr, wr_data);
   3107     } else {
   3108         if(SOC_WARM_BOOT(user_data->unit)) {
   3109             rv = soc_esw_miimc45_wb_write(user_data->unit, phy_id, reg_addr, wr_data);
   3110         } else {
   3111             rv = soc_esw_miimc45_write(user_data->unit, phy_id, reg_addr, wr_data);
   3112         }
   3113     }
   3114     return rv;
   3115 }
   3116 
   3117 #endif /* PORTMOD_SUPPORT */