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

xaui.c (25740B)


      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  * XAUI Error monitoring features. 
      8  */
      9 
     10 #include <sal/core/libc.h>
     11 #include <shared/alloc.h>
     12 #include <sal/core/spl.h>
     13 #include <sal/core/boot.h>
     14 
     15 #include <soc/drv.h>
     16 #include <soc/error.h>
     17 #include <soc/cmic.h>
     18 #include <soc/portmode.h>
     19 #include <soc/ll.h>
     20 #include <soc/xaui.h>
     21 #include <soc/phyctrl.h>
     22 #include <soc/debug.h>
     23 #include <soc/esw/portctrl.h>
     24 
     25 #ifdef BCM_XGS3_SWITCH_SUPPORT
     26 
     27 /*
     28  * Function:
     29  *      soc_xaui_err_sym_detect_set
     30  * Description:
     31  *      Enable/Disable XAUI error symbol monitoring feature.
     32  * Parameters:
     33  *      unit - Device number
     34  *      port - Port number
     35  *      enable - TRUE, enable |E| monitoring feature on the port.
     36  *               FALSE, disable |E| monitoring feature on the port.
     37  * Return Value:
     38  *      SOC_E_NONE
     39  *      SOC_E_UNAVAIL - Functionality not available
     40  */
     41 int
     42 soc_xaui_err_sym_detect_set(int unit, soc_port_t port, int enable)
     43 {
     44     uint8         phy_addr;
     45     uint16        octrl, rx_ctrl, rx_ctrl_1g, status;
     46 
     47     if (SOC_USE_PORTCTRL(unit)) {
     48         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
     49                             &phy_addr));
     50     } else {
     51         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
     52     }
     53     /* Map RxAll Block */
     54     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00f0));
     55 
     56     /* Read Rx Control 1G Register */
     57     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x19, &rx_ctrl_1g));
     58     octrl = rx_ctrl_1g;
     59     if (enable) {
     60         /*
     61          * Enable cgbad_tst, Emon_en, and cgbad_en
     62          */
     63         rx_ctrl_1g |= 0x0680;
     64     } else {
     65         /*
     66          * Disable cgbad_tst and Emon_en
     67          */
     68         rx_ctrl_1g &= ~0x0600;
     69     }
     70     if (octrl != rx_ctrl_1g) {
     71         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x19,
     72                                            rx_ctrl_1g));
     73     }
     74 
     75     /* Read Rx Control Register */
     76     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x11, &rx_ctrl));
     77     octrl = rx_ctrl;
     78     if (enable) {
     79         /*
     80          * Enable SigDetected_en, SigDetRestart_en, and
     81          * SigDetMonitor_en and map PRBS status register at 0x80F0.
     82          */
     83         rx_ctrl |= 0x1c47;
     84         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x11, rx_ctrl));
     85 
     86         /*
     87          * Clear the |E| count in PRBS status register (Clear-on-read)
     88          */
     89         SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x10, &status));
     90 
     91         /*
     92          * Restore original status register select mapping.
     93          */
     94         rx_ctrl = octrl | 0x1c40;
     95         if (rx_ctrl != octrl) {
     96             SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x11,
     97                                 rx_ctrl));
     98         }
     99 
    100     }
    101     /*
    102      * SigDetected_en, SigDetRestart_en and SigDetMonitor_en are not disabled
    103      * when disabling |E| monitoring because they are enabled by default.
    104      * Just made sure to enable them when enabling |E| monitoring.
    105      */
    106 
    107     /* Restore the block 0 mapping */
    108     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0));
    109 
    110     return SOC_E_NONE;
    111 }
    112 
    113 /*
    114  * Function:
    115  *      soc_xaui_err_sym_detect_get
    116  * Description:
    117  *      Get the status of XAUI error symbol monitoring feature.
    118  * Parameters:
    119  *      unit - Device number
    120  *      port - Port number
    121  *      enable - (OUT) TRUE, port is enabled, FALSE port is disabled.
    122  * Return Value:
    123  *      SOC_E_NONE
    124  *      SOC_E_UNAVAIL - Functionality not available
    125  */
    126 int
    127 soc_xaui_err_sym_detect_get(int unit, soc_port_t port, int *enable)
    128 {
    129     uint8         phy_addr;
    130     uint16        rx_ctrl;
    131     uint16        rx_ctrl_1g;
    132 
    133     if (SOC_USE_PORTCTRL(unit)) {
    134         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    135                             &phy_addr));
    136     } else {
    137         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    138     }
    139 
    140     /* Map RxAll block */
    141     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00f0));
    142 
    143     /*
    144      * Read Rx Control register and mask
    145      * SigDetected_en, SigDetRestart_en, and SigDetMonitor_en bits.
    146      */
    147     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x11, &rx_ctrl));
    148     rx_ctrl &= 0x1c00;
    149 
    150     /*
    151      * Read Rx Control 1G register and mask
    152      * cgbad_tst, Emon_en, and cgbad_en bits.
    153      */
    154     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x19, &rx_ctrl_1g));
    155     rx_ctrl_1g &= 0x0680;
    156 
    157     if (rx_ctrl == 0x1c00 && rx_ctrl_1g == 0x680) {
    158         *enable = 1;
    159     } else {
    160         *enable = 0;
    161     }
    162 
    163     /* Restore the block 0 mapping */
    164     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0));
    165 
    166     return SOC_E_NONE;
    167 }
    168 
    169 /*
    170  * Function:
    171  *      soc_xaui_err_sym_count
    172  * Description:
    173  *      Get the number of |E| symbol in XAUI lanes since last read.
    174  * Parameters:
    175  *      unit - Device number
    176  *      port - Port number
    177  *      count - (OUT) Number of |E| error since last read.
    178  * Return Value:
    179  *      SOC_E_NONE
    180  *      SOC_E_UNAVAIL - Functionality not available
    181  *      SOC_E_CONFIG  - Error symbol detect feature is not enabled
    182  */
    183 int
    184 soc_xaui_err_sym_count(int unit, soc_port_t port, int *count)
    185 {
    186     uint8         phy_addr;
    187     uint16        rx_ctrl, octrl;
    188     uint16        rx_ctrl_1g;
    189     uint16        rx_status;
    190 
    191     if (SOC_USE_PORTCTRL(unit)) {
    192         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    193                             &phy_addr));
    194     } else {
    195         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    196     }
    197     /*
    198      * Map Rx All register block
    199      */
    200     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00f0));
    201 
    202     /*
    203      * Read Rx Control 1G and Rx Control register to check whether
    204      * |E| monitoring is enabled.
    205      */
    206     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x19, &rx_ctrl_1g));
    207     rx_ctrl_1g &= 0x0680;
    208 
    209     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x11, &rx_ctrl));
    210     octrl = rx_ctrl;
    211     rx_ctrl &= 0x1c00;
    212 
    213     if (rx_ctrl != 0x1c00 || rx_ctrl_1g != 0x0680) {
    214         return SOC_E_CONFIG;
    215     }
    216 
    217     /*
    218      * If |E| monitor is enabled, map PRPS status register at 0x00F0
    219      */
    220     rx_ctrl = octrl | 0x0047;
    221     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x11, rx_ctrl));
    222 
    223     /*
    224      * Read PRBS status and parse error count field.
    225      * If sync_status indicates that symbol is not aligned to proper
    226      * symbol boundry, error count is invalid.
    227      */
    228     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x10, &rx_status));
    229     if (rx_status & 0x8000) {
    230         *count = rx_status & 0x3fff;
    231     } else {
    232         *count = 0;
    233     }
    234 
    235     /*
    236      * Restore original status register mapping at 0x00F0
    237      */
    238     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x11, octrl));
    239 
    240     /*
    241      * Restore block 0 mapping.
    242      */
    243     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0));
    244 
    245     return SOC_E_NONE;
    246 }
    247 
    248 /*
    249  * Function:
    250  *      soc_xaui_txbert_enable
    251  * Description:
    252  *      Enable Tx BERT in XAUI core.
    253  * Parameters:
    254  *      unit   - Device number
    255  *      port   - Port number
    256  *      enable - Enable or disable Tx BERT
    257  * Return Value:
    258  *      SOC_E_NONE
    259  *      SOC_E_PARAM   - port does not have XAUI core.
    260  * Note:
    261  *      This function clears the Tx counters before enabling
    262  * Tx BERT.
    263  */ 
    264 int
    265 soc_xaui_txbert_enable(int unit, soc_port_t port, int enable) 
    266 {
    267     uint8     phy_addr;
    268     uint16    phy_reg;
    269     uint16    blk_address;
    270 
    271     if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
    272         return SOC_E_PARAM;
    273     }
    274 
    275     if (SOC_USE_PORTCTRL(unit)) {
    276         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    277                             &phy_addr));
    278     } else {
    279         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    280     }
    281 
    282     /* Save block address to restore at the end */
    283     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address));
    284 
    285     /* Map Tx BERT Block */
    286     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0020));
    287 
    288     /* Configure Tx BERT */
    289     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x10, &phy_reg));
    290     if (enable) {
    291         /* Clear the Tx BERT counters */
    292         phy_reg |= 1 << 0; 
    293         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg));
    294 
    295         /* Run BERT */
    296         phy_reg |= 1 << 15;   /* Enable Tx packet generator */
    297         phy_reg &= ~(1 << 0);  
    298     } else {
    299         /* Disable packet generator */
    300         phy_reg &= ~(1 << 15);
    301     }
    302     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg));
    303 
    304     /* Restore block mapping */
    305     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address));
    306 
    307     return SOC_E_NONE;
    308 }
    309 
    310 /*
    311  * Function:
    312  *      soc_xaui_txbert_pkt_count_get
    313  * Description:
    314  *      Read total transmitted packet. 
    315  * Parameters:
    316  *      unit   - Device number
    317  *      port   - Port number
    318  *      count  - Number of packet transmitted 
    319  * Return Value:
    320  *      SOC_E_NONE
    321  *      SOC_E_PARAM   - port does not have XAUI core.
    322  * Note:
    323  *      The count is only 32 bit. The counter could overflow.
    324  */ 
    325 int
    326 soc_xaui_txbert_pkt_count_get(int unit, soc_port_t port, uint32 *count)
    327 {
    328     uint8  phy_addr;
    329     uint16 pkt_cnt_hi, pkt_cnt_lo;
    330     uint16 blk_address;
    331 
    332     if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
    333         return SOC_E_PARAM;
    334     }
    335 
    336     if (SOC_USE_PORTCTRL(unit)) {
    337         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    338                             &phy_addr));
    339     } else {
    340         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    341     }
    342 
    343     /* Save block address to restore at the end */
    344     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address));
    345 
    346     /* Map Tx BERT Block */
    347     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0020));
    348 
    349     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x19, &pkt_cnt_lo));
    350     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1a, &pkt_cnt_hi));
    351 
    352     *count = (pkt_cnt_hi << 16) | pkt_cnt_lo;
    353 
    354     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address));
    355 
    356     return SOC_E_NONE;
    357 }
    358 
    359 /*
    360  * Function:
    361  *      soc_xaui_txbert_byte_count_get
    362  * Description:
    363  *      Read total transmitted byte. 
    364  * Parameters:
    365  *      unit   - Device number
    366  *      port   - Port number
    367  *      count  - Number of byte transmitted 
    368  * Return Value:
    369  *      SOC_E_NONE
    370  *      SOC_E_PARAM   - port does not have XAUI core.
    371  * Note:
    372  *      The count is only 32 bit. The counter could overflow.
    373  */ 
    374 int
    375 soc_xaui_txbert_byte_count_get(int unit, soc_port_t port, uint32 *count)
    376 {
    377     uint8  phy_addr;
    378     uint16 byte_cnt_hi, byte_cnt_lo;
    379     uint16 blk_address;
    380 
    381     if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
    382         return SOC_E_PARAM;
    383     }
    384 
    385     if (SOC_USE_PORTCTRL(unit)) {
    386         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    387                             &phy_addr));
    388     } else {
    389         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    390     }
    391 
    392     /* Save block address to restore at the end */
    393     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address));
    394 
    395     /* Map Tx BERT Block */
    396     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0020));
    397 
    398     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &byte_cnt_lo));
    399     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x18, &byte_cnt_hi));
    400 
    401     *count = (byte_cnt_hi << 16) | byte_cnt_lo;
    402 
    403     /* Restore original block address */
    404     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address));
    405 
    406     return SOC_E_NONE;
    407 }
    408 
    409 /*
    410  * Function:
    411  *      soc_xaui_rxbert_enable
    412  * Description:
    413  *      Enable Rx BERT in XAUI core.
    414  * Parameters:
    415  *      unit   - Device number
    416  *      port   - Port number
    417  *      enable - Enable or disable Rx BERT
    418  * Return Value:
    419  *      SOC_E_NONE
    420  *      SOC_E_PARAM   - port does not have XAUI core.
    421  * Note:
    422  *      This function clears the Rx counters before enabling
    423  * Rx BERT.
    424  */ 
    425 int
    426 soc_xaui_rxbert_enable(int unit, soc_port_t port, int enable)
    427 {
    428     uint8   phy_addr;
    429     uint16  phy_reg;
    430     uint16  blk_address;
    431 
    432     if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
    433         return SOC_E_PARAM;
    434     }
    435 
    436     if (SOC_USE_PORTCTRL(unit)) {
    437         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    438                             &phy_addr));
    439     } else {
    440         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    441     }
    442 
    443     /* Save block address to restore at the end */
    444     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address));
    445 
    446     /* Map Block 0 */
    447     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0000));
    448 
    449     if (enable) {
    450         /* Turn off check end functions in xgmiiRcontrol */
    451         SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &phy_reg));
    452         phy_reg &= ~(1 << 10);
    453         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x17, phy_reg));
    454 
    455         /* Enable pgen_en in xgxsControl */
    456         SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x10, &phy_reg));
    457         phy_reg |= 1 << 15;  /* Enable pattern generator */
    458         phy_reg |= 1 << 14;  /* Enable pattern comparator */
    459         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg));
    460 
    461         /* Map Rx BERT Block */
    462         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030));
    463 
    464         /* Clear the Rx BERT counters */
    465         phy_reg  = 1 << 1;  /* Clear Rx BERT error counters */
    466         phy_reg |= 1 << 0;  /* Clear Rx BERT receive counters */
    467         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg));
    468 
    469         /* Enable packet monitor */
    470         phy_reg  = 1 << 15; /* Enable Rx packet monitor */
    471         phy_reg |= 3 << 4;  /* Get the source of Rx BERT from 
    472                              * clock compensation 
    473                              */
    474         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg));
    475     } else {
    476         /* Turn on check end function */
    477         SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &phy_reg));
    478         phy_reg |= 1 << 10;
    479         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x17, phy_reg));
    480 
    481         /* Disable pgen_en in xgxsControl */
    482         SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x10, &phy_reg));
    483         phy_reg &= ~(1 << 15);  /* Disable pattern generator */
    484         phy_reg &= ~(1 << 14);  /* Disable pattern comparator */
    485         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg));
    486 
    487         /* Map Rx BERT Block */
    488         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030));
    489 
    490         /* Disable packet monitor */
    491         phy_reg  &= ~(1 << 15); /* Disable Rx packet monitor */
    492         SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg));
    493    }
    494 
    495      /* Restore original block address */
    496     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address));
    497 
    498     return SOC_E_NONE;
    499 }
    500 
    501 /*
    502  * Function:
    503  *      soc_xaui_rxbert_pkt_count_get
    504  * Description:
    505  *      Read the number of packet received in BERT.
    506  * Parameters:
    507  *      unit   - Device number
    508  *      port   - Port number
    509  *      count  - Number of packet received. 
    510  * Return Value:
    511  *      SOC_E_NONE
    512  *      SOC_E_PARAM   - port does not have XAUI core.
    513  */ 
    514 int
    515 soc_xaui_rxbert_pkt_count_get(int unit, soc_port_t port, 
    516                               uint32 *count, int *prbs_lock)
    517 {
    518     uint8  phy_addr;
    519     uint16 pkt_cnt_hi, pkt_cnt_lo;
    520     uint16 blk_address, rx_status;
    521 
    522     if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
    523         return SOC_E_PARAM;
    524     }
    525 
    526     if (SOC_USE_PORTCTRL(unit)) {
    527         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    528                             &phy_addr));
    529     } else {
    530         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    531     }
    532 
    533     /* Save block address to restore at the end */
    534     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address));
    535 
    536     /* Map Rx BERT Block */
    537     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030));
    538 
    539     /* Get Rx Packet count */
    540     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x19, &pkt_cnt_lo));
    541     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1a, &pkt_cnt_hi));
    542     *count = (pkt_cnt_hi << 16) | pkt_cnt_lo;
    543 
    544     /* Get PRBS Lock status */
    545     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1e, &rx_status));
    546     *prbs_lock = (rx_status >> 15);
    547 
    548     /* Restore original block address */
    549     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address));
    550 
    551     return SOC_E_NONE;
    552 }
    553 
    554 /*
    555  * Function:
    556  *      soc_xaui_rxbert_byte_count_get
    557  * Description:
    558  *      Read the number of byte received in BERT.
    559  * Parameters:
    560  *      unit   - Device number
    561  *      port   - Port number
    562  *      count  - Number of byte received. 
    563  * Return Value:
    564  *      SOC_E_NONE
    565  *      SOC_E_PARAM   - port does not have XAUI core.
    566  */ 
    567 int
    568 soc_xaui_rxbert_byte_count_get(int unit, soc_port_t port, 
    569                                uint32 *count, int *prbs_lock)
    570 {
    571     uint8  phy_addr;
    572     uint16 byte_cnt_hi, byte_cnt_lo;
    573     uint16 blk_address, rx_status;
    574 
    575     if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
    576         return SOC_E_PARAM;
    577     }
    578 
    579     if (SOC_USE_PORTCTRL(unit)) {
    580         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    581                             &phy_addr));
    582     } else {
    583         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    584     }
    585 
    586     /* Save block address to restore at the end */
    587     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address));
    588 
    589     /* Map Rx BERT Block */
    590     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030));
    591 
    592     /* Get byte count */ 
    593     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &byte_cnt_lo));
    594     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x18, &byte_cnt_hi));
    595     *count = (byte_cnt_hi << 16) | byte_cnt_lo;
    596 
    597     /* Get PRBS Lock status */
    598     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1e, &rx_status));
    599     *prbs_lock = (rx_status >> 15);
    600 
    601     /* Restore block address */
    602     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address));
    603 
    604     return SOC_E_NONE;
    605 }
    606 
    607 /*
    608  * Function:
    609  *      soc_xaui_rxbert_bit_err_count_get
    610  * Description:
    611  *      Read the number of bit error received in BERT.
    612  * Parameters:
    613  *      unit   - Device number
    614  *      port   - Port number
    615  *      count  - Number of bit error received. 
    616  * Return Value:
    617  *      SOC_E_NONE
    618  *      SOC_E_PARAM   - port does not have XAUI core.
    619  */ 
    620 int
    621 soc_xaui_rxbert_bit_err_count_get(int unit, soc_port_t port, 
    622                                   uint32 *count, int *prbs_lock)
    623 {
    624     uint8  phy_addr;
    625     uint16 phy_reg;
    626     uint16 blk_address;
    627 
    628     if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
    629         return SOC_E_PARAM;
    630     }
    631 
    632     if (SOC_USE_PORTCTRL(unit)) {
    633         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    634                             &phy_addr));
    635     } else {
    636         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    637     }
    638 
    639     /* Save block mapping to restore at the end */
    640     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address));
    641 
    642     /* Map Rx BERT Block */
    643     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030));
    644 
    645     /* Get bit error count */ 
    646     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1b, &phy_reg));
    647     *count = phy_reg;
    648 
    649     /* Get PRBS Lock status */
    650     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1e, &phy_reg));
    651     *prbs_lock = (phy_reg >> 15);
    652 
    653     /* Restore original block mapping */
    654     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address));
    655 
    656     return SOC_E_NONE;
    657 }
    658 
    659 /*
    660  * Function:
    661  *      soc_xaui_rxbert_byte_err_count_get
    662  * Description:
    663  *      Read the number of byte error received in BERT.
    664  * Parameters:
    665  *      unit   - Device number
    666  *      port   - Port number
    667  *      count  - Number of byte error received. 
    668  * Return Value:
    669  *      SOC_E_NONE
    670  *      SOC_E_PARAM   - port does not have XAUI core.
    671  */ 
    672 int
    673 soc_xaui_rxbert_byte_err_count_get(int unit, soc_port_t port, 
    674                                    uint32 *count, int *prbs_lock)
    675 {
    676     uint8  phy_addr;
    677     uint16 phy_reg;
    678     uint16 blk_address;
    679 
    680     if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
    681         return SOC_E_PARAM;
    682     }
    683 
    684     if (SOC_USE_PORTCTRL(unit)) {
    685         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    686                             &phy_addr));
    687     } else {
    688         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    689     }
    690 
    691     /* Save block mappping to restore at the end */
    692     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address));
    693 
    694     /* Map Rx BERT Block */
    695     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030));
    696 
    697     /* Read byte error count */
    698     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1c, &phy_reg));
    699     *count = phy_reg;
    700 
    701     /* Get PRBS Lock status */
    702     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1e, &phy_reg));
    703     *prbs_lock = (phy_reg >> 15);
    704 
    705     /* Restore original block mapping */
    706     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address));
    707 
    708     return SOC_E_NONE;
    709 }
    710 
    711 /*
    712  * Function:
    713  *      soc_xaui_rxbert_pkt_err_count_get
    714  * Description:
    715  *      Read the number of packet error received in BERT.
    716  * Parameters:
    717  *      unit   - Device number
    718  *      port   - Port number
    719  *      count  - Number of packet error received. 
    720  * Return Value:
    721  *      SOC_E_NONE
    722  *      SOC_E_PARAM   - port does not have XAUI core.
    723  */ 
    724 int
    725 soc_xaui_rxbert_pkt_err_count_get(int unit, soc_port_t port, 
    726                                   uint32 *count, int *prbs_lock)
    727 {
    728     uint8  phy_addr;
    729     uint16 phy_reg;
    730     uint16 blk_address;
    731 
    732     if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
    733         return SOC_E_PARAM;
    734     }
    735 
    736     if (SOC_USE_PORTCTRL(unit)) {
    737         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    738                             &phy_addr));
    739     } else {
    740         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    741     }
    742 
    743     /* Save block address to restore at the end */
    744     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address));
    745 
    746     /* Map Rx BERT Block */
    747     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030));
    748 
    749     /* Get packet error count */
    750     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1d, &phy_reg));
    751     *count = phy_reg;
    752 
    753     /* Get PRBS Lock status */
    754     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1e, &phy_reg));
    755     *prbs_lock = (phy_reg >> 15);
    756 
    757     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address));
    758 
    759     return SOC_E_NONE;
    760 }
    761 
    762 int
    763 soc_xaui_config_set(int unit, soc_port_t port, soc_xaui_config_t *config) 
    764 {
    765     uint8  phy_addr;
    766     uint16 phy_reg;
    767     uint16 blk_address;
    768 
    769     if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
    770         return SOC_E_PARAM;
    771     }
    772 
    773     if (SOC_USE_PORTCTRL(unit)) {
    774         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    775                             &phy_addr));
    776     } else {
    777         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    778     }
    779 
    780     /* Save block address to restore at the end */
    781     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address));
    782 
    783     /* Map Tx All Block */
    784     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00a0));
    785 
    786     /* Read Tx Driver Configuration*/
    787     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &phy_reg));
    788 
    789     phy_reg &= ~(0xfff0);
    790     phy_reg |= (_shr_bit_rev8(config->preemphasis) >> 4) << 12;
    791     phy_reg |= (_shr_bit_rev8(config->idriver) >> 4) << 8;
    792     phy_reg |= (_shr_bit_rev8(config->ipredriver) >> 4) << 4;
    793     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x17, phy_reg));
    794 
    795     /* Map Rx All Block */
    796     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00f0));
    797 
    798     /* Read Rx Eq Boost */
    799     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1c, &phy_reg));
    800     phy_reg &= ~(0x0007);
    801     phy_reg |= config->equalizer_ctrl;
    802     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1c, phy_reg));
    803  
    804     /* Restore block address */
    805     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address));
    806 
    807     return SOC_E_NONE;
    808 } 
    809 
    810 int
    811 soc_xaui_config_get(int unit, soc_port_t port, soc_xaui_config_t *config)
    812 {
    813     uint8  phy_addr;
    814     uint16 phy_reg;
    815     uint16 blk_address;
    816 
    817     if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) {
    818         return SOC_E_PARAM;
    819     }
    820 
    821     if (SOC_USE_PORTCTRL(unit)) {
    822         SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port,
    823                             &phy_addr));
    824     } else {
    825         phy_addr = PORT_TO_PHY_ADDR_INT(unit, port);
    826     }
    827 
    828     /* Save block address to restore at the end */
    829     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address));
    830 
    831     /* Map Tx All Block */
    832     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00a0));
    833 
    834     /* Read Tx Driver Configuration*/
    835     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &phy_reg));
    836 
    837     config->preemphasis = (phy_reg & 0xf000) >> 12;
    838     config->idriver     = (phy_reg & 0x0f00) >> 8;
    839     config->ipredriver  = (phy_reg & 0x00f0) >> 4;
    840 
    841     /* Map Rx All Block */
    842     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00f0));
    843 
    844     /* Read Rx Eq Boost */
    845     SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1c, &phy_reg));
    846     config->equalizer_ctrl = (phy_reg & 0x0007);  
    847 
    848     /* Restore block address */
    849     SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address));
    850 
    851     config->preemphasis = (_shr_bit_rev8(config->preemphasis) >> 4);
    852     config->idriver     = (_shr_bit_rev8(config->idriver) >> 4);
    853     config->ipredriver  = (_shr_bit_rev8(config->ipredriver) >> 4);
    854 
    855     return SOC_E_NONE;
    856 }
    857 
    858 #endif /* BCM_XGS3_SWITCH */