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

phy8703.c (9615B)


      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  * File:        phy8703.c
      8  * Purpose:    Phys driver support for Broadcom Serial 10Gig
      9  *             transceiver with XAUI interface.
     10  */
     11 
     12 
     13 #include <sal/types.h>
     14 #include <sal/core/spl.h>
     15 #include <shared/bsl.h>
     16 #include <soc/drv.h>
     17 #include <soc/debug.h>
     18 #include <soc/error.h>
     19 #include <soc/phyreg.h>
     20 
     21 #include <soc/phy.h>
     22 #include <soc/phy/phyctrl.h>
     23 #include <soc/phy/drv.h>
     24 
     25 #include "phydefs.h"     /* Must include before other phy related includes */
     26 
     27 #ifdef INCLUDE_PHY_8703
     28 #include "phyconfig.h"   /* Must be the first phy include after phydefs.h */
     29 #include "phyident.h"
     30 #include "phyreg.h"
     31 #include "phynull.h"
     32 #include "phyxehg.h"
     33 #include "phy8703.h"
     34 
     35 
     36 /*
     37  * Function:
     38  *    phy_8703_init
     39  * Purpose:    
     40  *    Initialize 8703 phys
     41  * Parameters:
     42  *    unit - StrataSwitch unit #.
     43  *    port - StrataSwitch port #. 
     44  * Returns:    
     45  *    SOC_E_NONE
     46  */
     47 
     48 static int
     49 phy_8703_init(int unit, soc_port_t port)
     50 {
     51     int         is_8704;
     52     uint16      tmp;
     53     phy_ctrl_t *pc;
     54 
     55     pc = EXT_PHY_SW_STATE(unit, port);
     56     
     57     PHY_FLAGS_SET(unit, port,  PHY_FLAGS_FIBER | PHY_FLAGS_C45);
     58 
     59     /* Reset the device */
     60     SOC_IF_ERROR_RETURN
     61         (MODIFY_PHY8703_PMA_PMD_CTRLr(unit, pc,
     62                                       MII_CTRL_RESET, MII_CTRL_RESET));
     63 
     64     SOC_IF_ERROR_RETURN
     65         (MODIFY_PHY8703_PCS_CTRLr(unit, pc,
     66                                   MII_CTRL_RESET, MII_CTRL_RESET));
     67 
     68     SOC_IF_ERROR_RETURN
     69         (MODIFY_PHY8703_PHYXS_CTRLr(unit, pc,
     70                                     MII_CTRL_RESET, MII_CTRL_RESET));
     71 
     72 
     73     /* P_DOWN/OPTXRST1 */
     74     SOC_IF_ERROR_RETURN
     75         (READ_PHY8703_IDENTIFIERr(unit, pc, &tmp));
     76 
     77     if (soc_property_port_get(unit, port, spn_FORCE_OPTTXENBLVL, FALSE)) {
     78         tmp |= 0x8000; /* Set OPTXENB_LVL */
     79     } else {
     80         tmp &= ~0x8000;
     81     }
     82  
     83     if (soc_property_port_get(unit, port, spn_FORCE_OPTTXRSTLVL, TRUE)) {
     84         tmp |= 0x4000; /* Set OPTXRST_LVL */
     85     } else {
     86         tmp &= ~0x4000;
     87     }
     88 
     89     if (soc_property_port_get(unit, port, spn_FORCE_OPTBIASFLTLVL, TRUE)) {
     90         tmp |= 0x2000; /* Set OPBIASFLT_LVL */
     91     } else {
     92         tmp &= ~0x2000;
     93     }
     94 
     95     if (soc_property_port_get(unit, port, spn_FORCE_OPTTEMPFLTLVL, TRUE)) {
     96         tmp |= 0x1000; /* Set OPMPFLT_LVL */
     97     } else {
     98         tmp &= ~0x1000;
     99     }
    100 
    101     if (soc_property_port_get(unit, port, spn_FORCE_OPTPRFLTLVL, TRUE)) {
    102         tmp |= 0x0800; /* Set OPPRFLT_LVL */
    103     } else {
    104         tmp &= ~0x0800;
    105     }
    106 
    107     if (soc_property_port_get(unit, port, spn_FORCE_OPTTXFLLVL, TRUE)) {
    108         tmp |= 0x0400; /* Set OPTXFLT_LVL */
    109     } else {
    110         tmp &= ~0x0400;
    111     }
    112 
    113     if (soc_property_port_get(unit, port, spn_FORCE_OPTRXLOSLVL, TRUE)) {
    114         tmp |= 0x0200; /* Set OPRXLOS_LVL */
    115     } else {
    116         tmp &= ~0x0200;
    117     }
    118 
    119     if (soc_property_port_get(unit, port, spn_FORCE_OPTRXFLTLVL, TRUE)) {
    120         tmp |= 0x0100; /* Set OPRXFLT_LVL */
    121     } else {
    122         tmp &= ~0x0100;
    123     }
    124 
    125     if (soc_property_port_get(unit, port, spn_FORCE_OPTTXONLVL, TRUE)) {
    126         tmp |= 0x0080; /* Set OPTXON_LVL */
    127     } else {
    128         tmp &= ~0x0080;
    129     }
    130 
    131     SOC_IF_ERROR_RETURN
    132         (WRITE_PHY8703_IDENTIFIERr(unit, pc, tmp));
    133 
    134     /*
    135      * Enable 8704 XFP clock output
    136      */
    137     is_8704 = pc->phy_rev == 3;
    138     if (is_8704 && 
    139         soc_property_port_get(unit, port, spn_PHY_XFP_CLOCK, TRUE)) {
    140         SOC_IF_ERROR_RETURN
    141             (MODIFY_PHY8703_PMD_TX_CTRLr(unit, pc, 0x0100, 0x0100));
    142     }
    143  
    144     LOG_INFO(BSL_LS_SOC_PHY,
    145              (BSL_META_U(unit,
    146                          "8703: u=%d port%d: init.\n"),
    147                          unit, port));
    148 
    149     return SOC_E_NONE;
    150 }
    151 
    152 /*
    153  * Function:
    154  *    phy_8703_link_get
    155  * Purpose:
    156  *    Get layer2 connection status.
    157  * Parameters:
    158  *    unit - StrataSwitch unit #.
    159  *    port - StrataSwitch port #. 
    160  *      link - address of memory to store link up/down state.
    161  * Returns:    
    162  *    SOC_E_NONE
    163  */
    164 
    165 STATIC int
    166 phy_8703_link_get(int unit, soc_port_t port, int *link)
    167 {
    168     uint16      pma_mii_stat, pcs_mii_stat, pxs_mii_stat, link_stat;
    169     phy_ctrl_t *pc;
    170 
    171     LOG_INFO(BSL_LS_SOC_PHY,
    172              (BSL_META_U(unit,
    173                          "phy_8703_link_get: u=%d port%d: link:%s\n"),
    174               unit, port, ""));
    175 
    176     if (link == NULL) {
    177         return SOC_E_NONE;
    178     }
    179 
    180     if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) {
    181         *link = FALSE;
    182         return SOC_E_NONE;
    183     }
    184 
    185     pc = EXT_PHY_SW_STATE(unit, port);
    186     SOC_IF_ERROR_RETURN
    187         (READ_PHY8703_PMA_PMD_STATr(unit, pc, &pma_mii_stat));
    188 
    189     /* Receive Link status */
    190     SOC_IF_ERROR_RETURN
    191         (READ_PHY8703_PCS_STATr(unit, pc, &pcs_mii_stat));
    192 
    193     /* Transmit Link status */
    194     SOC_IF_ERROR_RETURN
    195         (READ_PHY8703_PHYXS_STATr(unit, pc, &pxs_mii_stat));
    196 
    197     link_stat = pma_mii_stat & pcs_mii_stat & pxs_mii_stat;
    198 
    199     *link = (link_stat & MII_STAT_LA) ? TRUE : FALSE;
    200 
    201     LOG_INFO(BSL_LS_SOC_PHY,
    202              (BSL_META_U(unit,
    203                          "phy_8703_link_get: u=%d port%d: link:%s\n"),
    204               unit, port, *link ? "Up": "Down"));
    205 
    206     return SOC_E_NONE;
    207 }
    208 
    209 /*
    210  * Function:
    211  *    phy_8703_enable_set
    212  * Purpose:
    213  *    Enable/Disable phy 
    214  * Parameters:
    215  *    unit - StrataSwitch unit #.
    216  *    port - StrataSwitch port #. 
    217  *      enable - on/off state to set
    218  * Returns:    
    219  *    SOC_E_NONE
    220  */
    221 
    222 STATIC int
    223 phy_8703_enable_set(int unit, soc_port_t port, int enable)
    224 {
    225     uint16      data;       /* Holder for new value to write to PHY reg */
    226     uint16      mask;       /* Holder for bit mask to update in PHY reg */
    227     phy_ctrl_t *pc;
    228 
    229     pc = EXT_PHY_SW_STATE(unit, port);
    230 
    231     data = 0;
    232     mask = 1 << 0; /* Global PMD transmit disable */
    233     if (enable) {
    234         PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE);
    235     } else {
    236         data = 1 << 0;  /* Global PMD transmit disable */
    237         PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE);
    238     }
    239 
    240     SOC_IF_ERROR_RETURN
    241         (MODIFY_PHY8703_PMA_PMD_TX_DISABLEr(unit, pc, data, mask));
    242     return (SOC_E_NONE);
    243 }
    244 
    245 
    246 /*
    247  * Function:
    248  *    phy_8703_lb_set
    249  * Purpose:
    250  *    Put 8703 in PHY PCS/PMA/PMD loopback
    251  * Parameters:
    252  *    unit - StrataSwitch unit #.
    253  *    port - StrataSwitch port #. 
    254  *      enable - binary value for on/off (1/0)
    255  * Returns:    
    256  *    SOC_E_NONE
    257  */
    258 
    259 STATIC int
    260 phy_8703_lb_set(int unit, soc_port_t port, int enable)
    261 {
    262     uint16     tmp;
    263     phy_ctrl_t *pc; 
    264 
    265     LOG_INFO(BSL_LS_SOC_PHY,
    266              (BSL_META_U(unit,
    267                          "phy_8703_lb_set: u=%d port%d: %s PCS/PMA/PMD loopback.\n"),
    268               unit, port, enable ? "Enabling": "Disabling"));
    269 
    270     pc = EXT_PHY_SW_STATE(unit, port);
    271 
    272     tmp = enable ? MII_CTRL_PMA_LOOPBACK : 0;
    273 
    274     SOC_IF_ERROR_RETURN
    275         (MODIFY_PHY8703_PMA_PMD_CTRLr(unit, pc,
    276                                       tmp, MII_CTRL_PMA_LOOPBACK));
    277 
    278     return SOC_E_NONE;
    279 }
    280 
    281 /*
    282  * Function:
    283  *    phy_8703_lb_get
    284  * Purpose:
    285  *    Get 8703 PHY loopback state
    286  * Parameters:
    287  *    unit - StrataSwitch unit #.
    288  *    port - StrataSwitch port #. 
    289  *      enable - address of location to store binary value for on/off (1/0)
    290  * Returns:    
    291  *    SOC_E_NONE
    292  */
    293 
    294 STATIC int
    295 phy_8703_lb_get(int unit, soc_port_t port, int *enable)
    296 {
    297     uint16      tmp;
    298     phy_ctrl_t *pc;
    299 
    300     pc = EXT_PHY_SW_STATE(unit, port);
    301     SOC_IF_ERROR_RETURN
    302         (READ_PHY8703_PMA_PMD_CTRLr(unit, pc, &tmp));
    303 
    304     *enable = (tmp & MII_CTRL_PMA_LOOPBACK) ? TRUE : FALSE;
    305 
    306     LOG_INFO(BSL_LS_SOC_PHY,
    307              (BSL_META_U(unit,
    308                          "phy_8703_lb_get: u=%d port%d: loopback:%s\n"),
    309               unit, port, *enable ? "Enabled": "Disabled"));
    310     
    311     return SOC_E_NONE;
    312 }
    313 
    314 
    315 /*
    316  * Variable:
    317  *    phy_8703_drv
    318  * Purpose:
    319  *    Phy Driver for 10G (XAUI x 4) Serdes PHY. 
    320  */
    321 
    322 phy_driver_t phy_8703drv_xe = {
    323     "8703 10-Gigabit PHY Driver",
    324     phy_8703_init,        /* Init */
    325     phy_null_reset,       /* Reset (dummy) */
    326     phy_8703_link_get,    /* Link get   */
    327     phy_8703_enable_set,  /* Enable set */
    328     phy_null_enable_get,  /* Enable get */
    329     phy_null_set,         /* Duplex set */
    330     phy_null_one_get,     /* Duplex get */
    331     phy_xehg_speed_set,   /* Speed set  */
    332     phy_xehg_speed_get,   /* Speed get  */
    333     phy_null_set,         /* Master set */
    334     phy_null_zero_get,    /* Master get */
    335     phy_null_set,         /* ANA set */
    336     phy_null_an_get,      /* ANA get */
    337     phy_null_mode_set,    /* Local Advert set */
    338     phy_null_mode_get,    /* Local Advert get */
    339     phy_null_mode_get,    /* Remote Advert get */
    340     phy_8703_lb_set,      /* PHY loopback set */
    341     phy_8703_lb_get,      /* PHY loopback set */
    342     phy_null_interface_set, /* IO Interface set */
    343     phy_xehg_interface_get, /* IO Interface get */
    344     phy_xehg_ability_get,   /* PHY abilities mask */
    345     NULL,
    346     NULL,
    347     phy_null_mdix_set,
    348     phy_null_mdix_get,
    349     phy_null_mdix_status_get,
    350     NULL,
    351     NULL,
    352     phy_null_medium_get,
    353     NULL,                    /* phy_cable_diag  */
    354     NULL,                    /* phy_link_change */
    355     NULL,                    /* phy_control_set */
    356     NULL,                    /* phy_control_get */
    357     NULL,                    /* phy_reg_read */
    358     NULL,                    /* phy_reg_write */
    359     NULL,                    /* phy_reg_modify */
    360     NULL,                    /* phy_notify */
    361 };
    362 
    363 #else /* INCLUDE_PHY_8703 */
    364 int _soc_phy_8703_not_empty;
    365 #endif /* INCLUDE_PHY_8703 */
    366