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

phy8072.c (70555B)


      1 
      2 /*
      3  * 
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * File:        phy8072.c
      9  * Purpose:    Phys Driver support for Broadcom 8072 Serial 10Gig
     10  *             transceiver with XAUI interface.
     11  */
     12 
     13 #include <sal/types.h>
     14 #include <shared/bsl.h>
     15 #include <soc/drv.h>
     16 #include <soc/debug.h>
     17 #include <soc/error.h>
     18 #include <soc/phyreg.h>
     19 
     20 #include <soc/phy.h>
     21 #include <soc/phy/phyctrl.h>
     22 #include <soc/phy/drv.h>
     23 
     24 #include "phydefs.h"      /* Must include before other phy related includes */
     25 
     26 #if defined(INCLUDE_PHY_8072)
     27 #include "phyconfig.h"    /* Must be the first phy include after phydefs.h */
     28 #include "phyident.h"
     29 #include "phyreg.h"
     30 #include "phynull.h"
     31 #include "phyxehg.h"
     32 #include "phy8072.h"
     33 
     34 #define PHY_ID1_8072    0x6035
     35 #define PHY_ID1_8073    0x6036
     36 #define PHY_ID1_8074    0x6036
     37 #define PHY_8073_A0     0x0000
     38 #define PHY_8073_A1     0x0001
     39 
     40 #define PHY_8072_PMA_PMD_LOOPBACK       1
     41 #if 0
     42 #define PHY_8072_PCS_LOOPBACK           1
     43 #define PHY_8072_SYSTEM_LOOPBACK        1
     44 #define PHY_8072_XAUI_LOOPBACK          1
     45 #endif
     46 
     47 #define APPLY_SNR_PATCH(dev, ver) \
     48     ((dev == PHY_8073_A1) && (ver == 0x0102)) ||     \
     49     ((dev == PHY_8073_A0) && ((ver == 0x0101) || (ver == 0x0102)))
     50 
     51 /*
     52  * SPI-ROM Program related defs
     53  */
     54 #define SPI_CTRL_1_L        0xC000
     55 #define SPI_CTRL_1_H        0xC002
     56 #define SPI_CTRL_2_L        0xC400
     57 #define SPI_CTRL_2_H        0xC402
     58 #define SPI_TXFIFO          0xD000
     59 #define SPI_RXFIFO          0xD400                                                                                 
     60 #define WR_CPU_CTRL_REGS    0x11
     61 #define RD_CPU_CTRL_REGS    0xEE
     62 #define WR_CPU_CTRL_FIFO    0x66
     63 /*
     64  * SPI Controller Commands(Messages).
     65  */
     66 #define MSGTYPE_HWR          0x40
     67 #define MSGTYPE_HRD          0x80
     68 #define WRSR_OPCODE          0x01
     69 #define WR_OPCODE            0x02
     70 #define WRDI_OPCODE          0x04
     71 #define RDSR_OPCODE          0x05
     72 #define WREN_OPCODE          0x06
     73 #define WR_BLOCK_SIZE        0x40
     74 #define TOTAL_WR_BYTE        0x4000
     75                                                                                 
     76 #define WR_TIMEOUT   1000000
     77 static int write_message(int unit, phy_ctrl_t *pc, uint16 wrdata, uint16 * rddata);
     78 
     79 STATIC int phy_8072_ability_local_get(int, soc_port_t, soc_port_ability_t *);
     80 STATIC int phy_8072_speed_get(int, soc_port_t, int *);
     81 STATIC int phy_8072_ability_advert_set(int, soc_port_t, soc_port_ability_t *);
     82 STATIC int phy_8072_an_get(int, soc_port_t, int *, int *);
     83 
     84 
     85 STATIC int
     86 _8072_rom_load(int unit,phy_ctrl_t * pc,int phy_id1)
     87 {
     88     if (phy_id1 == PHY_ID1_8072) {
     89         /* reset the device */
     90         SOC_IF_ERROR_RETURN
     91              (MODIFY_PHY8072_PMA_PMD_CTRLr(unit, pc,
     92                                           MII_CTRL_RESET, MII_CTRL_RESET));
     93                                                                                      
     94         /* Wait 200ms after PCB reboot, for internal ROM load to finish */
     95         sal_usleep(200000);
     96 
     97         SOC_IF_ERROR_RETURN
     98             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xca85, 0x0001));
     99         sal_usleep(1000);
    100         SOC_IF_ERROR_RETURN
    101             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, PMAD_GEN_CTRL_STAT_REG, 
    102                                        0x0188));
    103         sal_usleep(1000);
    104         SOC_IF_ERROR_RETURN
    105             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, PMAD_GEN_CTRL_STAT_REG, 
    106                                        0x018a));
    107         sal_usleep(1000);
    108         SOC_IF_ERROR_RETURN
    109             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, PMAD_GEN_CTRL_STAT_REG, 
    110                                        0x0188));
    111         /*
    112          * Wait for atleast 100ms for code to download via SPI port
    113          */
    114         sal_usleep(200000);
    115         SOC_IF_ERROR_RETURN
    116             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xca85, 0x0000));
    117         sal_usleep(1000);
    118                                                                                 
    119     } else if (phy_id1 == PHY_ID1_8073) {
    120         /* reset the device */
    121         SOC_IF_ERROR_RETURN
    122             (MODIFY_PHY8072_PMA_PMD_CTRLr(unit, pc,
    123                                           MII_CTRL_RESET, MII_CTRL_RESET));
    124 
    125         /* no delay is needed for 8073 per chip designer*/                                              
    126         SOC_IF_ERROR_RETURN
    127             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, PMAD_GEN_CTRL_STAT_REG, 
    128                                        0x0001));
    129         SOC_IF_ERROR_RETURN
    130             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, PMAD_GEN_CTRL_STAT_REG, 
    131                                        0x008C));
    132         SOC_IF_ERROR_RETURN
    133             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xCA85, 0x0001));
    134         SOC_IF_ERROR_RETURN
    135             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, PMAD_GEN_CTRL_STAT_REG, 
    136                                        0x018A));
    137         SOC_IF_ERROR_RETURN
    138             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, PMAD_GEN_CTRL_STAT_REG, 
    139                                        0x0188));
    140 
    141         /*
    142          * Wait for atleast 100ms for code to download via SPI port
    143          */
    144         sal_usleep(200000);
    145         SOC_IF_ERROR_RETURN
    146             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xca85, 0x0000));
    147         sal_usleep(1000);
    148     }
    149     return SOC_E_NONE;
    150                                                                                 
    151 }
    152 
    153 STATIC int
    154 _8074_rom_load(int unit,phy_ctrl_t * pc,int phy_id1)
    155 {
    156     uint16 phy_addr;
    157     int i;
    158 
    159     phy_addr = pc->phy_id & 0xfffc;
    160     for(i = 0; i < 4; i++) {
    161         /* Disable SPI for all ports, return value ignored on purpose */
    162         pc->write(unit, phy_addr+i,SOC_PHY_CLAUSE45_ADDR(1, 0xc843), 0x000f);
    163         pc->write(unit, phy_addr+i,SOC_PHY_CLAUSE45_ADDR(1, 0xc840), 0x000C);
    164 
    165         /* Set bit SPI Download (15), SER Boot (14) And SPI Port Enable (0) In C848, SPI_PORT_CTRL */
    166         pc->write(unit, phy_addr+i,SOC_PHY_CLAUSE45_ADDR(1, 0xc848), 0xC0F1);
    167     }
    168 
    169     /* Place Micro in reset */
    170     SOC_IF_ERROR_RETURN
    171         (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xca10, 0x018f));
    172 
    173     /* Enable SPI */
    174     SOC_IF_ERROR_RETURN
    175         (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xc843, 0x0000));
    176     SOC_IF_ERROR_RETURN
    177         (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xc840, 0x0000));
    178 
    179     /* Remove M8051 resets */
    180     SOC_IF_ERROR_RETURN
    181         (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xca10, 0x0188));
    182 
    183     /* The rest is moved outside this routine. */
    184     return SOC_E_NONE;
    185 }
    186 
    187 STATIC int
    188 _8073_A0_xaui_check(int unit, int port)
    189 {
    190     uint8 count;
    191     uint16 data16;
    192     phy_ctrl_t *pc;
    193     soc_timeout_t  to;
    194     sal_usecs_t start, end;
    195     pc = EXT_PHY_SW_STATE(unit, port);
    196 
    197     /*
    198      * Get the Chip revision or chip id
    199      * XAUI Workaround is not needed for Rev A1 and 8074 device
    200      */
    201 
    202     SOC_IF_ERROR_RETURN
    203         (READ_PHY8072_PMA_PMD_REG(unit, pc, PMAD_CHIP_REV_REG, &data16));
    204     if (data16 == PHY_8073_A1) {
    205         return SOC_E_NONE;
    206     }
    207 
    208     SOC_IF_ERROR_RETURN
    209         (READ_PHY8072_PMA_PMD_REG(unit,pc,0xC802,&data16));
    210     if ( data16 == 0x8074) {
    211         return SOC_E_NONE;
    212     }
    213 
    214     SOC_IF_ERROR_RETURN
    215         (READ_PHY8072_PMA_PMD_REG(unit, pc, PMAD_USR_STATUS_REG, &data16));
    216 
    217     if (!PMAD_STATUS_AN_10G(data16)) {
    218         return SOC_E_NONE;
    219     }
    220 
    221     start = sal_time_usecs();
    222     LOG_INFO(BSL_LS_SOC_PHY,
    223              (BSL_META_U(unit,
    224                          "xaui w/a in progress \n")));
    225     for (count = 0; count < 12; count++) {
    226         soc_timeout_init(&to, 5000000, 0);
    227         LOG_INFO(BSL_LS_SOC_PHY,
    228                  (BSL_META_U(unit,
    229                              ".")));
    230         do {
    231             SOC_IF_ERROR_RETURN
    232                 (READ_PHY8072_PMA_PMD_REG(unit, pc, PMAD_USR_STATUS_REG, 
    233                               &data16));
    234         if (!(data16 & PMAD_STATUS_1G_LINKDOWN) || 
    235             !(data16 & PMAD_STATUS_2p5G_LINKDOWN)) {
    236                 return SOC_E_NONE;
    237         } else if (!(data16 & PMAD_STATUS_10G_LINKDOWN)) {
    238                 SOC_IF_ERROR_RETURN
    239                     (READ_PHY8072_PMA_PMD_REG(unit, pc, 0xC841, &data16));
    240                 if (data16 & (1<<15)) {
    241                     end = sal_time_usecs();
    242                     LOG_INFO(BSL_LS_SOC_PHY,
    243                              (BSL_META_U(unit,
    244                                          "\nxaui w/a completed successfully u=%d,p=%d"
    245                                          " time taken = %d\n"), unit, port,
    246                               SAL_USECS_SUB(end, start)));
    247                     return SOC_E_NONE;
    248                 }
    249             }
    250         } while (!soc_timeout_check(&to));
    251     }
    252 
    253     LOG_WARN(BSL_LS_SOC_PHY,
    254              (BSL_META_U(unit,
    255                          "\nWarning! : u=%d, p=%d:"
    256                          "8073A0 XAUI Work Around may not have completed\n"), unit, port));
    257 
    258     SOC_IF_ERROR_RETURN /* Restart AN ..HP*/
    259         (WRITE_PHY8072_AN_REG(unit, pc, AN_CTRL_REG, AN_ENABLE|AN_RESTART)); 
    260 
    261     return SOC_E_NONE;
    262 }
    263 
    264 /* Function:
    265  *    phy_8072_init
    266  * Purpose:    
    267  *    Initialize 8072 phys
    268  * Parameters:
    269  *    unit - StrataSwitch unit #.
    270  *    port - StrataSwitch port #. 
    271  * Returns:    
    272  *    SOC_E_NONE
    273  */
    274 
    275 STATIC int
    276 phy_8072_init(int unit, soc_port_t port)
    277 {
    278     soc_timeout_t  to;
    279     int            rv;
    280     uint16         data16;
    281     phy_ctrl_t     *pc;
    282     uint32	   phy_ext_rom_boot;	 
    283     soc_port_ability_t  ability;
    284     int phy_8074;
    285 
    286     pc = EXT_PHY_SW_STATE(unit, port);
    287     
    288     PHY_FLAGS_SET(unit, port,  PHY_FLAGS_FIBER | PHY_FLAGS_C45);
    289 
    290     phy_ext_rom_boot = soc_property_port_get(unit, port, spn_PHY_EXT_ROM_BOOT, 1);
    291 
    292     phy_8074 = FALSE;
    293 
    294     if (phy_ext_rom_boot) {
    295 
    296         if (pc->phy_id1 == PHY_ID1_8073) {
    297             uint16  data;
    298             /* Check register 0xc802 to find out if it is a real 8074 device. */
    299             SOC_IF_ERROR_RETURN
    300                 (READ_PHY8072_PMA_PMD_REG(unit,pc,0xC802,&data));
    301             if ( data == 0x8074 ) {
    302                 phy_8074 = TRUE;
    303                 _8074_rom_load(unit,pc,pc->phy_id1);
    304             } else {
    305                 _8072_rom_load(unit,pc,pc->phy_id1);
    306             }
    307 
    308         } else {
    309             _8072_rom_load(unit,pc,pc->phy_id1);
    310         }
    311 
    312         /* Make sure SPI-ROM load is complete */
    313         soc_timeout_init(&to, 500000, 0);
    314         do {
    315             rv = (READ_PHY8072_GENREG1r(unit, pc, &data16));
    316             if (((data16 & 0xFFF0) == PMDA_ROM_LOAD_8072ID) || 
    317                 ((data16 & 0xFFF0) == PMDA_ROM_LOAD_8073ID) ||  
    318                  SOC_FAILURE(rv)) {
    319                 break;
    320             }
    321         } while (!soc_timeout_check(&to));
    322 
    323         if (phy_8074) {
    324             SOC_IF_ERROR_RETURN
    325                 (MODIFY_PHY8072_PMA_PMD_REG(unit, pc, 0xc843, 0x000f, 0x000f));
    326             SOC_IF_ERROR_RETURN
    327                 (MODIFY_PHY8072_PMA_PMD_REG(unit, pc, 0xc840, 0x000c, 0x000c));
    328         }
    329 
    330         SOC_IF_ERROR_RETURN
    331             (READ_PHY8072_GENREG1r(unit, pc,&data16));
    332         if (PMDA_ROM_LOAD_8072ID == (data16 & 0xFFF0) || 
    333             PMDA_ROM_LOAD_8073ID == (data16 & 0xFFF0)) {
    334             SOC_IF_ERROR_RETURN
    335                 (READ_PHY8072_PMA_PMD_REG(unit, pc, 0xCA1A,&data16));
    336             LOG_CLI((BSL_META_U(unit,
    337                                 "8072: u=%d p=%d external rom boot complete f/w ver. "
    338                                 "0x%x: init.\n"),
    339                      unit, port,data16));
    340 
    341         } else {
    342             LOG_WARN(BSL_LS_SOC_PHY,
    343                      (BSL_META_U(unit,
    344                                  "ROM_CODE read : u=%d p=%d 0x%x Expected 0xBCB0\n"),
    345                       unit, port, data16));
    346         }
    347 
    348         if (pc->phy_id1 == PHY_ID1_8073) {
    349             uint16 dev_rev;
    350             uint16 snr_val;
    351             uint16 rom_ver;
    352 
    353             SOC_IF_ERROR_RETURN
    354                 (READ_PHY8072_PMA_PMD_REG(unit, pc, PMAD_CHIP_REV_REG,
    355                                           &dev_rev));
    356             SOC_IF_ERROR_RETURN
    357                 (READ_PHY8072_PMA_PMD_REG(unit, pc, PMAD_GEN2_REG, &rom_ver));
    358             /*
    359              * Dis/En Tx to avoid Autoneg stuck for A1 devices.
    360              */
    361             if (dev_rev == PHY_8073_A1 || dev_rev == PHY_8073_A0) {
    362                 SOC_IF_ERROR_RETURN
    363                    (MODIFY_PHY8072_PMA_PMD_REG(unit, pc, 0xCA02, 0x400, 0x400));
    364                 sal_usleep(1000000);
    365                 SOC_IF_ERROR_RETURN
    366                    (MODIFY_PHY8072_PMA_PMD_REG(unit, pc, 0xCA02, 0x000, 0x400));
    367             }
    368 
    369             SOC_IF_ERROR_RETURN
    370                 (MODIFY_PHY8072_PMA_PMD_REG(unit, pc, 0xCA1B, 0x1000, 0x1000));
    371 
    372             sal_usleep(10000);
    373             /*
    374              * SNR Improvement: Change FFE main cursor to 5.
    375              */
    376             if (APPLY_SNR_PATCH(dev_rev, rom_ver)) {
    377                 snr_val = (dev_rev == PHY_8073_A0) ? 0xFA0C : 0xFB0C;
    378                 SOC_IF_ERROR_RETURN
    379                     (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xCA1B, snr_val));
    380             }
    381             SOC_IF_ERROR_RETURN /* FEC Advert Enable */
    382                 (MODIFY_PHY8072_AN_REG(unit, pc, AN_ADVERT_2_REG, 
    383                                  AN_ADVERT_FEC, AN_ADVERT_FEC));
    384         }
    385     }
    386 
    387     SOC_IF_ERROR_RETURN /* Restart AN */
    388         (WRITE_PHY8072_AN_REG(unit, pc, AN_CTRL_REG, AN_ENABLE|AN_RESTART)); 
    389 
    390     if (pc->phy_id1 == PHY_ID1_8073) {
    391         sal_usleep(50000);
    392 
    393             /* XAUI Workaround */
    394         SOC_IF_ERROR_RETURN(_8073_A0_xaui_check(unit, port));
    395     }
    396 
    397     /* fix for PHY-443 */
    398     SOC_IF_ERROR_RETURN
    399         (MODIFY_PHY8072_PHYXS_REG(unit, pc, 0x8111, 1 << 3, 1 << 3));
    400 
    401     /* Set Local Advertising Configuration */
    402     SOC_IF_ERROR_RETURN
    403         (phy_8072_ability_local_get(unit, port, &ability));
    404     SOC_IF_ERROR_RETURN
    405         (phy_8072_ability_advert_set(unit, port, &ability));
    406                                                                                 
    407     LOG_INFO(BSL_LS_SOC_PHY,
    408              (BSL_META_U(unit,
    409                          "8072: u=%d port%d: init.\n"), unit, port));
    410 
    411     return SOC_E_NONE;
    412 }
    413 
    414 
    415 /*
    416  * Function:
    417  *    phy_8072_link_get
    418  * Purpose:
    419  *    Get layer2 connection status.
    420  * Parameters:
    421  *    unit - StrataSwitch unit #.
    422  *    port - StrataSwitch port #. 
    423  *      link - address of memory to store link up/down state.
    424  * Returns:    
    425  *    SOC_E_NONE
    426  */
    427 
    428 STATIC int
    429 phy_8072_link_get(int unit, soc_port_t port, int *link)
    430 {
    431     uint16      pma_mii_stat, pcs_mii_stat, link_stat,speed_val;
    432     phy_ctrl_t *pc;
    433     int an = 0,an_done = 0,cur_speed;
    434 
    435     if (link == NULL) {
    436         return SOC_E_NONE;
    437     }
    438 
    439     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
    440         *link = FALSE;
    441         return SOC_E_NONE;
    442     }
    443 
    444     pc = EXT_PHY_SW_STATE(unit, port);
    445 
    446     phy_8072_an_get(unit,port,&an,&an_done);
    447 
    448     /* return link false if in the middle of autoneg */
    449     if (an == TRUE && an_done == FALSE) {
    450         *link = FALSE;
    451         return SOC_E_NONE;
    452     } 
    453 
    454     /* check if the current speed is set to 10G */
    455     cur_speed = 0;
    456     if (an) { /* autoneg is enabled */
    457         SOC_IF_ERROR_RETURN
    458             (READ_PHY8072_AN_REG(unit, pc, AN_ETH_STATUS_REG, &speed_val));
    459         if (speed_val & AN_SPEED_10GBASE_KR) {
    460             cur_speed = 10000;
    461         }
    462     } else { /* force mode */
    463         SOC_IF_ERROR_RETURN
    464             (READ_PHY8072_PMA_PMD_REG(unit,pc,PMAD_CTRL2_REG, &speed_val));
    465         if ((speed_val & PMAD_CTRL2r_PMA_TYPE_MASK)==PMAD_CTRL2r_PMA_TYPE_10G) {
    466             cur_speed = 10000;
    467         }
    468     }
    469 
    470     if (cur_speed == 10000) { /* check all 2 device's link status if 10G */
    471         /* Receive Link status */
    472         SOC_IF_ERROR_RETURN
    473             (READ_PHY8072_PCS_STATr(unit, pc, &pcs_mii_stat));
    474     }
    475 
    476     SOC_IF_ERROR_RETURN
    477         (READ_PHY8072_PMA_PMD_STATr(unit, pc, &pma_mii_stat));
    478 
    479     link_stat = (cur_speed == 10000)?
    480                  pma_mii_stat & pcs_mii_stat:
    481                  pma_mii_stat;
    482 
    483     *link = (link_stat & MII_STAT_LA) ? TRUE : FALSE;
    484 
    485     return SOC_E_NONE;
    486 }
    487 
    488 /*
    489  * Function:
    490  *    phy_8072_enable_set
    491  * Purpose:
    492  *    Enable/Disable phy 
    493  * Parameters:
    494  *    unit - StrataSwitch unit #.
    495  *    port - StrataSwitch port #. 
    496  *      enable - on/off state to set
    497  * Returns:    
    498  *    SOC_E_NONE
    499  */
    500 
    501 STATIC int
    502 phy_8072_enable_set(int unit, soc_port_t port, int enable)
    503 {
    504     uint16      data;       /* Holder for new value to write to PHY reg */
    505     uint16      mask;       /* Holder for bit mask to update in PHY reg */
    506     phy_ctrl_t *pc;
    507 
    508     pc = EXT_PHY_SW_STATE(unit, port);
    509 
    510     data = 0;
    511     mask = 1 << 0; /* Global PMD transmit disable */
    512     if (enable) {
    513         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
    514     } else {
    515         data = 1 << 0;  /* Global PMD transmit disable */
    516         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
    517     }
    518 
    519     SOC_IF_ERROR_RETURN
    520         (MODIFY_PHY8072_PMA_PMD_TX_DISABLEr(unit, pc, data, mask));
    521     return (SOC_E_NONE);
    522 }
    523 
    524 /*
    525  * Function:
    526  *    phy_8072_lb_set
    527  * Purpose:
    528  *    Put 8072 in PHY PCS/PMA/PMD loopback
    529  * Parameters:
    530  *    unit - StrataSwitch unit #.
    531  *    port - StrataSwitch port #. 
    532  *      enable - binary value for on/off (1/0)
    533  * Returns:    
    534  *    SOC_E_NONE
    535  */
    536 
    537 STATIC int
    538 phy_8072_lb_set(int unit, soc_port_t port, int enable)
    539 {
    540     phy_ctrl_t *pc; 
    541     uint16     tmp;
    542 
    543     pc = EXT_PHY_SW_STATE(unit, port);
    544 
    545 #if defined(PHY_8072_PCS_LOOPBACK)
    546     tmp = enable ? MII_CTRL_LE : 0;
    547 
    548     SOC_IF_ERROR_RETURN
    549         (MODIFY_PHY8072_PCS_CTRLr(unit, pc, tmp, MII_CTRL_LE));
    550 #endif /* PHY_8072_PCS_LOOPBACK */
    551 
    552 #if defined(PHY_8072_PMA_PMD_LOOPBACK)
    553     tmp = enable ? MII_CTRL_PMA_LOOPBACK : 0;
    554 
    555     SOC_IF_ERROR_RETURN
    556         (MODIFY_PHY8072_PMA_PMD_CTRLr(unit, pc,
    557                                       tmp, MII_CTRL_PMA_LOOPBACK));
    558 #endif /* PHY_8072_PMA_PMD_LOOPBACK */
    559 
    560 #if defined(PHY_8072_SYSTEM_LOOPBACK)
    561 
    562    tmp = enable? XGXS_MODE_SYSTEM_LOOPBACK | XGXS_CTRL_RLOOP
    563          :XGXS_MODE_NORMAL;    
    564    SOC_IF_ERROR_RETURN
    565        (MODIFY_PHY8072_PHYXS_REG(unit,pc,XGXS_MODE_CTRLr,
    566                      tmp,
    567                      XGXS_MODE_MASK | XGXS_CTRL_RLOOP)); 
    568 
    569 #endif /* PHY_8072_SYSTEM_LOOPBACK */
    570 
    571 #if defined(PHY_8072_XAUI_LOOPBACK)
    572    SOC_IF_ERROR_RETURN
    573         (READ_PHY8072_PHYXS_REG(unit, pc, PHYXS_MODE_CTRL_REG, &tmp));
    574     tmp &= ~(0xf << 8);
    575     tmp |= ((enable) ? 6 : 1) << 8;
    576     SOC_IF_ERROR_RETURN
    577         (WRITE_PHY8072_PHYXS_REG(unit, pc, PHYXS_MODE_CTRL_REG, tmp));
    578 
    579     tmp = (enable) ? (0x00f0) : (0x0000);
    580     SOC_IF_ERROR_RETURN
    581         (WRITE_PHY8072_PHYXS_REG(unit, pc, 0x8017, tmp));
    582 #endif /* PHY_8072_XAUI_LOOPBACK */
    583 
    584     return SOC_E_NONE;
    585 }
    586 
    587 /*
    588  * Function:
    589  *    phy_8072_lb_get
    590  * Purpose:
    591  *    Get 8072 PHY loopback state
    592  * Parameters:
    593  *    unit - StrataSwitch unit #.
    594  *    port - StrataSwitch port #. 
    595  *      enable - address of location to store binary value for on/off (1/0)
    596  * Returns:    
    597  *    SOC_E_NONE
    598  */
    599 
    600 STATIC int
    601 phy_8072_lb_get(int unit, soc_port_t port, int *enable)
    602 {
    603     uint16      tmp;
    604     phy_ctrl_t *pc;
    605 
    606     pc = EXT_PHY_SW_STATE(unit, port);
    607 
    608 #if defined(PHY_8072_PCS_LOOPBACK)
    609     SOC_IF_ERROR_RETURN
    610         (READ_PHY8072_PCS_CTRLr(unit, pc, &tmp));
    611 
    612     *enable = (tmp & MII_CTRL_LE) ? TRUE : FALSE;
    613 #endif /* PHY_8072_PCS_LOOPBACK */
    614 
    615 
    616 
    617 #if defined(PHY_8072_PMA_PMD_LOOPBACK)
    618     SOC_IF_ERROR_RETURN
    619         (READ_PHY8072_PMA_PMD_CTRLr(unit, pc, &tmp));
    620 
    621     *enable = (tmp & MII_CTRL_PMA_LOOPBACK) ? TRUE : FALSE;
    622 #endif /* PHY_8072_PMA_PMD_LOOPBACK */
    623 
    624 #if defined(PHY_8072_SYSTEM_LOOPBACK)
    625    SOC_IF_ERROR_RETURN
    626        (READ_PHY8072_PHYXS_REG(unit,pc,XGXS_MODE_CTRLr,&tmp));
    627    *enable = (tmp & XGXS_MODE_MASK)? FALSE:TRUE;
    628 #endif /* PHY_8072_SYSTEM_LOOPBACK */
    629 
    630 #if defined(PHY_8072_XAUI_LOOPBACK)
    631     SOC_IF_ERROR_RETURN
    632         (READ_PHY8072_PHYXS_REG(unit, pc, PHYXS_MODE_CTRL_REG, &tmp));
    633     *enable = ((tmp & (0xf << 8)) == (6 << 8));
    634 #endif /* PHY_8072_XAUI_LOOPBACK */
    635 
    636     LOG_INFO(BSL_LS_SOC_PHY,
    637              (BSL_META_U(unit,
    638                          "phy_8072_lb_get: u=%d port%d: loopback:%s\n"),
    639               unit, port, *enable ? "Enabled": "Disabled"));
    640     
    641     return SOC_E_NONE;
    642 }
    643 
    644 
    645 STATIC int
    646 phy_8072_linkup_evt(int unit, soc_port_t port)
    647 {
    648     phy_ctrl_t *pc;    /* PHY software state */
    649     uint16 dev_rev;
    650     uint16 snr_val;
    651     uint16 rom_ver;
    652     uint16 link;
    653 
    654     pc = EXT_PHY_SW_STATE(unit, port);
    655     SOC_IF_ERROR_RETURN(_8073_A0_xaui_check(unit, port));
    656 
    657     if (pc->phy_id1 == PHY_ID1_8072) {
    658         return SOC_E_NONE;
    659     }
    660     SOC_IF_ERROR_RETURN
    661         (READ_PHY8072_PMA_PMD_REG(unit, pc, PMAD_CHIP_REV_REG, &dev_rev));
    662     SOC_IF_ERROR_RETURN
    663         (READ_PHY8072_PMA_PMD_REG(unit, pc, PMAD_GEN2_REG, &rom_ver));
    664     if(APPLY_SNR_PATCH(dev_rev, rom_ver)) {
    665         /*
    666         * Change CDR Bandwidth.
    667         */
    668         SOC_IF_ERROR_RETURN
    669             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xCA46, 0x0333));
    670         /*
    671         * Change PLL Bandwidth.
    672         */
    673         SOC_IF_ERROR_RETURN
    674             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xCA1D, 0x26BC));
    675         /*
    676         * SNR Improvement.
    677         */
    678         snr_val = (dev_rev == PHY_8073_A0) ? 0xFA0C : 0xFB0C;
    679         SOC_IF_ERROR_RETURN
    680             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xCA1B, snr_val));
    681     }
    682     SOC_IF_ERROR_RETURN
    683         (READ_PHY8072_PMA_PMD_REG(unit, pc, PMAD_USR_STATUS_REG, &link));
    684 
    685     /* if autoneg to 10G, sync up the serdes's speed in case it's not done*/
    686     if (PMAD_STATUS_AN_10G(link)) {
    687         SOC_IF_ERROR_RETURN
    688             (soc_phyctrl_notify(unit, port, phyEventSpeed, 10000));
    689     }
    690     LOG_INFO(BSL_LS_SOC_PHY,
    691              (BSL_META_U(unit,
    692                          "phy_8072_linkup_evt: u=%d p=%d\n"),
    693               unit, port));
    694     return SOC_E_NONE;
    695 }
    696 
    697 STATIC int
    698 _phy_8072_control_tx_driver_set(int unit, soc_port_t port,
    699                                 soc_phy_control_t type, uint32 value)
    700 {
    701     uint16       data;  /* Temporary holder of reg value to be written */
    702     uint16       mask;  /* Bit mask of reg value to be updated */
    703     phy_ctrl_t  *pc;    /* PHY software state */
    704 
    705     pc = EXT_PHY_SW_STATE(unit, port);
    706 
    707     /* Dozen SerDes */
    708     switch(type) {
    709     case SOC_PHY_CONTROL_PREEMPHASIS:
    710          data = (uint16)(value & 0xf);
    711          data = data << 12;
    712          mask = 0xf000;
    713          break;
    714     case SOC_PHY_CONTROL_DRIVER_CURRENT:
    715          data = (uint16)(value & 0xf);
    716          data = data << 8;
    717          mask = 0x0f00;
    718          break;
    719     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
    720          data = (uint16)(value & 0xf);
    721          data = data << 4;
    722          mask = 0x00f0;
    723          break;
    724     default:
    725          /* should never get here */
    726          return SOC_E_PARAM;
    727     }
    728     SOC_IF_ERROR_RETURN
    729         (MODIFY_PHY8072_TXA_ACTRL_3r(unit, pc, data, mask));
    730 
    731     return SOC_E_NONE;
    732 }
    733 
    734 STATIC int
    735 _phy_8072_control_tx_driver_get(int unit, soc_port_t port,
    736                                 soc_phy_control_t type, uint32 *value)
    737 {
    738     uint16         data16;   /* Temporary holder of a reg value */
    739     phy_ctrl_t    *pc;       /* PHY software state */
    740 
    741     pc = EXT_PHY_SW_STATE(unit, port);
    742 
    743     data16 = 0;
    744     SOC_IF_ERROR_RETURN
    745         (READ_PHY8072_TXA_ACTRL_3r(unit, pc, &data16));
    746     switch(type) {
    747     case SOC_PHY_CONTROL_PREEMPHASIS:
    748          *value = (data16 & 0xf000) >> 12;
    749          break;
    750     case SOC_PHY_CONTROL_DRIVER_CURRENT:
    751          *value = (data16 & 0x0f00) >> 8;
    752          break;
    753     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
    754          *value = (data16 & 0x00f0) >> 4;
    755          break;
    756     default:
    757          /* should never get here */
    758          return SOC_E_PARAM;
    759     }
    760 
    761     return SOC_E_NONE;
    762 }
    763 
    764 /*
    765  * Function:
    766  *      phy_8072_control_set
    767  * Purpose:
    768  *      Configure PHY device specific control fucntion.
    769  * Parameters:
    770  *      unit  - StrataSwitch unit #.
    771  *      port  - StrataSwitch port #.
    772  *      type  - Control to update
    773  *      value - New setting for the control
    774  * Returns:
    775  *      SOC_E_NONE
    776  */
    777 STATIC int
    778 phy_8072_control_set(int unit, soc_port_t port,
    779                      soc_phy_control_t type, uint32 value)
    780 {
    781     int rv;
    782 
    783     PHY_CONTROL_TYPE_CHECK(type);
    784 
    785     rv = SOC_E_UNAVAIL;
    786     switch(type) {
    787     case SOC_PHY_CONTROL_PREEMPHASIS:
    788         /* fall through */
    789     case SOC_PHY_CONTROL_DRIVER_CURRENT:
    790         /* fall through */
    791     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
    792         rv = _phy_8072_control_tx_driver_set(unit, port, type, value);
    793         break;
    794     default:
    795         rv = SOC_E_UNAVAIL;
    796         break;
    797     }
    798     return rv;
    799 }
    800 /*
    801  * Function:
    802  *      phy_8072_control_get
    803  * Purpose:
    804  *      Get current control settign of the PHY.
    805  * Parameters:
    806  *      unit  - StrataSwitch unit #.
    807  *      port  - StrataSwitch port #.
    808  *      type  - Control to update
    809  *      value - (OUT)Current setting for the control
    810  * Returns:
    811  *      SOC_E_NONE
    812  */
    813 STATIC int
    814 phy_8072_control_get(int unit, soc_port_t port,
    815                      soc_phy_control_t type, uint32 *value)
    816 {
    817     int rv;
    818 
    819     PHY_CONTROL_TYPE_CHECK(type);
    820 
    821     rv = SOC_E_UNAVAIL;
    822     switch(type) {
    823     case SOC_PHY_CONTROL_PREEMPHASIS:
    824         /* fall through */
    825     case SOC_PHY_CONTROL_DRIVER_CURRENT:
    826         /* fall through */
    827     case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT:
    828         rv = _phy_8072_control_tx_driver_get(unit, port, type, value);
    829         break;
    830     default:
    831         rv = SOC_E_UNAVAIL;
    832         break;
    833     }
    834 
    835     return rv;
    836 }
    837 
    838 /*
    839  * Function:
    840  *      phy_8072_probe
    841  * Purpose:
    842  *      Complement the generic phy probe routine to identify this phy when its
    843  *      phy id0 and id1 is same as some other phy's.  
    844  * Parameters:
    845  *      unit - StrataSwitch unit #.
    846  *      pc   - phy ctrl descriptor.
    847  * Returns:
    848  *      SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error>
    849  */
    850                                                                                       
    851 
    852 STATIC int
    853 phy_8072_probe(int unit, phy_ctrl_t *pc)
    854 {
    855     uint16 data0 = 0;
    856     uint16 data1 = 0;
    857 
    858     if (soc_property_port_get(unit, pc->port, spn_PHY_8072, FALSE)) {
    859         return SOC_E_NONE;
    860     }
    861 
    862     /* device 8072 and 8073 has different id1, but uses the same driver. 
    863      * First check if the device's id1 matches 8073.
    864      */
    865     SOC_IF_ERROR_RETURN
    866         (READ_PHY8072_PMA_PMD_REG(unit,pc,PMAD_ID1_REG,&data1));
    867 
    868     if (data1 == PHY_ID1_8073) {
    869 
    870         /* PHY 8727 has the same phyid1, check register 0xc802 to find out if
    871          * it is a real 8073 or 8074 device.
    872          */
    873         SOC_IF_ERROR_RETURN
    874             (READ_PHY8072_PMA_PMD_REG(unit,pc,0xC802,&data1));
    875         if (data1 != 0x8073) {
    876             return SOC_E_NOT_FOUND;
    877         } else {
    878           /* found a 8073 */
    879           return SOC_E_NONE;
    880         }
    881     }
    882 
    883     /* 8072 has the same phy id0 and id1. The difference is the register
    884      * 0 device 7 reads as 0 for 87x6, 0x1000 for 8072 after powerup.
    885      */
    886     SOC_IF_ERROR_RETURN
    887         (READ_PHY8072_AN_REG(unit,pc,0,&data0));
    888 
    889     /* needed for subsequent initialization after powerup */
    890     SOC_IF_ERROR_RETURN
    891         (READ_PHY8072_GENREG1r(unit,pc,&data1));
    892 
    893     /* the id after the SPI-ROM is loaded for 8072 */
    894     if ((data1 & 0xFFF0) == PMDA_ROM_LOAD_8072ID) {
    895         return SOC_E_NONE;
    896     }
    897 
    898     /* the id after the SPI-ROM is loaded for 8706 */
    899     if ((data1 == 0x4321) || (data1 == 0x1234)) {
    900         return SOC_E_NOT_FOUND;
    901     }
    902 
    903     /* powerup case */
    904     if (data0 == 0x1000) {
    905         return SOC_E_NONE;
    906     }
    907 
    908     return SOC_E_NOT_FOUND;
    909 }
    910 
    911 STATIC int
    912 phy_8074_probe(int unit, phy_ctrl_t *pc)
    913 {
    914     uint16 data = 0;
    915 
    916     /* device 8072 and 8073/8074 have different id1, but use the same driver. 
    917      * First check if the device's id1 matches 8074.
    918      */
    919     SOC_IF_ERROR_RETURN
    920         (READ_PHY8072_PMA_PMD_REG(unit,pc,PMAD_ID1_REG,&data));
    921 
    922     if (data == PHY_ID1_8074) {
    923         /* PHYs 8727/8073/8074 have the same phyid1, check register 0xc802 to find out if
    924          * 8074 device.
    925          */
    926         SOC_IF_ERROR_RETURN
    927             (READ_PHY8072_PMA_PMD_REG(unit,pc,0xC802,&data));
    928         if (data == 0x8074) {
    929             return SOC_E_NONE;
    930         }
    931     }
    932     return SOC_E_NOT_FOUND;
    933 }
    934 
    935 /*
    936  * Function:
    937  *      phy_8072_speed_set
    938  * Purpose:
    939  *      Set PHY speed
    940  * Parameters:
    941  *      unit - StrataSwitch unit #.
    942  *      port - StrataSwitch port #.
    943  *      speed - link speed in Mbps
    944  * Returns:
    945  *      SOC_E_NONE
    946  */
    947 
    948 STATIC int
    949 phy_8072_speed_set(int unit, soc_port_t port, int speed)
    950 {
    951     phy_ctrl_t  *pc;
    952     phy_ctrl_t  *int_pc;
    953     int rv = SOC_E_NONE;
    954                                                                                 
    955     LOG_INFO(BSL_LS_SOC_PHY,
    956              (BSL_META_U(unit,
    957                          "phy_8072_speed_set: u=%d p=%d speed=%d\n"),
    958                          unit, port,speed));
    959                                                                                 
    960     if (!(speed == 10000 || speed == 1000 || speed==2500)) {
    961         return SOC_E_PARAM;
    962     }
    963                                                                                 
    964     pc = EXT_PHY_SW_STATE(unit, port);
    965     int_pc = INT_PHY_SW_STATE(unit, port);
    966                                                                                 
    967     SOC_IF_ERROR_RETURN
    968         (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0x0096, 0x0000));
    969 
    970     if (speed == 10000 || speed == 1000) {
    971         SOC_IF_ERROR_RETURN
    972             (MODIFY_PHY8072_AN_REG(unit,pc,0x8309,(1 << 5),(1 << 5)));
    973     }
    974 
    975     if (speed == 10000) {
    976         SOC_IF_ERROR_RETURN
    977             (MODIFY_PHY8072_PMA_PMD_REG(unit,pc,PMAD_CTRL2_REG,
    978                     PMAD_CTRL2r_PMA_TYPE_10G,PMAD_CTRL2r_PMA_TYPE_MASK));
    979                                                                                 
    980         SOC_IF_ERROR_RETURN
    981             (MODIFY_PHY8072_PMA_PMD_REG(unit,pc, MII_CTRL_REG,
    982                     MII_CTRL_SS_LSB,MII_CTRL_SS_LSB));
    983         SOC_IF_ERROR_RETURN
    984             (WRITE_PHY8072_AN_REG(unit,pc,0x8308,0x1C));
    985         SOC_IF_ERROR_RETURN
    986             (WRITE_PHY8072_AN_REG(unit, pc, AN_CTRL_REG,
    987                           AN_ENABLE |
    988                           AN_RESTART));
    989 
    990         sal_usleep(40000);
    991         SOC_IF_ERROR_RETURN
    992             (WRITE_PHY8072_AN_REG(unit,pc,AN_CTRL_REG,0));
    993 
    994     } else if (speed == 1000) {
    995         SOC_IF_ERROR_RETURN
    996             (MODIFY_PHY8072_PMA_PMD_REG(unit,pc,PMAD_CTRL2_REG,
    997                     PMAD_CTRL2r_PMA_TYPE_1G,PMAD_CTRL2r_PMA_TYPE_MASK));
    998                                                                                 
    999         SOC_IF_ERROR_RETURN
   1000             (MODIFY_PHY8072_PMA_PMD_REG(unit,pc,MII_CTRL_REG,
   1001                     0,MII_CTRL_SS_LSB));
   1002     } else if (speed == 2500) {
   1003 
   1004         SOC_IF_ERROR_RETURN
   1005             (MODIFY_PHY8072_PMA_PMD_REG(unit,pc,PMAD_CTRL2_REG,
   1006                     PMAD_CTRL2r_PMA_TYPE_1G,PMAD_CTRL2r_PMA_TYPE_MASK)); 
   1007 
   1008         SOC_IF_ERROR_RETURN
   1009             (WRITE_PHY8072_AN_REG(unit, pc, AN_CTRL_REG,
   1010                           AN_ENABLE |
   1011                           AN_RESTART));
   1012 
   1013         sal_usleep(40000);
   1014         SOC_IF_ERROR_RETURN
   1015             (WRITE_PHY8072_AN_REG(unit,pc,AN_CTRL_REG,0));
   1016 
   1017         SOC_IF_ERROR_RETURN
   1018             (WRITE_PHY8072_AN_REG(unit,pc,0xffe0,0));
   1019         SOC_IF_ERROR_RETURN
   1020             (MODIFY_PHY8072_AN_REG(unit,pc,0x8309,0,(1 << 5)));
   1021         sal_usleep(10000);
   1022 
   1023         SOC_IF_ERROR_RETURN
   1024             (WRITE_PHY8072_AN_REG(unit,pc,0x8308,0x10));
   1025     }
   1026  
   1027                                                                    
   1028     /* need to set the internal phy's speed accordingly */
   1029                                                                                 
   1030     if (NULL != int_pc) {
   1031         rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed);
   1032     }
   1033     return rv;
   1034 }
   1035 
   1036 /*
   1037  * Function:
   1038  *      phy_8072_speed_get
   1039  * Purpose:
   1040  *      Get PHY speed
   1041  * Parameters:
   1042  *      unit - StrataSwitch unit #.
   1043  *      port - StrataSwitch port #.
   1044  *      speed - current link speed in Mbps
   1045  * Returns:
   1046  *      SOC_E_NONE
   1047  */
   1048 
   1049 STATIC int
   1050 phy_8072_speed_get(int unit, soc_port_t port, int *speed)
   1051 {
   1052     phy_ctrl_t  *pc;
   1053     uint16       speed_val;
   1054     int an = 0;
   1055     int an_done = 0;                                        
   1056     uint16 an_cl37 = 0;
   1057     uint16 status = 0;
   1058 
   1059     pc = EXT_PHY_SW_STATE(unit, port);
   1060     speed_val = 0;
   1061     *speed = 10000;
   1062                                                                                 
   1063     phy_8072_an_get(unit, port, &an, &an_done);
   1064     if (pc->phy_id1 == PHY_ID1_8073) {
   1065         SOC_IF_ERROR_RETURN
   1066             (READ_PHY8072_PMA_PMD_REG(unit, pc, PMAD_USR_STATUS_REG, 
   1067               &status));
   1068     }
   1069 
   1070     if (an) { /* autoneg is enabled */
   1071         SOC_IF_ERROR_RETURN
   1072             (READ_PHY8072_AN_REG(unit, pc, AN_ETH_STATUS_REG, &speed_val));
   1073         if (speed_val & AN_SPEED_10GBASE_KR) {
   1074             *speed = 10000;
   1075         } else if (PMAD_STATUS_AN_2p5G(status)) {
   1076             *speed = 2500;
   1077         } else if (speed_val & AN_SPEED_1000BASE_KX) {
   1078             *speed = 1000;
   1079         } else {
   1080             uint16 phy_id1;
   1081             int link_cl37;
   1082 
   1083             SOC_IF_ERROR_RETURN
   1084                 (READ_PHY8072_PMA_PMD_REG(unit,pc,PMAD_ID1_REG,&phy_id1));
   1085 
   1086             /* check CL37 link status */
   1087             SOC_IF_ERROR_RETURN
   1088                 (READ_PHY8072_AN_REG(unit, pc, 0x8304, &an_cl37));
   1089             link_cl37 = an_cl37 & 0x2; 
   1090            
   1091             /* check if CL37 enabled. automatically enabled for 8073 */ 
   1092             if (phy_id1 == PHY_ID1_8072) { 
   1093                 SOC_IF_ERROR_RETURN
   1094                     (READ_PHY8072_AN_REG(unit, pc, 0xFFE0, &an_cl37));
   1095                 link_cl37 = link_cl37 && (an_cl37 & AN_ENABLE);
   1096             }
   1097 
   1098             if (link_cl37) {
   1099                 *speed = 1000;
   1100             }
   1101         }                        
   1102     } else { /* autoneg is not enabled, forced speed */
   1103 
   1104         SOC_IF_ERROR_RETURN
   1105             (READ_PHY8072_PMA_PMD_REG(unit,pc,PMAD_USR_STATUS_REG,&speed_val));
   1106         if (speed_val & PMAD_STATUS_MODE_2p5G) {
   1107                 *speed = 2500;
   1108         } else {
   1109         SOC_IF_ERROR_RETURN
   1110             (READ_PHY8072_PMA_PMD_REG(unit,pc,PMAD_CTRL2_REG, &speed_val));
   1111         if ((speed_val & PMAD_CTRL2r_PMA_TYPE_MASK) ==
   1112                                             PMAD_CTRL2r_PMA_TYPE_1G) {
   1113             *speed = 1000;
   1114         } else if ((speed_val & PMAD_CTRL2r_PMA_TYPE_MASK) == 
   1115                                PMAD_CTRL2r_PMA_TYPE_10G) {
   1116             *speed = 10000;
   1117         }
   1118         }
   1119     }
   1120                                                                        
   1121     LOG_INFO(BSL_LS_SOC_PHY,
   1122              (BSL_META_U(unit,
   1123                          "phy_8072_speed_get: u=%d p=%d speed=%d\n"),
   1124               unit, port, *speed));
   1125     return SOC_E_NONE;
   1126 }
   1127 
   1128 /*
   1129  * Function:
   1130  *      phy_8072_an_get
   1131  * Purpose:
   1132  *      Get the current auto-negotiation status (enabled/busy)
   1133  * Parameters:
   1134  *      unit - StrataSwitch unit #.
   1135  *      port - StrataSwitch port #.
   1136  *      an   - (OUT) if true, auto-negotiation is enabled.
   1137  *      an_done - (OUT) if true, auto-negotiation is complete. This
   1138  *              value is undefined if an == false.
   1139  * Returns:
   1140  *      SOC_E_XXX
   1141  */
   1142 
   1143 STATIC int
   1144 phy_8072_an_get(int unit, soc_port_t port, int *an, int *an_done)
   1145 {
   1146     phy_ctrl_t *pc;
   1147     uint16 an_status;
   1148 
   1149     pc = EXT_PHY_SW_STATE(unit, port);
   1150     SOC_IF_ERROR_RETURN
   1151         (READ_PHY8072_AN_REG(unit, pc, AN_CTRL_REG, &an_status));
   1152     *an = (an_status & AN_ENABLE)? TRUE: FALSE;
   1153 
   1154     SOC_IF_ERROR_RETURN
   1155         (READ_PHY8072_AN_REG(unit, pc, AN_STATUS_REG, &an_status));
   1156     *an_done = (an_status & AN_DONE)? TRUE: FALSE;
   1157     return SOC_E_NONE;
   1158 }
   1159 
   1160 /*
   1161  * Function:
   1162  *      phy_8072_an_set
   1163  * Purpose:
   1164  *      Enable or disabled auto-negotiation on the specified port.
   1165  * Parameters:
   1166  *      unit - StrataSwitch unit #.
   1167  *      port - StrataSwitch port #.
   1168  *      an   - Boolean, if true, auto-negotiation is enabled
   1169  *              (and/or restarted). If false, autonegotiation is disabled.
   1170  * Returns:
   1171  *      SOC_E_XXX
   1172  */
   1173 
   1174 STATIC int
   1175 phy_8072_an_set(int unit, soc_port_t port, int an)
   1176 {
   1177     phy_ctrl_t  *pc;
   1178     uint16 phy_id1;
   1179 
   1180     pc = EXT_PHY_SW_STATE(unit, port);
   1181 
   1182     LOG_INFO(BSL_LS_SOC_PHY,
   1183              (BSL_META_U(unit,
   1184                          "phy_8072_an_set: u=%d p=%d an=%d\n"),
   1185               unit, port, an));
   1186 
   1187     SOC_IF_ERROR_RETURN
   1188         (READ_PHY8072_PMA_PMD_REG(unit,pc,PMAD_ID1_REG,&phy_id1));
   1189                                                                                 
   1190     if (an) {
   1191     SOC_IF_ERROR_RETURN
   1192         (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0x0096, 0x0002));
   1193 
   1194         if (phy_id1 == PHY_ID1_8072) {
   1195             /* Allow Clause 37 through Clause 73 */
   1196             SOC_IF_ERROR_RETURN
   1197                 (WRITE_PHY8072_AN_REG(unit, pc, 0x8370,0x040c));
   1198                                                                                 
   1199         }
   1200 
   1201         /* Enable Clause 37 AN */
   1202         SOC_IF_ERROR_RETURN
   1203             (WRITE_PHY8072_AN_REG(unit, pc, 0xFFE0, 0x1100));
   1204 
   1205         SOC_IF_ERROR_RETURN
   1206             (WRITE_PHY8072_AN_REG(unit, pc, AN_CTRL_REG, 
   1207                           AN_EXT_NXT_PAGE |
   1208                           AN_ENABLE |
   1209                           AN_RESTART));
   1210     } else {
   1211         SOC_IF_ERROR_RETURN
   1212             (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0x0096, 0x0000));
   1213 
   1214         if (phy_id1 == PHY_ID1_8072) {
   1215             /* no Clause 37 through Clause 73 */
   1216             SOC_IF_ERROR_RETURN
   1217                 (WRITE_PHY8072_AN_REG(unit, pc, 0x8370,0x0));
   1218                                                                                 
   1219         }  
   1220         /* disable Clause 37 AN */
   1221         SOC_IF_ERROR_RETURN
   1222             (WRITE_PHY8072_AN_REG(unit, pc, 0xFFE0, 0x0));
   1223                                                              
   1224         SOC_IF_ERROR_RETURN
   1225             (WRITE_PHY8072_AN_REG(unit, pc, AN_CTRL_REG, 0x0));
   1226     }
   1227     return SOC_E_NONE;
   1228 }
   1229 
   1230 /*
   1231  * Function:
   1232  *      phy_8072_ability_advert_get
   1233  * Purpose:
   1234  *      Get the current advertisement for auto-negotiation.
   1235  * Parameters:
   1236  *      unit - StrataSwitch unit #.
   1237  *      port - StrataSwitch port #.
   1238  *      mode - (OUT) Port mode mask indicating supported options/speeds.
   1239  * Returns:
   1240  *      SOC_E_XXX
   1241  * Notes:
   1242  *      The advertisement is retrieved for the ACTIVE medium.
   1243  *      No synchronization performed at this level.
   1244  */
   1245 
   1246 STATIC int
   1247 phy_8072_ability_advert_get(int unit, soc_port_t port,
   1248                            soc_port_ability_t *ability)
   1249 {
   1250     uint16           an_adv;
   1251     uint16           pause;
   1252     soc_port_mode_t  mode;
   1253     phy_ctrl_t      *pc;
   1254 
   1255     if (NULL == ability) {
   1256         return (SOC_E_PARAM);
   1257     }
   1258                                                                                 
   1259     pc = EXT_PHY_SW_STATE(unit, port);
   1260 
   1261     /* advert register 1 */
   1262     SOC_IF_ERROR_RETURN
   1263         (READ_PHY8072_AN_REG(unit, pc, AN_ADVERT_1_REG, &an_adv));
   1264 
   1265     mode = 0;
   1266     pause = 0;
   1267     mode |= (an_adv & AN_ADVERT_10G) ? SOC_PA_SPEED_10GB : 0;
   1268     mode |= (an_adv & AN_ADVERT_1G) ? SOC_PA_SPEED_1000MB : 0;
   1269 
   1270     /* check Full Duplex advertisement on Clause 37 */
   1271     SOC_IF_ERROR_RETURN
   1272         (READ_PHY8072_AN_REG(unit, pc, 0xFFE4,&an_adv));
   1273                                                                                 
   1274     mode |= (an_adv & 0x20) ? SOC_PA_SPEED_1000MB : 0;
   1275 
   1276     if (pc->phy_id1 == PHY_ID1_8073) {
   1277         SOC_IF_ERROR_RETURN
   1278             (READ_PHY8072_AN_REG(unit, pc, 0x8329,&an_adv));
   1279         mode |= (an_adv & 0x1) ? SOC_PA_SPEED_2500MB : 0;
   1280     }
   1281 
   1282     SOC_IF_ERROR_RETURN
   1283         (READ_PHY8072_AN_REG(unit, pc, AN_ADVERT_0_REG, &pause));
   1284                                                                                 
   1285     ability->speed_full_duplex = mode;
   1286     ability->pause = 0;
   1287     switch (pause & (AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)) {
   1288         case AN_ADVERT_PAUSE:
   1289             ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   1290             break;
   1291         case AN_ADVERT_PAUSE_ASYM:
   1292             ability->pause = SOC_PA_PAUSE_TX;
   1293             break;
   1294         case AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM:
   1295             ability->pause = SOC_PA_PAUSE_RX;
   1296             break;
   1297     }
   1298 
   1299     LOG_INFO(BSL_LS_SOC_PHY,
   1300              (BSL_META_U(unit,
   1301                          "phy_8072_ability_advert_get: u=%d p=%d speed=0x%x pause=0x%x\n"),
   1302               unit, port, ability->speed_full_duplex, ability->pause));
   1303     return SOC_E_NONE;
   1304 }
   1305 
   1306 /*
   1307  * Function:
   1308  *      phy_8072_ability_advert_set
   1309  * Purpose:
   1310  *      Set the current advertisement for auto-negotiation.
   1311  * Parameters:
   1312  *      unit - StrataSwitch unit #.
   1313  *      port - StrataSwitch port #.
   1314  *      mode - Port mode mask indicating supported options/speeds.
   1315  * Returns:
   1316  *      SOC_E_XXX
   1317  * Notes:
   1318  *      The advertisement is set only for the ACTIVE medium.
   1319  *      No synchronization performed at this level.
   1320  */
   1321 
   1322 STATIC int
   1323 phy_8072_ability_advert_set(int unit, soc_port_t port,
   1324                        soc_port_ability_t *ability)
   1325 {   
   1326     uint16           an_adv;
   1327     uint16           an_adv_cl37;
   1328     phy_ctrl_t      *pc;                                                                                 
   1329     if (NULL == ability) {
   1330         return (SOC_E_PARAM);
   1331     }
   1332                                                                                 
   1333     pc = EXT_PHY_SW_STATE(unit, port);
   1334                                                                                 
   1335     /*
   1336      * Set advertised duplex (only FD supported).
   1337      */
   1338     an_adv =  (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? 
   1339               AN_ADVERT_1G : 0;
   1340                                                                                 
   1341     /* write Full Duplex advertisement on Clause 37 */
   1342     SOC_IF_ERROR_RETURN
   1343         (WRITE_PHY8072_AN_REG(unit, pc, 0xFFE4,an_adv));
   1344 
   1345     an_adv =  (ability->speed_full_duplex & 
   1346                (SOC_PA_SPEED_1000MB | SOC_PA_SPEED_2500MB)) ? 
   1347                AN_ADVERT_1G : 0;
   1348     an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ? 
   1349                AN_ADVERT_10G : 0; 
   1350 
   1351     /* advert register 1 */
   1352     SOC_IF_ERROR_RETURN
   1353         (WRITE_PHY8072_AN_REG(unit, pc, AN_ADVERT_1_REG, an_adv));
   1354 
   1355     if (pc->phy_id1 == PHY_ID1_8073) {
   1356         an_adv =  (ability->speed_full_duplex & SOC_PA_SPEED_2500MB) ? 0x1 : 0;
   1357         SOC_IF_ERROR_RETURN
   1358             (WRITE_PHY8072_AN_REG(unit, pc, 0x8329, an_adv));
   1359     }
   1360 
   1361     an_adv = an_adv_cl37 = 0;
   1362     switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) {
   1363         case SOC_PA_PAUSE_TX:
   1364             an_adv = AN_ADVERT_PAUSE_ASYM;
   1365             an_adv_cl37 = MII_ANA_C37_ASYM_PAUSE;
   1366             break;
   1367         case SOC_PA_PAUSE_RX:
   1368             an_adv = AN_ADVERT_PAUSE_ASYM | AN_ADVERT_PAUSE;
   1369             an_adv_cl37 = MII_ANA_C37_ASYM_PAUSE | MII_ANA_C37_PAUSE;
   1370             break;
   1371         case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX:
   1372             an_adv_cl37 = MII_ANA_C37_PAUSE;
   1373             an_adv = AN_ADVERT_PAUSE;
   1374             break;
   1375     }
   1376     SOC_IF_ERROR_RETURN
   1377         (MODIFY_PHY8072_AN_REG(unit, pc, AN_ADVERT_0_REG, an_adv,
   1378                                AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM));
   1379     /* write Pause advertisement on Clause 37 */
   1380     SOC_IF_ERROR_RETURN
   1381         (MODIFY_PHY8072_AN_REG(unit, pc, 0xFFE4, an_adv_cl37,
   1382                             MII_ANA_C37_ASYM_PAUSE | MII_ANA_C37_PAUSE));
   1383 
   1384     LOG_INFO(BSL_LS_SOC_PHY,
   1385              (BSL_META_U(unit,
   1386                          "phy_8072_ability_advert_set: u=%d p=%d pause=0x%08x adv_reg1=0x%04x\n"),
   1387               unit, port, ability->pause, an_adv));
   1388     return SOC_E_NONE;
   1389 }
   1390 
   1391 /*
   1392  * Function:
   1393  *      phy_8072_ability_local_get
   1394  * Purpose:
   1395  *      Get the device's complete abilities.
   1396  * Parameters:
   1397  *      unit - StrataSwitch unit #.
   1398  *      port - StrataSwitch port #.
   1399  *      ability - return device's abilities.
   1400  * Returns:
   1401  *      SOC_E_XXX
   1402  */
   1403 
   1404 STATIC int
   1405 phy_8072_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1406 {
   1407     phy_ctrl_t *pc;
   1408 
   1409     pc = EXT_PHY_SW_STATE(unit, port);
   1410                                                                                       
   1411     LOG_INFO(BSL_LS_SOC_PHY,
   1412              (BSL_META_U(unit,
   1413                          "phy_8072_ability_local_get: u=%d p=%d\n"),
   1414               unit, port));
   1415                                                                                 
   1416     if (NULL == ability) {
   1417         return SOC_E_PARAM;
   1418     }
   1419                                                                                 
   1420     ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   1421     ability->speed_full_duplex  = SOC_PA_SPEED_1000MB;
   1422 
   1423     switch(pc->speed_max) {
   1424         case 10000:
   1425         default:
   1426             ability->speed_full_duplex |= SOC_PA_SPEED_10GB;
   1427             if (pc->phy_id1 == PHY_ID1_8073) {
   1428                 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB;
   1429             }
   1430             break;
   1431     }
   1432 
   1433     ability->pause     = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 
   1434     ability->interface = SOC_PA_INTF_XGMII;
   1435     ability->medium    = SOC_PA_MEDIUM_FIBER;
   1436     ability->loopback  = SOC_PA_LB_PHY;
   1437     ability->flags     = SOC_PA_AUTONEG;
   1438 
   1439     LOG_INFO(BSL_LS_SOC_PHY,
   1440              (BSL_META_U(unit,
   1441                          "phy_8072_ability_local_get: u=%d p=%d speed=0x%x pause=0x%x\n"),
   1442               unit, port, ability->speed_full_duplex,ability->pause));
   1443 
   1444     return (SOC_E_NONE);
   1445 }
   1446 
   1447 /*
   1448  * Function:
   1449  *      phy_8072_ability_remote_get
   1450  * Purpose:
   1451  *      Get the device's complete abilities.
   1452  * Parameters:
   1453  *      unit - StrataSwitch unit #.
   1454  *      port - StrataSwitch port #.
   1455  *      ability - return device's abilities.
   1456  * Returns:
   1457  *      SOC_E_XXX
   1458  */
   1459 
   1460 STATIC int
   1461 phy_8072_ability_remote_get(int unit, soc_port_t port, soc_port_ability_t *ability)
   1462 {
   1463     phy_ctrl_t *pc;
   1464     uint16      lp_abil, lp_abil_cl37;
   1465     soc_port_mode_t  mode;
   1466     int speed;
   1467 
   1468     pc = EXT_PHY_SW_STATE(unit, port);
   1469 
   1470     LOG_INFO(BSL_LS_SOC_PHY,
   1471              (BSL_META_U(unit,
   1472                          "phy_8072_ability_remote_get: u=%d p=%d\n"),
   1473               unit, port));
   1474 
   1475     if (NULL == ability) {
   1476         return SOC_E_PARAM;
   1477     }
   1478 
   1479     mode = 0;
   1480     ability->speed_half_duplex  = SOC_PA_ABILITY_NONE;
   1481     SOC_IF_ERROR_RETURN
   1482         (READ_PHY8072_AN_REG(unit, pc, AN_LP_ABILITY_1_REG, &lp_abil));
   1483     mode |= (lp_abil & AN_ADVERT_1G) ? SOC_PA_SPEED_1000MB : 0;
   1484     mode |= (lp_abil & AN_ADVERT_10G) ? SOC_PA_SPEED_10GB : 0;
   1485     ability->speed_full_duplex  = mode;
   1486 
   1487     if (pc->phy_id1 == PHY_ID1_8073) {
   1488         SOC_IF_ERROR_RETURN
   1489             (READ_PHY8072_AN_REG(unit, pc, 0x832C, &lp_abil));
   1490         if (lp_abil &  0x1) {
   1491             ability->speed_full_duplex |= SOC_PA_SPEED_2500MB;
   1492         }
   1493     }
   1494 
   1495     SOC_IF_ERROR_RETURN
   1496         (READ_PHY8072_AN_REG(unit, pc, AN_LP_ABILITY_0_REG, &lp_abil));
   1497 
   1498     ability->pause = 0;
   1499     switch (lp_abil & (AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)) {
   1500         case AN_ADVERT_PAUSE:
   1501             ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   1502             break;
   1503         case AN_ADVERT_PAUSE_ASYM:
   1504             ability->pause = SOC_PA_PAUSE_TX;
   1505             break;
   1506         case AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM:
   1507             ability->pause = SOC_PA_PAUSE_RX;
   1508             break;
   1509     }
   1510 
   1511     SOC_IF_ERROR_RETURN
   1512         (phy_8072_speed_get(unit,port,&speed));
   1513 
   1514     if (speed == 1000) {  /* add clause37 attributes */
   1515         SOC_IF_ERROR_RETURN
   1516             (READ_PHY8072_AN_REG(unit, pc, 0xFFE5, &lp_abil_cl37));
   1517         ability->speed_full_duplex |= 
   1518                    (lp_abil_cl37 & MII_ANA_C37_FD) ? SOC_PA_SPEED_1000MB : 0;
   1519 
   1520         switch (lp_abil_cl37 & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) {
   1521             case MII_ANP_C37_PAUSE:
   1522                 ability->pause |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX;
   1523                 break;
   1524             case MII_ANP_C37_ASYM_PAUSE:
   1525                 ability->pause |= SOC_PA_PAUSE_TX;
   1526                 break;
   1527             case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE:
   1528                 ability->pause |= SOC_PA_PAUSE_RX;
   1529                 break;
   1530         }
   1531     }
   1532     ability->interface = SOC_PA_INTF_XGMII;
   1533     ability->medium    = SOC_PA_MEDIUM_FIBER;
   1534     ability->loopback  = SOC_PA_LB_PHY;
   1535     SOC_IF_ERROR_RETURN
   1536         (READ_PHY8072_AN_REG(unit, pc, AN_STATUS_REG, &lp_abil));
   1537     ability->flags     = (lp_abil & AN_LP_AN_ABILITY) ? SOC_PA_AUTONEG : 0;
   1538 
   1539     LOG_INFO(BSL_LS_SOC_PHY,
   1540              (BSL_META_U(unit,
   1541                          "phy_8072_ability_remote_get: u=%d p=%d speed=0x%x pause=0x%x\n"),
   1542               unit, port, ability->speed_full_duplex, ability->pause));
   1543 
   1544     return (SOC_E_NONE);
   1545 }
   1546 
   1547 /*
   1548  *  Function:
   1549  *      phy_8072_rom_wait
   1550  *
   1551  *  Purpose:
   1552  *      Wait for data to be written to the SPI-ROM.
   1553  *  Input:
   1554  *      unit, port
   1555  */
   1556 STATIC int
   1557 phy_8072_rom_wait(int unit, int port)
   1558 {
   1559     uint16     rd_data;
   1560     uint16     wr_data;
   1561     int        count;
   1562     phy_ctrl_t *pc;
   1563     soc_timeout_t to;
   1564     int        SPI_READY;
   1565 
   1566     pc = EXT_PHY_SW_STATE(unit, port);
   1567 
   1568     rd_data = 0;
   1569     soc_timeout_init(&to, WR_TIMEOUT, 0);
   1570     do {
   1571         /*
   1572          * Write SPI Control Register Read Command.
   1573          */
   1574         count = 1;
   1575         wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count);
   1576         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1577         wr_data = SPI_CTRL_1_L;
   1578         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1579         if (rd_data & 0x0100) {
   1580             break;
   1581         }
   1582     } while (!soc_timeout_check(&to));
   1583     if (!(rd_data & 0x0100)) {
   1584         LOG_ERROR(BSL_LS_SOC_PHY,
   1585                   (BSL_META_U(unit,
   1586                               "phy 8072 : u = %d p = %d timeout 1\n"),
   1587                               unit, port));
   1588         SOC_IF_ERROR_RETURN(SOC_E_TIMEOUT);
   1589     }
   1590 
   1591     SPI_READY = 1;
   1592     while (SPI_READY == 1) {
   1593         /*
   1594          * Set-up SPI Controller To Receive SPI EEPROM Status.
   1595          */
   1596         count = 1;
   1597         wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count);
   1598         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1599         wr_data = SPI_CTRL_2_H;
   1600         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1601         wr_data = 0x0100;
   1602         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1603         /*
   1604          * Fill-up SPI Transmit Fifo To check SPI Status.
   1605          */
   1606         count = 2;
   1607         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   1608         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1609         /*
   1610          * Write Tx Fifo Register Address.
   1611          */
   1612         wr_data = SPI_TXFIFO;
   1613         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1614 
   1615         /*
   1616          * Write SPI Tx Fifo Control Word-1.
   1617          */
   1618         wr_data = ((1 * 0x0100) | MSGTYPE_HRD);
   1619         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1620         /*
   1621          * Write SPI Tx Fifo Control Word-2.
   1622          */
   1623         wr_data = RDSR_OPCODE;
   1624         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1625         /*
   1626          * Write SPI Control Register Write Command.
   1627          */
   1628         count = 2;
   1629         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   1630         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1631         /*
   1632          * Write SPI Control -1 Register Address.
   1633          */
   1634         wr_data = SPI_CTRL_1_L;
   1635         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1636         /*
   1637          * Write SPI Control -1 Register Word-1.
   1638          */
   1639         wr_data = 0x0101;
   1640         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1641         /*
   1642          * Write SPI Control -1 Register Word-2.
   1643          */
   1644         wr_data = 0x0100;
   1645         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1646         /*
   1647          * Write SPI Control Register Write Command.
   1648          */
   1649         count = 1;
   1650         wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count);
   1651         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1652         /*
   1653          * Write SPI Control -1 Register Address.
   1654          */
   1655         wr_data = SPI_CTRL_1_H;
   1656         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1657         /*
   1658          * Write SPI Control -1 Register Word-2.
   1659          */
   1660         wr_data = 0x0103;
   1661         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1662         /*
   1663          * Wait For 64 bytes To be written.
   1664          */
   1665         rd_data = 0x0000;
   1666         soc_timeout_init(&to, WR_TIMEOUT, 0);
   1667         do {
   1668             count = 1;
   1669             wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count);
   1670             SOC_IF_ERROR_RETURN(write_message
   1671                                 (unit, pc, wr_data, &rd_data));
   1672             wr_data = SPI_CTRL_1_L;
   1673             SOC_IF_ERROR_RETURN(write_message
   1674                                 (unit, pc, wr_data, &rd_data));
   1675             if (rd_data & 0x0100) {
   1676                 break;
   1677             }
   1678         } while (!soc_timeout_check(&to));
   1679         if (!(rd_data & 0x0100)) {
   1680             LOG_ERROR(BSL_LS_SOC_PHY,
   1681                       (BSL_META_U(unit,
   1682                                   "phy 8072 : u = %d p = %d timeout 2\n"),
   1683                                   unit, port));
   1684             SOC_IF_ERROR_RETURN(SOC_E_TIMEOUT);
   1685         }
   1686         /*
   1687          * Write SPI Control Register Read Command.
   1688          */
   1689         count = 1;
   1690         wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count);
   1691         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1692         /*
   1693          * Write SPI Control -1 Register Address.
   1694          */
   1695         wr_data = SPI_RXFIFO;
   1696         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1697         if ((rd_data & 0x1) == 0) {
   1698             SPI_READY = 0;
   1699         }
   1700     }                           /* SPI_READY */
   1701     return SOC_E_NONE;
   1702 }
   1703 
   1704 /*
   1705  * Function:
   1706  *      phy_8072_rom_write_enable_set
   1707  *
   1708  * Purpose:
   1709  *      Enable disable protection on SPI_EEPROM
   1710  *
   1711  * Input:
   1712  *      unit
   1713  *      port
   1714  *      enable
   1715  * Output:
   1716  *      SOC_E_xxx
   1717  *
   1718  * Notes:
   1719  *          25AA256 256Kbit Serial EEPROM
   1720  *          STATUS Register
   1721  *          +------------------------------------------+
   1722  *          | WPEN | x | x | x | BP1 | BP0 | WEL | WIP |
   1723  *          +------------------------------------------+
   1724  *      BP1 BP0  :   Protected Blocks
   1725  *       0   0   :  Protect None
   1726  *       1   1   :  Protect All
   1727  *
   1728  *      WEL : Write Latch Enable
   1729  *       0  : Do not allow writes
   1730  *       1  : Allow writes
   1731  */
   1732 
   1733 STATIC int
   1734 phy_8072_rom_write_enable_set(int unit, int port, int enable)
   1735 {
   1736     uint16     rd_data;
   1737     uint16     wr_data;
   1738     uint8      wrsr_data;
   1739     int        count;
   1740     phy_ctrl_t *pc;
   1741 
   1742     pc = EXT_PHY_SW_STATE(unit, port);
   1743 
   1744     /*
   1745      * Write SPI Control Register Write Command.
   1746      */
   1747     count = 2;
   1748     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   1749     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1750 
   1751     /*
   1752      * Write SPI Control -2 Register Address.
   1753      */
   1754     wr_data = SPI_CTRL_2_L;
   1755     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1756 
   1757     /*
   1758      * Write SPI Control -2 Register Word-1.
   1759      */
   1760     wr_data = 0x8200;
   1761     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1762 
   1763     /*
   1764      * Write SPI Control -2 Register Word-2.
   1765      */
   1766     wr_data = 0x0100;
   1767     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1768 
   1769     /*
   1770      * Fill-up SPI Transmit Fifo With SPI EEPROM Messages.
   1771      * Write SPI Control Register Write Command.
   1772      */
   1773     count = 4;
   1774     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   1775     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1776 
   1777     /*
   1778      * Write Tx Fifo Register Address.
   1779      */
   1780     wr_data = SPI_TXFIFO;
   1781     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1782 
   1783     /*
   1784      * Write SPI Tx Fifo Control Word-1.
   1785      */
   1786     wr_data = ((1 * 0x0100) | MSGTYPE_HWR);
   1787     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1788 
   1789     /*
   1790      * Write SPI Tx Fifo Control Word-2.
   1791      */
   1792     wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE);
   1793     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1794 
   1795     /*
   1796      * Write SPI Tx Fifo Control Word-3.
   1797      */
   1798     wr_data = ((WRSR_OPCODE * 0x100) | (0x2));
   1799     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1800 
   1801     /*
   1802      * Write SPI Tx Fifo Control Word-4.
   1803      */
   1804     wrsr_data = enable ? 0x2 : 0xc;
   1805     wr_data = ((wrsr_data * 0x0100) | wrsr_data);
   1806     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1807 
   1808     /*
   1809      * Write SPI Control Register Write Command.
   1810      */
   1811     count = 2;
   1812     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   1813     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1814 
   1815     /*
   1816      * Write SPI Control -1 Register Address.
   1817      */
   1818     wr_data = SPI_CTRL_1_L;
   1819     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1820 
   1821     /*
   1822      * Write SPI Control -1 Register Word-1.
   1823      */
   1824     wr_data = 0x0101;
   1825     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1826 
   1827     /*
   1828      * Write SPI Control -1 Register Word-2.
   1829      */
   1830     wr_data = 0x0003;
   1831     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1832 
   1833     /*
   1834      * Wait For WRSR Command To be written.
   1835      */
   1836     SOC_IF_ERROR_RETURN(phy_8072_rom_wait(unit, port));
   1837 
   1838     return SOC_E_NONE;
   1839 }
   1840 
   1841 /*
   1842  * Function:
   1843  *      phy_8072_firmware_set
   1844  * Purpose:
   1845  *      program the given firmware into the SPI-ROM 
   1846  * Parameters:
   1847  *      unit - StrataSwitch unit #.
   1848  *      port - StrataSwitch port #.
   1849  *      offset - offset to the data stream
   1850  *      array  - the given data
   1851  *      datalen- the data length  
   1852  * Returns:
   1853  *      SOC_E_NONE
   1854  */
   1855 
   1856 STATIC int
   1857 phy_8072_firmware_set(int unit, int port, int offset, uint8 *array,int datalen)
   1858 {
   1859 
   1860     uint16     rd_data;
   1861     uint16     wr_data;
   1862     int        j;
   1863     int        i = 0;
   1864     int        count;
   1865     int     phy_8074;
   1866     phy_ctrl_t *pc;
   1867     uint8       spi_values[WR_BLOCK_SIZE];
   1868 
   1869     pc = EXT_PHY_SW_STATE(unit, port);
   1870 
   1871     phy_8074 = FALSE;
   1872 
   1873     if (pc->phy_id1 == PHY_ID1_8073) {
   1874         uint16     data;
   1875 
   1876         SOC_IF_ERROR_RETURN
   1877             (READ_PHY8072_PMA_PMD_REG(unit,pc,0xC802,&data));
   1878         if ( data == 0x8074 ) {
   1879             phy_8074 = TRUE;
   1880             /* Enable the SPI */
   1881             SOC_IF_ERROR_RETURN
   1882                 (MODIFY_PHY8072_PMA_PMD_REG(unit, pc, 0xc843, 0x0000, 0x000f));
   1883             SOC_IF_ERROR_RETURN
   1884                 (MODIFY_PHY8072_PMA_PMD_REG(unit, pc, 0xc840, 0x0000, 0x000c));
   1885         }
   1886     }
   1887 
   1888     /*
   1889      * ser_boot pin HIGH
   1890      */
   1891     SOC_IF_ERROR_RETURN
   1892         (MODIFY_PHY8072_PMA_PMD_REG(unit, pc, 0xCA85, 0x1, 0x1)); 
   1893     /*
   1894      * Read LASI Status registers To clear initial Failure status.
   1895      */
   1896     SOC_IF_ERROR_RETURN
   1897         (READ_PHY8072_PMA_PMD_REG(unit, pc, 0x9003, &rd_data));
   1898     SOC_IF_ERROR_RETURN
   1899         (READ_PHY8072_PMA_PMD_REG(unit, pc, 0x9004, &rd_data));
   1900     SOC_IF_ERROR_RETURN
   1901         (READ_PHY8072_PMA_PMD_REG(unit, pc, 0x9005, &rd_data));
   1902 
   1903     /*
   1904      * Enable the LASI For Message out. 
   1905      */
   1906     SOC_IF_ERROR_RETURN
   1907         (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0x9000, 0x0004));
   1908     /*
   1909      * 0x9002, bit 2 Is Rx Alarm enabled For LASI. 
   1910      */
   1911     SOC_IF_ERROR_RETURN
   1912         (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0x9002, 0x0004));
   1913     /*
   1914      * Read Any Residual Message out register.
   1915      */
   1916     SOC_IF_ERROR_RETURN
   1917         (READ_PHY8072_PMA_PMD_REG(unit, pc, 0xCA13, &rd_data));
   1918     /*
   1919      * Clear LASI Message Out Status. 
   1920      */
   1921     SOC_IF_ERROR_RETURN
   1922         (READ_PHY8072_PMA_PMD_REG(unit, pc, 0x9003, &rd_data));
   1923 
   1924     /* set SPI-ROM write enable */ 
   1925     SOC_IF_ERROR_RETURN(phy_8072_rom_write_enable_set(unit, port, 1));
   1926 
   1927     LOG_INFO(BSL_LS_SOC_PHY,
   1928              (BSL_META_U(unit,
   1929                          "init0: u=%d p=%d\n"),
   1930                          unit, port));
   1931 
   1932     for (j = 0; j < datalen; j += WR_BLOCK_SIZE) {
   1933         /*
   1934          * Setup SPI Controller. 
   1935          */
   1936         count = 2;
   1937         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   1938         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1939 
   1940         /* Write SPI Control -2 Register Address.*/
   1941         wr_data = SPI_CTRL_2_L;
   1942         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1943 
   1944         /* Write SPI Control -2 Register Word-1. */
   1945         wr_data = 0x8200;
   1946         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1947 
   1948         /* Write SPI Control -2 Register Word-2. */
   1949         wr_data = 0x0100;
   1950         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1951 
   1952         /* Fill-up SPI Transmit Fifo.
   1953          * Write SPI Control Register Write Command.
   1954          */
   1955         count = 4 + (WR_BLOCK_SIZE / 2);
   1956         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   1957         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1958 
   1959         /* Write Tx Fifo Register Address. */
   1960         wr_data = SPI_TXFIFO;
   1961         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1962 
   1963         /* Write SPI Tx Fifo Control Word-1. */
   1964         wr_data = ((1 * 0x0100) | MSGTYPE_HWR);
   1965         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1966 
   1967         /* Write SPI Tx Fifo Control Word-2. */
   1968         wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE);
   1969         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1970 
   1971         /* Write SPI Tx Fifo Control Word-3. */
   1972         wr_data = ((WR_OPCODE * 0x0100) | (0x3 + WR_BLOCK_SIZE));
   1973         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1974 
   1975         /* Write SPI Tx Fifo Control Word-4. */
   1976         wr_data = (((j & 0x00FF) * 0x0100) | ((j & 0xFF00) / 0x0100));
   1977         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   1978 
   1979         LOG_INFO(BSL_LS_SOC_PHY,
   1980                  (BSL_META_U(unit,
   1981                              "loop: u=%d p=%d,inxj: %d,inxi:%d\n"),
   1982                              unit, port,j,i));
   1983 
   1984         if (datalen < (j + WR_BLOCK_SIZE)) {   /* last block */ 
   1985             sal_memset(spi_values,0,WR_BLOCK_SIZE);
   1986             sal_memcpy(spi_values,&array[j],datalen - j);
   1987 
   1988             for (i = 0; i < WR_BLOCK_SIZE; i += 2) {
   1989                 /* Write SPI Tx Fifo Data Word-4. */
   1990                 wr_data = ((spi_values[i+1] * 0x0100) | spi_values[i]);
   1991                 SOC_IF_ERROR_RETURN(write_message(unit, pc,wr_data, &rd_data));
   1992             }           
   1993         } else {        
   1994             for (i = 0; i < WR_BLOCK_SIZE; i += 2) {
   1995                 /* Write SPI Tx Fifo Data Word-4. */
   1996                 wr_data = ((array[j+i+1] * 0x0100) | array[j+i]);
   1997                 SOC_IF_ERROR_RETURN(write_message(unit, pc,wr_data, &rd_data));
   1998             }
   1999         }
   2000 
   2001         /* 
   2002          * Set-up SPI Controller To Transmit.
   2003          * Write SPI Control Register Write Command.
   2004          */
   2005         count = 2;
   2006         wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   2007         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2008 
   2009         wr_data = SPI_CTRL_1_L;
   2010         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2011 
   2012         /* Write SPI Control -1 Register Word-1. */
   2013         wr_data = 0x0501;
   2014         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2015 
   2016         /* Write SPI Control -1 Register Word-2. */
   2017         wr_data = 0x0003;
   2018         SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2019 
   2020         /* Wait For 64 bytes To be written.   */
   2021         SOC_IF_ERROR_RETURN(phy_8072_rom_wait(unit, port));
   2022     }
   2023 
   2024     /* clear SPI-ROM write enable */ 
   2025     SOC_IF_ERROR_RETURN(phy_8072_rom_write_enable_set(unit, port, 0));
   2026 
   2027     /* Disable SPI EEPROM. */
   2028     count = 2;
   2029     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   2030     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2031 
   2032     /* Write SPI Control -2 Register Address. */
   2033     wr_data = SPI_CTRL_2_L;
   2034     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2035 
   2036     /* Write SPI Control -2 Register Word-1. */
   2037     wr_data = 0x8200;
   2038     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2039 
   2040     /* Write SPI Control -2 Register Word-2. */
   2041     wr_data = 0x0100;
   2042     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2043 
   2044 
   2045     /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages. */
   2046     count = 2;
   2047     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   2048     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2049 
   2050     /* Write Tx Fifo Register Address. */
   2051     wr_data = SPI_TXFIFO;
   2052     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2053 
   2054     /* Write SPI Tx Fifo Control Word-1. */
   2055     wr_data = ((0x1*0x0100) | MSGTYPE_HWR);
   2056     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2057 
   2058     /* Write SPI Tx Fifo Control Word-2. */
   2059     wr_data = WRDI_OPCODE;
   2060     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2061 
   2062     /* Write SPI Control Register Write Command. */
   2063     count = 2;
   2064     wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count);
   2065     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2066 
   2067     /* Write SPI Control -1 Register Address. */
   2068     wr_data = SPI_CTRL_1_L;
   2069     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2070 
   2071     /* Write SPI Control -1 Register Word-1. */
   2072     wr_data = 0x0101;
   2073     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2074 
   2075     /* Write SPI Control -1 Register Word-2. */
   2076     wr_data = 0x0003;
   2077     SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data));
   2078 
   2079     /*
   2080      * ser_boot pin LOW
   2081      */
   2082     SOC_IF_ERROR_RETURN
   2083         (MODIFY_PHY8072_PMA_PMD_REG(unit, pc, 0xCA85, 0x0, 0x1)); 
   2084 
   2085     if (phy_8074) {
   2086         SOC_IF_ERROR_RETURN
   2087             (MODIFY_PHY8072_PMA_PMD_REG(unit, pc, 0xc843, 0x000f, 0x000f));
   2088         SOC_IF_ERROR_RETURN
   2089             (MODIFY_PHY8072_PMA_PMD_REG(unit, pc, 0xc840, 0x000c, 0x000c));
   2090     }
   2091 
   2092     LOG_INFO(BSL_LS_SOC_PHY,
   2093              (BSL_META_U(unit,
   2094                          "phy_8072_rom_program: u=%d p=%d done\n"), unit, port));
   2095 
   2096     return SOC_E_NONE;
   2097 }
   2098 
   2099 static int
   2100 write_message(int unit, phy_ctrl_t *pc, uint16 wrdata, uint16 *rddata)
   2101 {
   2102 
   2103     uint16     tmp_data = 0;
   2104     soc_timeout_t to;
   2105 
   2106     SOC_IF_ERROR_RETURN
   2107         (READ_PHY8072_PMA_PMD_REG(unit, pc, 0xCA13, &tmp_data));
   2108     SOC_IF_ERROR_RETURN
   2109         (WRITE_PHY8072_PMA_PMD_REG(unit, pc, 0xCA12, wrdata));
   2110 
   2111     soc_timeout_init(&to, WR_TIMEOUT, 0);
   2112     do {
   2113         SOC_IF_ERROR_RETURN
   2114             (READ_PHY8072_PMA_PMD_REG(unit, pc, 0x9005, &tmp_data));
   2115         if (tmp_data & 0x4)
   2116             break;
   2117     } while (!soc_timeout_check(&to));
   2118     if (!(tmp_data & 0x4)) {
   2119         LOG_ERROR(BSL_LS_SOC_PHY,
   2120                   (BSL_META_U(unit,
   2121                               "write_message failed: wrdata %04x\n"), wrdata));
   2122         return SOC_E_FAIL;
   2123     }
   2124 
   2125     SOC_IF_ERROR_RETURN
   2126         (READ_PHY8072_PMA_PMD_REG(unit, pc, 0xCA13, &tmp_data));
   2127     *rddata = tmp_data;
   2128     SOC_IF_ERROR_RETURN
   2129         (READ_PHY8072_PMA_PMD_REG(unit, pc, 0x9003, &tmp_data));
   2130 
   2131     return SOC_E_NONE;
   2132 }
   2133 
   2134 /*
   2135  * Variable:
   2136  *    phy_8072_drv
   2137  * Purpose:
   2138  *    Phy Driver for 10G (XAUI x 4) Serdes PHY. 
   2139  */
   2140 
   2141 phy_driver_t phy_8072drv_xe = {
   2142     "8072 10-Gigabit PHY Driver",
   2143     phy_8072_init,        /* Init */
   2144     phy_null_reset,       /* Reset (dummy) */
   2145     phy_8072_link_get,    /* Link get   */
   2146     phy_8072_enable_set,  /* Enable set */
   2147     phy_null_enable_get,  /* Enable get */
   2148     phy_null_set,         /* Duplex set */
   2149     phy_null_one_get,     /* Duplex get */
   2150     phy_8072_speed_set,   /* Speed set  */
   2151     phy_8072_speed_get,   /* Speed get  */
   2152     phy_null_set,         /* Master set */
   2153     phy_null_zero_get,    /* Master get */
   2154     phy_8072_an_set,         /* ANA set */
   2155     phy_8072_an_get,      /* ANA get */
   2156     NULL,                 /* Local Advert set */
   2157     NULL,                 /* Local Advert get */
   2158     NULL,                 /* Remote Advert get */
   2159     phy_8072_lb_set,      /* PHY loopback set */
   2160     phy_8072_lb_get,      /* PHY loopback set */
   2161     phy_null_interface_set, /* IO Interface set */
   2162     phy_xehg_interface_get, /* IO Interface get */
   2163     NULL,                   /* pd_ability, deprecated */
   2164     phy_8072_linkup_evt,
   2165     NULL,
   2166     phy_null_mdix_set,
   2167     phy_null_mdix_get,
   2168     phy_null_mdix_status_get,
   2169     NULL,
   2170     NULL,
   2171     phy_null_medium_get,
   2172     NULL,                    /* phy_cable_diag  */
   2173     NULL,                    /* phy_link_change */
   2174     phy_8072_control_set,    /* phy_control_set */
   2175     phy_8072_control_get,    /* phy_control_get */
   2176     NULL,                    /* phy_reg_read */
   2177     NULL,                    /* phy_reg_write */
   2178     NULL,                    /* phy_reg_modify */
   2179     NULL,                    /* phy_notify */
   2180     phy_8072_probe,          /* pd_probe  */
   2181     phy_8072_ability_advert_set,  /* pd_ability_advert_set */
   2182     phy_8072_ability_advert_get,  /* pd_ability_advert_get */
   2183     phy_8072_ability_remote_get,  /* pd_ability_remote_get */
   2184     phy_8072_ability_local_get,   /* pd_ability_local_get  */
   2185     phy_8072_firmware_set
   2186 };
   2187 
   2188 phy_driver_t phy_8074drv_xe = {
   2189     "8072 10-Gigabit PHY Driver",
   2190     phy_8072_init,        /* Init */
   2191     phy_null_reset,       /* Reset (dummy) */
   2192     phy_8072_link_get,    /* Link get   */
   2193     phy_8072_enable_set,  /* Enable set */
   2194     phy_null_enable_get,  /* Enable get */
   2195     phy_null_set,         /* Duplex set */
   2196     phy_null_one_get,     /* Duplex get */
   2197     phy_8072_speed_set,   /* Speed set  */
   2198     phy_8072_speed_get,   /* Speed get  */
   2199     phy_null_set,         /* Master set */
   2200     phy_null_zero_get,    /* Master get */
   2201     phy_8072_an_set,         /* ANA set */
   2202     phy_8072_an_get,      /* ANA get */
   2203     NULL,                 /* Local Advert set */
   2204     NULL,                 /* Local Advert get */
   2205     NULL,                 /* Remote Advert get */
   2206     phy_8072_lb_set,      /* PHY loopback set */
   2207     phy_8072_lb_get,      /* PHY loopback set */
   2208     phy_null_interface_set, /* IO Interface set */
   2209     phy_xehg_interface_get, /* IO Interface get */
   2210     NULL,                   /* pd_ability, deprecated */
   2211     phy_8072_linkup_evt,
   2212     NULL,
   2213     phy_null_mdix_set,
   2214     phy_null_mdix_get,
   2215     phy_null_mdix_status_get,
   2216     NULL,
   2217     NULL,
   2218     phy_null_medium_get,
   2219     NULL,                    /* phy_cable_diag  */
   2220     NULL,                    /* phy_link_change */
   2221     phy_8072_control_set,    /* phy_control_set */
   2222     phy_8072_control_get,    /* phy_control_get */
   2223     NULL,                    /* phy_reg_read */
   2224     NULL,                    /* phy_reg_write */
   2225     NULL,                    /* phy_reg_modify */
   2226     NULL,                    /* phy_notify */
   2227     phy_8074_probe,          /* pd_probe  */
   2228     phy_8072_ability_advert_set,  /* pd_ability_advert_set */
   2229     phy_8072_ability_advert_get,  /* pd_ability_advert_get */
   2230     phy_8072_ability_remote_get,  /* pd_ability_remote_get */
   2231     phy_8072_ability_local_get,   /* pd_ability_local_get  */
   2232     phy_8072_firmware_set
   2233 };
   2234 
   2235 #else /* INCLUDE_PHY_8072 */
   2236 int _phy_8072_not_empty;
   2237 #endif /* INCLUDE_PHY_8072 */