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

sesto_diag_seq.c (35176B)


      1 /*
      2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3 * 
      4 * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5 * 
      6 */
      7 
      8 /*
      9  *         
     10  * 
     11  * This program is the proprietary software of Broadcom Corporation
     12  * and/or its licensors, and may only be used, duplicated, modified
     13  * or distributed pursuant to the terms and conditions of a separate,
     14  * written license agreement executed between you and Broadcom
     15  * (an "Authorized License").  Except as set forth in an Authorized
     16  * License, Broadcom grants no license (express or implied), right
     17  * to use, or waiver of any kind with respect to the Software, and
     18  * Broadcom expressly reserves all rights in and to the Software
     19  * and all intellectual property rights therein.  IF YOU HAVE
     20  * NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS SOFTWARE
     21  * IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE
     22  * ALL USE OF THE SOFTWARE.  
     23  *  
     24  * Except as expressly set forth in the Authorized License,
     25  *  
     26  * 1.     This program, including its structure, sequence and organization,
     27  * constitutes the valuable trade secrets of Broadcom, and you shall use
     28  * all reasonable efforts to protect the confidentiality thereof,
     29  * and to use this information only in connection with your use of
     30  * Broadcom integrated circuit products.
     31  *  
     32  * 2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS
     33  * PROVIDED "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES,
     34  * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY,
     35  * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE.  BROADCOM SPECIFICALLY
     36  * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY,
     37  * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES,
     38  * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
     39  * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING
     40  * OUT OF USE OR PERFORMANCE OF THE SOFTWARE.
     41  * 
     42  * 3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL
     43  * BROADCOM OR ITS LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL,
     44  * INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY DAMAGES WHATSOEVER
     45  * ARISING OUT OF OR IN ANY WAY RELATING TO YOUR USE OF OR INABILITY
     46  * TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF THE
     47  * POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF
     48  * THE AMOUNT ACTUALLY PAID FOR THE SOFTWARE ITSELF OR USD 1.00,
     49  * WHICHEVER IS GREATER. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING
     50  * ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.$
     51  */
     52 
     53 #include <phymod/phymod.h>
     54 #include <phymod/phymod_system.h>
     55 #include <phymod/phymod_diagnostics.h>
     56 #include "sesto_address_defines.h"
     57 #include "sesto_reg_structs.h"
     58 #include "sesto_cfg_seq.h"
     59 #include "sesto_diag_seq.h"
     60 #include "sesto_serdes/falcon_furia_sesto_src/falcon_furia_sesto_functions.h"
     61 #include "sesto_serdes/merlin_sesto_src/merlin_sesto_functions.h"
     62 #include "sesto_serdes/common/srds_api_enum.h"
     63 
     64 int _sesto_phymod_prbs_poly_to_serdes_prbs_poly(uint16_t phymod_poly, uint16_t *serdes_poly)
     65 {
     66     switch (phymod_poly) {
     67         case phymodPrbsPoly7:
     68             *serdes_poly = PRBS_7;
     69         break;
     70         case phymodPrbsPoly9:
     71             *serdes_poly = PRBS_9;
     72         break;
     73         case phymodPrbsPoly11:
     74             *serdes_poly = PRBS_11;
     75         break;
     76         case phymodPrbsPoly15:
     77             *serdes_poly = PRBS_15;
     78         break;
     79         case phymodPrbsPoly23:
     80             *serdes_poly = PRBS_23;
     81         break;
     82         case phymodPrbsPoly31:
     83             *serdes_poly = PRBS_31;
     84         break;
     85         case phymodPrbsPoly58:
     86             *serdes_poly = PRBS_58;
     87         break;
     88         default: 
     89             return PHYMOD_E_PARAM;
     90     }
     91 
     92     return PHYMOD_E_NONE;
     93 }
     94 int _sesto_serdes_prbs_poly_to_phymod_prbs_poly(uint16_t serdes_poly, phymod_prbs_poly_t *phymod_poly)
     95 {
     96     switch (serdes_poly) {
     97         case PRBS_7:
     98             *phymod_poly = phymodPrbsPoly7;
     99         break; 
    100         case PRBS_9:
    101             *phymod_poly = phymodPrbsPoly9;
    102         break; 
    103         case PRBS_11:
    104             *phymod_poly = phymodPrbsPoly11;
    105         break; 
    106         case PRBS_15:
    107             *phymod_poly = phymodPrbsPoly15;
    108         break; 
    109         case PRBS_23:
    110             *phymod_poly = phymodPrbsPoly23;
    111         break; 
    112         case PRBS_31:
    113             *phymod_poly = phymodPrbsPoly31;
    114         break; 
    115         case PRBS_58:
    116             *phymod_poly = phymodPrbsPoly58;
    117         break; 
    118         default: 
    119             return PHYMOD_E_PARAM;
    120     }
    121 
    122     return PHYMOD_E_NONE;
    123 }
    124 
    125 int _sesto_phy_prbs_config_set(const phymod_phy_access_t* phy, uint32_t flags , const phymod_prbs_t* prbs)
    126 {
    127     phymod_phy_inf_config_t config;
    128     uint16_t ip = 0;
    129     uint16_t lane = 0, max_lane = 0;
    130     uint16_t lane_mask = 0, cast_type = 0, mcast_val = 0;
    131     uint16_t prbs_poly = 0;
    132     int rv = PHYMOD_E_NONE;
    133     const phymod_access_t *pa = &phy->access;
    134 
    135     PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t));
    136     config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode");
    137     SESTO_IF_ERR_RETURN(
    138        _sesto_phy_interface_config_get(phy, 0, &config));
    139     lane_mask = PHYMOD_ACC_LANE_MASK(pa);
    140     SESTO_GET_IP(phy, config, ip);
    141     SESTO_IF_ERR_RETURN(
    142           _sesto_phymod_prbs_poly_to_serdes_prbs_poly (prbs->poly, &prbs_poly));
    143 
    144     max_lane = (ip == SESTO_FALCON_CORE) ? 
    145                    SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE;
    146 
    147     
    148     SESTO_GET_CORE_SLICE_INFO(phy, ip, config, &cast_type, &mcast_val);
    149 
    150     PHYMOD_DEBUG_VERBOSE(("IP:%s Max_lane:%d lanemask:0x%x cast Type:%x\n", 
    151                 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask, cast_type));
    152 
    153     if (cast_type != SESTO_CAST_INVALID) {
    154         for (lane = 0; lane < max_lane; lane ++) {
    155             if (lane_mask & (1 << lane)) {
    156                 SESTO_IF_ERR_RETURN (
    157                   _sesto_set_slice_reg (pa, cast_type, ip,
    158                               SESTO_DEV_PMA_PMD, mcast_val, lane));
    159                 if (flags == 0 || PHYMOD_PRBS_DIRECTION_TX_GET(flags)) {
    160                     if (ip == SESTO_FALCON_CORE) {
    161                         SESTO_IF_ERR_RETURN(
    162                             falcon_furia_sesto_config_tx_prbs(pa, prbs_poly, (uint8_t)prbs->invert)); 
    163                     } else {
    164                         SESTO_IF_ERR_RETURN(
    165                             merlin_sesto_config_tx_prbs(pa, prbs_poly, (uint8_t)prbs->invert)); 
    166                     }
    167                 }
    168                 if (PHYMOD_PRBS_DIRECTION_RX_GET(flags) || flags == 0) {
    169                     /* Enabling PRBS CHECKER SELF SYNC HYS*/
    170                     if (ip == SESTO_FALCON_CORE) {
    171                         SESTO_IF_ERR_RETURN(
    172                                 falcon_furia_sesto_config_rx_prbs(pa, prbs_poly, 0, 
    173                                 (uint8_t)prbs->invert));
    174                     } else {
    175                         SESTO_IF_ERR_RETURN(
    176                             merlin_sesto_config_rx_prbs(pa, prbs_poly, 0, 
    177                                 (uint8_t)prbs->invert)); 
    178                     }
    179                 }
    180                 if (SESTO_IS_MULTI_BROAD_CAST_SET(cast_type)) {
    181                     break;
    182                 }
    183             }
    184         }
    185     } else {
    186         PHYMOD_DEBUG_VERBOSE(("Lane mask not Fine \n"));
    187         return PHYMOD_E_PARAM;
    188     }
    189 
    190 ERR:
    191     SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD);
    192     PHYMOD_FREE(config.device_aux_modes);
    193 
    194     return rv;
    195 }
    196 
    197 int _sesto_phy_prbs_enable_set(const phymod_phy_access_t* phy, uint32_t flags, uint32_t enable)
    198 {
    199     phymod_phy_inf_config_t config;
    200     uint16_t ip = 0;
    201     uint16_t lane = 0, max_lane = 0, dig_lpbk_en = 0;
    202     uint16_t lane_mask = 0, cast_type = 0, mcast_val = 0;
    203     int rv = PHYMOD_E_NONE;
    204     const phymod_access_t *pa = &phy->access;
    205 
    206     PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t));
    207     config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode");
    208     SESTO_IF_ERR_RETURN(
    209        _sesto_phy_interface_config_get(phy, 0, &config));
    210 
    211     SESTO_GET_IP(phy, config, ip);
    212     max_lane = (ip == SESTO_FALCON_CORE) ? 
    213                    SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE;
    214 
    215     lane_mask = PHYMOD_ACC_LANE_MASK(pa);
    216     SESTO_GET_CORE_SLICE_INFO(phy, ip, config, &cast_type, &mcast_val);
    217 
    218     PHYMOD_DEBUG_VERBOSE(("IP:%s Max_lane:%d lanemask:0x%x cast type:%d\n", 
    219                 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask, cast_type));
    220 
    221     if (cast_type != SESTO_CAST_INVALID) {
    222         for (lane = 0; lane < max_lane; lane ++) {
    223             if (lane_mask & (1 << lane)) {
    224                 SESTO_IF_ERR_RETURN (
    225                   _sesto_set_slice_reg (pa, cast_type, ip,
    226                               SESTO_DEV_PMA_PMD, mcast_val, lane));
    227                if (flags == 0 || PHYMOD_PRBS_DIRECTION_TX_GET(flags)) {
    228                    if (ip == SESTO_FALCON_CORE) {
    229                        SESTO_IF_ERR_RETURN(
    230                            falcon_furia_sesto_tx_prbs_en(pa, enable));
    231                    } else {
    232                        SESTO_IF_ERR_RETURN(
    233                             merlin_sesto_tx_prbs_en(pa, enable));
    234                    }
    235                }
    236                if (PHYMOD_PRBS_DIRECTION_RX_GET(flags) || flags == 0) {
    237                     /* Enabling PRBS CHECKER SELF SYNC HYS*/
    238                    if (ip == SESTO_FALCON_CORE) {
    239                        if (enable) {
    240                            SESTO_IF_ERR_RETURN (
    241 	                          wr_falcon_furia_sesto_prbs_chk_clk_en_frc_on(1));
    242                            /* Check for digital loopback enable or not */
    243                            SESTO_CHIP_FIELD_READ(pa, F25G_TLB_RX_DIG_LPBK_CONFIG,
    244                                       dig_lpbk_en, dig_lpbk_en);
    245                            /* Do not enable prbs_chk_en_auto_mode when digital lpbk is set */
    246                            if (!dig_lpbk_en) {
    247                                SESTO_IF_ERR_RETURN (
    248                                   wr_falcon_furia_sesto_prbs_chk_en_auto_mode(1));
    249                            }
    250                        }
    251                        SESTO_IF_ERR_RETURN(
    252                             falcon_furia_sesto_rx_prbs_en(pa, enable));
    253                        if (!enable) {
    254                            SESTO_IF_ERR_RETURN (
    255 	                          wr_falcon_furia_sesto_prbs_chk_clk_en_frc_on(0));
    256                            SESTO_IF_ERR_RETURN (
    257                               wr_falcon_furia_sesto_prbs_chk_en_auto_mode(0));
    258                        }
    259                    } else {
    260                        if (enable) {
    261                            SESTO_IF_ERR_RETURN (
    262                                 wr_prbs_chk_clk_en_frc_on(1));
    263                            /* Check for digital loopback enable or not */
    264                            SESTO_CHIP_FIELD_READ(pa, M10G_TLB_RX_DIG_LPBK_CONFIG,
    265                                       dig_lpbk_en, dig_lpbk_en);
    266                            /* Do not enable prbs_chk_en_auto_mode when digital lpbk is set */
    267                            if (!dig_lpbk_en) {
    268                                SESTO_IF_ERR_RETURN (
    269                                     wr_prbs_chk_en_auto_mode(1));
    270                            } 
    271                        }
    272                        SESTO_IF_ERR_RETURN (
    273                             merlin_sesto_rx_prbs_en(pa, enable));
    274                        if (!enable) {
    275                            SESTO_IF_ERR_RETURN (
    276 	                          wr_prbs_chk_clk_en_frc_on(0));
    277                            SESTO_IF_ERR_RETURN (
    278                                 wr_prbs_chk_en_auto_mode(0));
    279                        }
    280                    }
    281                }
    282                if (SESTO_IS_MULTI_BROAD_CAST_SET(cast_type)) {
    283                    break;
    284                }
    285             }
    286         }
    287     } else {
    288         PHYMOD_DEBUG_VERBOSE(("Lane mask not Fine \n"));
    289         return PHYMOD_E_PARAM;
    290     }
    291 
    292 ERR:
    293     SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD);
    294     PHYMOD_FREE(config.device_aux_modes);
    295 
    296     return rv;
    297 }
    298 
    299 int _sesto_phy_prbs_enable_get(const phymod_phy_access_t* phy, uint32_t flags, uint32_t *enable)
    300 {
    301     phymod_phy_inf_config_t config;
    302     uint16_t ip = 0;
    303     uint16_t lane = 0, max_lane = 0, lane_mask = 0;
    304     uint8_t gen_en = 0, ckr_en = 0;
    305     int rv = PHYMOD_E_NONE;
    306     const phymod_access_t *pa = &phy->access;
    307 
    308     PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t));
    309     config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode");
    310     SESTO_IF_ERR_RETURN(
    311        _sesto_phy_interface_config_get(phy, 0, &config));
    312 
    313     SESTO_GET_IP(phy, config, ip);
    314     max_lane = (ip == SESTO_FALCON_CORE) ? 
    315                    SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE;
    316 
    317     lane_mask = PHYMOD_ACC_LANE_MASK(pa);
    318     PHYMOD_DEBUG_VERBOSE(("%s :: IP:%s Max_lane:%d lanemask:0x%x\n", __func__,
    319                 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask));
    320 
    321     for (lane = 0; lane < max_lane; lane ++) {
    322         if ((lane_mask & (1 << lane))) {
    323             SESTO_IF_ERR_RETURN (
    324                 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip,
    325                      SESTO_DEV_PMA_PMD, 0, lane));
    326             if (flags == 0 || PHYMOD_PRBS_DIRECTION_TX_GET(flags)) {
    327                 if (ip == SESTO_FALCON_CORE) {
    328                     SESTO_IF_ERR_RETURN(
    329                           falcon_furia_sesto_get_tx_prbs_en(pa, &gen_en));
    330                     *enable = gen_en;
    331                 } else {
    332                     SESTO_IF_ERR_RETURN(
    333                           merlin_sesto_get_tx_prbs_en(pa, &gen_en));
    334                     *enable = gen_en;
    335                 }
    336             }
    337             if (flags == 0 || PHYMOD_PRBS_DIRECTION_RX_GET(flags)) {
    338                 if (ip == SESTO_FALCON_CORE) {
    339                     SESTO_IF_ERR_RETURN(
    340                             falcon_furia_sesto_get_rx_prbs_en(pa, &ckr_en));
    341                     *enable = ckr_en;
    342                 } else {
    343                     SESTO_IF_ERR_RETURN(
    344                           merlin_sesto_get_rx_prbs_en(pa, &ckr_en));
    345                     *enable = ckr_en;
    346                 }
    347             }
    348             break;
    349         }
    350     }
    351     if (flags == 0) {
    352         *enable = ckr_en & gen_en;
    353     } 
    354 
    355 ERR:
    356     SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD);
    357     PHYMOD_FREE(config.device_aux_modes);
    358 
    359     return rv;
    360 }
    361 
    362 int _sesto_phy_prbs_config_get(const phymod_phy_access_t* phy, uint32_t flags , phymod_prbs_t* prbs)
    363 {
    364     phymod_phy_inf_config_t config;
    365     uint16_t ip = 0;
    366     uint16_t lane = 0, max_lane = 0, lane_mask;
    367     uint8_t data = 0;
    368     int rv = PHYMOD_E_NONE;
    369     enum srds_prbs_checker_mode_enum temp = 0;
    370     enum srds_prbs_polynomial_enum serdes_poly = 0;
    371     const phymod_access_t *pa = &phy->access;
    372 
    373     PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t));
    374     config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode");
    375     SESTO_IF_ERR_RETURN(
    376        _sesto_phy_interface_config_get(phy, 0, &config));
    377 
    378     SESTO_GET_IP(phy, config, ip);
    379     max_lane = (ip == SESTO_FALCON_CORE) ? 
    380                    SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE;
    381 
    382     lane_mask = PHYMOD_ACC_LANE_MASK(pa);
    383     PHYMOD_DEBUG_VERBOSE(("IP:%s Max_lane:%d lanemask:0x%x\n", 
    384                 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask));
    385 
    386     for (lane = 0; lane < max_lane; lane ++) {
    387         if ((lane_mask & (1 << lane))) {
    388            SESTO_IF_ERR_RETURN (
    389               _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip,
    390                    SESTO_DEV_PMA_PMD, 0, lane));
    391 
    392             if (flags == 0 || PHYMOD_PRBS_DIRECTION_TX_GET(flags)) {
    393                 if (ip == SESTO_FALCON_CORE) {
    394                     SESTO_IF_ERR_RETURN(falcon_furia_sesto_get_tx_prbs_config(pa, &serdes_poly, &data));
    395                     prbs->invert = data;                                          
    396                 } else { 
    397                     SESTO_IF_ERR_RETURN(merlin_sesto_get_tx_prbs_config(pa, &serdes_poly, &data));
    398                     prbs->invert = data;                                          
    399                 }                                                                 
    400             }                                                                     
    401             if (flags == 0 || PHYMOD_PRBS_DIRECTION_RX_GET(flags)) {              
    402                 if (ip == SESTO_FALCON_CORE) {                                    
    403                     SESTO_IF_ERR_RETURN(falcon_furia_sesto_get_rx_prbs_config(pa, &serdes_poly, &temp, &data));
    404                     prbs->invert = data;                                          
    405                 } else {
    406                     SESTO_IF_ERR_RETURN(merlin_sesto_get_rx_prbs_config(pa, &serdes_poly, &temp, &data));
    407                     prbs->invert = data;
    408                 }
    409             }
    410             break;
    411         }
    412     }
    413 
    414     PHYMOD_DEBUG_VERBOSE(("Checker POLY:%d\n", serdes_poly));
    415     SESTO_IF_ERR_RETURN (
    416         _sesto_serdes_prbs_poly_to_phymod_prbs_poly(serdes_poly, &prbs->poly));
    417 
    418 ERR:
    419     SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD);
    420     PHYMOD_FREE(config.device_aux_modes);
    421 
    422     return rv;
    423 }
    424 
    425 int _sesto_phy_prbs_status_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_prbs_status_t* prbs_status)
    426 {
    427     phymod_phy_inf_config_t config;
    428     uint16_t ip = 0;
    429     uint16_t lane = 0, max_lane = 0, lane_mask = 0;
    430     uint8_t data = 0;
    431     uint32_t err_cnt = 0;
    432     int rv = PHYMOD_E_NONE;
    433     const phymod_access_t *pa = &phy->access;
    434 
    435     PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t));
    436     config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode");
    437     SESTO_IF_ERR_RETURN(
    438        _sesto_phy_interface_config_get(phy, 0, &config));
    439 
    440     SESTO_GET_IP(phy, config, ip);
    441     max_lane = (ip == SESTO_FALCON_CORE) ? 
    442                    SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE;
    443 
    444     lane_mask = PHYMOD_ACC_LANE_MASK(pa);
    445     PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n",  __func__,
    446                 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask));
    447     prbs_status->prbs_lock = 1;
    448     prbs_status->prbs_lock_loss = 1;
    449     for (lane = 0; lane < max_lane; lane ++) {
    450         if ((lane_mask & (1 << lane))) {
    451             SESTO_IF_ERR_RETURN (
    452                 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip,
    453                      SESTO_DEV_PMA_PMD, 0, lane));
    454             if (ip == SESTO_FALCON_CORE) {
    455                 SESTO_IF_ERR_RETURN(falcon_furia_sesto_prbs_chk_lock_state(pa, &data));
    456                 prbs_status->prbs_lock &= data;
    457                 SESTO_IF_ERR_RETURN(falcon_furia_sesto_prbs_err_count_state(pa, &err_cnt, &data));
    458                 prbs_status->prbs_lock_loss &= data;
    459                 prbs_status->error_count |= err_cnt;
    460             } else {
    461                 SESTO_IF_ERR_RETURN(merlin_sesto_prbs_chk_lock_state(pa, &data));
    462                 prbs_status->prbs_lock &= data;
    463                 SESTO_IF_ERR_RETURN(merlin_sesto_prbs_err_count_state(pa, &err_cnt, &data));
    464                 prbs_status->prbs_lock_loss &= data;
    465                 prbs_status->error_count |= err_cnt;
    466             }
    467             READ_SESTO_PMA_PMD_REG(pa, 0x8000, data);
    468         }
    469     }
    470 
    471 ERR:
    472     SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD);
    473     PHYMOD_FREE(config.device_aux_modes);
    474 
    475     return rv;
    476 }
    477 
    478 int _sesto_phy_display_eyescan(const phymod_phy_access_t *phy)
    479 {
    480     phymod_phy_inf_config_t config;
    481     uint16_t ip = 0;
    482     uint16_t lane = 0, max_lane = 0;
    483     uint16_t lane_mask = 0;
    484     int rv = PHYMOD_E_NONE;
    485     const phymod_access_t *pa = &phy->access;
    486 
    487     PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t));
    488     config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode");
    489     SESTO_IF_ERR_RETURN(
    490        _sesto_phy_interface_config_get(phy, 0, &config));
    491 
    492     SESTO_GET_IP(phy, config, ip)
    493     max_lane = (ip == SESTO_FALCON_CORE) ? 
    494                    SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE;
    495 
    496     lane_mask = PHYMOD_ACC_LANE_MASK(pa);
    497     PHYMOD_DEBUG_VERBOSE(("%s::IP:%s Max_lane:%d lanemask:0x%x\n", __func__,
    498                 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask));
    499 
    500     SESTO_IF_ERR_RETURN (
    501         _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, SESTO_DEV_PMA_PMD, 0, 0));
    502     if (ip == SESTO_FALCON_CORE) {
    503         SESTO_IF_ERR_RETURN
    504             (falcon_furia_sesto_display_core_state_hdr(pa));
    505         SESTO_IF_ERR_RETURN
    506             (falcon_furia_sesto_display_core_state_line(pa));
    507     } else {
    508         SESTO_IF_ERR_RETURN
    509             (merlin_sesto_display_core_state_hdr(pa)) ;
    510         SESTO_IF_ERR_RETURN
    511             (merlin_sesto_display_core_state_line(pa));
    512     }
    513 
    514     for (lane = 0; lane < max_lane; lane++) {
    515         if ((lane_mask & (1 << lane))) {
    516             SESTO_IF_ERR_RETURN (
    517                 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip,
    518                      SESTO_DEV_PMA_PMD, 0, lane));
    519             
    520             /* set the core to get the master /slave */
    521             /* System side always master Line side considered as slave*/
    522             if (ip == SESTO_FALCON_CORE) {
    523                 SESTO_IF_ERR_RETURN
    524                     (falcon_furia_sesto_display_lane_state_hdr(pa));
    525                 SESTO_IF_ERR_RETURN
    526                     (falcon_furia_sesto_display_lane_state(pa)); 
    527                 SESTO_IF_ERR_RETURN
    528                     (falcon_furia_sesto_display_eye_scan(pa));
    529             } else {
    530                 SESTO_IF_ERR_RETURN
    531                     (merlin_sesto_display_lane_state_hdr(pa));
    532                 SESTO_IF_ERR_RETURN
    533                     (merlin_sesto_display_lane_state(pa)); 
    534                 SESTO_IF_ERR_RETURN
    535                     (merlin_sesto_display_eye_scan(pa));
    536             }
    537         }
    538     }
    539 
    540 ERR:
    541     SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD);
    542     PHYMOD_FREE(config.device_aux_modes);
    543 
    544     return rv;
    545 }
    546 
    547 int _sesto_core_diagnostics_get(const phymod_core_access_t* core, phymod_core_diagnostics_t* diag)
    548 {
    549     phymod_phy_inf_config_t config;
    550     uint16_t ip = 0;
    551     int16_t temp = 0;
    552     phymod_phy_access_t phy;
    553     int rv = PHYMOD_E_NONE;
    554     const phymod_access_t *pa = &core->access;
    555 
    556     PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t));
    557     PHYMOD_MEMCPY(&phy, core, sizeof(phymod_core_access_t));
    558     config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode");
    559     SESTO_IF_ERR_RETURN(
    560        _sesto_phy_interface_config_get(&phy, 0, &config));
    561 
    562     SESTO_GET_IP(core, config, ip);
    563     PHYMOD_DEBUG_VERBOSE(("%s::IP:%s \n", __func__,(ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON"));
    564 
    565     if (ip == SESTO_FALCON_CORE) { /* Falcon core status dump */
    566         SESTO_IF_ERR_RETURN(
    567             _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST,
    568                 SESTO_FALCON_CORE, SESTO_DEV_PMA_PMD, 0, 0));
    569         SESTO_IF_ERR_RETURN(falcon_furia_sesto_read_die_temperature(pa, &temp));
    570         diag->temperature = temp;
    571         SESTO_IF_ERR_RETURN(_sesto_falcon_read_pll_range(&core->access, &diag->pll_range));
    572     } else {  /* Merlin core status dump */
    573         SESTO_IF_ERR_RETURN(
    574             _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST,
    575                 SESTO_MERLIN_CORE, SESTO_DEV_PMA_PMD, 0, 0));
    576         SESTO_IF_ERR_RETURN(merlin_sesto_read_die_temperature(pa, &temp));
    577         diag->temperature = temp;
    578         SESTO_IF_ERR_RETURN(_sesto_merlin_read_pll_range(&core->access, &diag->pll_range));
    579     }
    580 ERR:
    581     SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD);
    582     PHYMOD_FREE(config.device_aux_modes);
    583 
    584     return rv;
    585 }
    586 
    587 int _sesto_phy_diagnostics_get(const phymod_phy_access_t *phy, phymod_phy_diagnostics_t* diag)
    588 {
    589     phymod_phy_inf_config_t config;
    590     uint16_t ip = 0;
    591     uint16_t lane = 0, max_lane = 0;
    592     uint16_t lane_mask = 0;
    593     int rv = PHYMOD_E_NONE;
    594     const phymod_access_t *pa = &phy->access;
    595 
    596     PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t));
    597     config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode");
    598     SESTO_IF_ERR_RETURN(
    599        _sesto_phy_interface_config_get(phy, 0, &config));
    600 
    601     SESTO_GET_IP(phy, config, ip);
    602     max_lane = (ip == SESTO_FALCON_CORE) ?
    603                    SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE;
    604 
    605     lane_mask = PHYMOD_ACC_LANE_MASK(pa);
    606     PHYMOD_DEBUG_VERBOSE(("%s::IP:%s Max_lane:%d lanemask:0x%x\n", __func__,
    607                 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask));
    608 
    609     for (lane = 0; lane < max_lane; lane++) {
    610         if ((lane_mask & (1 << lane))) {
    611             SESTO_IF_ERR_RETURN (
    612                 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip,
    613                      SESTO_DEV_PMA_PMD, 0, lane));
    614             PHYMOD_DEBUG_VERBOSE(("Phy Diagnostics for Lane:%d \n",lane));
    615             /* set the core to get the master /slave */
    616             /* System side always master Line side considered as slave*/
    617             if (ip == SESTO_FALCON_CORE) {
    618                 falcon_furia_sesto_lane_state_define_st state;
    619                 PHYMOD_MEMSET(&state, 0, sizeof(falcon_furia_sesto_lane_state_define_st));
    620                 SESTO_IF_ERR_RETURN
    621                         (_falcon_furia_sesto_read_lane_state_define(pa, &state));
    622                 diag->signal_detect = state.sig_det;
    623                 diag->osr_mode = state.osr_mode.tx_rx;
    624                 diag->rx_lock = state.rx_lock;
    625                 diag->tx_ppm = state.tx_ppm;
    626                 diag->clk90_offset = state.clk90;
    627                 diag->clkp1_offset = state.clkp1;
    628                 diag->p1_lvl = state.p1_lvl;
    629                 diag->dfe1_dcd = state.dfe1_dcd;
    630                 diag->dfe2_dcd = state.dfe2_dcd;
    631                 diag->slicer_offset.offset_pe = state.pe;
    632                 diag->slicer_offset.offset_ze = state.ze;
    633                 diag->slicer_offset.offset_me = state.me;
    634                 diag->slicer_offset.offset_po = state.po;
    635                 diag->slicer_offset.offset_zo = state.zo;
    636                 diag->slicer_offset.offset_mo = state.mo;
    637                 diag->eyescan.heye_left = state.heye_left;
    638                 diag->eyescan.heye_right = state.heye_right;
    639                 diag->eyescan.veye_upper = state.veye_upper;
    640                 diag->eyescan.veye_lower = state.veye_lower;
    641                 diag->link_time = state.link_time;
    642                 diag->pf_main = state.pf_main;
    643                 diag->pf_hiz = state.pf_hiz;
    644                 diag->pf_bst = state.pf_bst;
    645                 diag->pf_low = 0; /* Not Availble in serdes API*/
    646                 diag->pf2_ctrl = state.pf2_ctrl;
    647                 diag->vga = state.vga;
    648                 diag->dc_offset = state.dc_offset;
    649                 diag->p1_lvl_ctrl = state.p1_lvl_ctrl;
    650                 diag->dfe1 = state.dfe1;
    651                 diag->dfe2 = state.dfe2;
    652                 diag->dfe3 = state.dfe3;
    653                 diag->dfe4 = state.dfe4;
    654                 diag->dfe5 = state.dfe5;
    655                 diag->dfe6 = state.dfe6;
    656                 diag->txfir_pre = state.txfir_pre;
    657                 diag->txfir_main = state.txfir_main;
    658                 diag->txfir_post1 = state.txfir_post1;
    659                 diag->txfir_post2 = state.txfir_post2;
    660                 diag->txfir_post3 = state.txfir_post3;
    661                 diag->tx_amp_ctrl = 0; /* Not Availble in serdes API*/
    662                 diag->br_pd_en = state.br_pd_en;
    663                 break;
    664             } else {
    665                 merlin_sesto_lane_state_define_st state;
    666                 SESTO_IF_ERR_RETURN
    667                     (_merlin_sesto_read_lane_state_define(pa, &state));
    668                 diag->signal_detect = state.sig_det;
    669                 diag->osr_mode = state.osr_mode.tx_rx;
    670                 diag->rx_lock = state.rx_lock;
    671                 diag->tx_ppm = state.tx_ppm;
    672                 diag->clk90_offset = state.clk90;
    673                 diag->clkp1_offset = state.clkp1;
    674                 diag->p1_lvl = state.p1_lvl;
    675                 diag->dfe1_dcd = state.dfe1_dcd;
    676                 diag->dfe2_dcd = state.dfe2_dcd;
    677                 diag->slicer_offset.offset_pe = state.pe;
    678                 diag->slicer_offset.offset_ze = state.ze;
    679                 diag->slicer_offset.offset_me = state.me;
    680                 diag->slicer_offset.offset_po = state.po;
    681                 diag->slicer_offset.offset_zo = state.zo;
    682                 diag->slicer_offset.offset_mo = state.mo;
    683                 diag->eyescan.heye_left = state.heye_left;
    684                 diag->eyescan.heye_right = state.heye_right;
    685                 diag->eyescan.veye_upper = state.veye_upper;
    686                 diag->eyescan.veye_lower = state.veye_lower;
    687                 diag->link_time = state.link_time;
    688                 diag->pf_main = state.pf_main;
    689                 diag->pf_hiz = state.pf_hiz;
    690                 diag->pf_bst = state.pf_bst;
    691                 diag->pf_low = 0; /* Not Availble in serdes API*/
    692                 diag->pf2_ctrl = state.pf2_ctrl;
    693                 diag->vga = state.vga;
    694                 diag->dc_offset = state.dc_offset;
    695                 diag->p1_lvl_ctrl = state.p1_lvl_ctrl;
    696                 diag->dfe1 = state.dfe1;
    697                 diag->dfe2 = state.dfe2;
    698                 diag->dfe3 = state.dfe3;
    699                 diag->dfe4 = state.dfe4;
    700                 diag->dfe5 = state.dfe5;
    701                 diag->dfe6 = state.dfe6;
    702                 diag->txfir_pre = state.txfir_pre;
    703                 diag->txfir_main = state.txfir_main;
    704                 diag->txfir_post1 = state.txfir_post1;
    705                 diag->txfir_post2 = state.txfir_post2;
    706                 diag->txfir_post3 = state.txfir_post3;
    707                 diag->tx_amp_ctrl = 0; /* Not Availble in serdes API*/
    708                 diag->br_pd_en = state.br_pd_en;
    709                 break;
    710             }
    711         }
    712     }
    713 
    714 ERR:
    715     SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD);
    716     PHYMOD_FREE(config.device_aux_modes);
    717 
    718     return rv;
    719 }
    720 int _sesto_ber_proj_lane_speed_get(phymod_phy_inf_config_t *config, uint16_t ip, uint32_t *speed)
    721 {
    722     SESTO_DEVICE_AUX_MODE_T  *aux;
    723     aux = (SESTO_DEVICE_AUX_MODE_T*) config->device_aux_modes;
    724 
    725     if (ip == SESTO_FALCON_CORE) {
    726         if (config->data_rate == SESTO_SPD_100G || config->data_rate == SESTO_SPD_106G) {
    727             *speed = 25781250;
    728             if (PHYMOD_INTF_MODES_OTN_GET(config)) {
    729                 *speed = 27952500;
    730             } else if (PHYMOD_INTF_MODES_HIGIG_GET(config)) {
    731                 *speed = 27343750;
    732             }
    733         } else if ((config->data_rate == SESTO_SPD_40G || config->data_rate == SESTO_SPD_42G) && (!aux->pass_thru)) {
    734             *speed = 20625000;
    735             if (PHYMOD_INTF_MODES_HIGIG_GET(config)) {
    736                 *speed = 21875000;
    737             }
    738         } else if ((config->data_rate == SESTO_SPD_20G || config->data_rate == SESTO_SPD_21G) && (!aux->pass_thru)) {
    739             *speed = 20625000;
    740             if (PHYMOD_INTF_MODES_HIGIG_GET(config)) {
    741                 *speed = 21875000;
    742             }
    743         } else {
    744             *speed = 10312500;
    745             if (PHYMOD_INTF_MODES_OTN_GET(config)) {
    746                 *speed = 10937500;
    747             } else if (PHYMOD_INTF_MODES_HIGIG_GET(config)) {
    748                 *speed = 11180000;
    749             }
    750         }
    751     } else {
    752             *speed = 10312500;
    753             if (PHYMOD_INTF_MODES_OTN_GET(config)) {
    754                 *speed = 10937500;
    755             } else if (PHYMOD_INTF_MODES_HIGIG_GET(config)) {
    756                 *speed = 11180000;
    757             }
    758     }
    759 
    760     return PHYMOD_E_NONE;
    761 }
    762 int _sesto_ber_proj(const phymod_phy_access_t *phy, const phymod_phy_eyescan_options_t* eyescan_options)
    763 {
    764     phymod_phy_inf_config_t config;
    765     uint16_t ip = 0;
    766     uint16_t lane = 0, max_lane = 0;
    767     uint16_t lane_mask = 0;
    768     int rv = PHYMOD_E_NONE;
    769     const phymod_access_t *pa = &phy->access;
    770 #ifdef SERDES_API_FLOATING_POINT
    771     uint32_t speed;
    772     USR_DOUBLE speedD;
    773 #endif
    774 
    775     PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t));
    776     config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode");
    777     SESTO_IF_ERR_RETURN(
    778        _sesto_phy_interface_config_get(phy, 0, &config));
    779 
    780     SESTO_GET_IP(phy, config, ip);
    781     max_lane = (ip == SESTO_FALCON_CORE) ?
    782                    SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE;
    783 
    784     lane_mask = PHYMOD_ACC_LANE_MASK(pa);
    785     PHYMOD_DEBUG_VERBOSE(("%s::IP:%s Max_lane:%d lanemask:0x%x\n", __func__,
    786                 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask));
    787 
    788     SESTO_IF_ERR_RETURN (
    789         _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, SESTO_DEV_PMA_PMD, 0, 0));
    790     if (ip == SESTO_FALCON_CORE) {
    791         SESTO_IF_ERR_RETURN
    792             (falcon_furia_sesto_display_core_state_hdr(pa));
    793         SESTO_IF_ERR_RETURN
    794             (falcon_furia_sesto_display_core_state_line(pa));
    795     } else {
    796         SESTO_IF_ERR_RETURN
    797             (merlin_sesto_display_core_state_hdr(pa)) ;
    798         SESTO_IF_ERR_RETURN
    799             (merlin_sesto_display_core_state_line(pa));
    800     }
    801 
    802     for (lane = 0; lane < max_lane; lane++) {
    803         if ((lane_mask & (1 << lane))) {
    804             SESTO_IF_ERR_RETURN (
    805                 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip,
    806                      SESTO_DEV_PMA_PMD, 0, lane));
    807 
    808             PHYMOD_DEBUG_VERBOSE(("eye_margin_proj for Lane:%d \n",lane));
    809             if (ip == SESTO_FALCON_CORE) {
    810                 SESTO_IF_ERR_RETURN
    811                     (falcon_furia_sesto_display_lane_state_hdr(pa));
    812                 SESTO_IF_ERR_RETURN
    813                     (falcon_furia_sesto_display_lane_state(pa));
    814 #ifdef SERDES_API_FLOATING_POINT
    815                 SESTO_IF_ERR_RETURN
    816                     (_sesto_ber_proj_lane_speed_get(&config, ip, &speed));
    817                 speedD = speed * 1000.0;
    818                 SESTO_IF_ERR_RETURN
    819                     (falcon_furia_sesto_eye_margin_proj(pa, speedD, eyescan_options->ber_proj_scan_mode,
    820                                eyescan_options->ber_proj_timer_cnt, eyescan_options->ber_proj_err_cnt));
    821 #else
    822                 PHYMOD_DIAG_OUT(("BER PROJ needs SERDES_API_FLOATING_POINT define to operate\n"));
    823                 rv = PHYMOD_E_RESOURCE;
    824 #endif
    825 
    826             } else {
    827                 SESTO_IF_ERR_RETURN
    828                     (merlin_sesto_display_lane_state_hdr(pa));
    829                 SESTO_IF_ERR_RETURN
    830                     (merlin_sesto_display_lane_state(pa));
    831 #ifdef SERDES_API_FLOATING_POINT
    832                 SESTO_IF_ERR_RETURN
    833                     (_sesto_ber_proj_lane_speed_get(&config, ip, &speed));
    834                 speedD = speed * 1000.0;
    835                 SESTO_IF_ERR_RETURN
    836                     (merlin_sesto_eye_margin_proj(pa, speedD, eyescan_options->ber_proj_scan_mode,
    837                                eyescan_options->ber_proj_timer_cnt, eyescan_options->ber_proj_err_cnt));
    838                 /*Work around for PRBS Locked with Errors */
    839 #else
    840                 PHYMOD_DIAG_OUT(("BER PROJ needs SERDES_API_FLOATING_POINT define to operate\n"));
    841                 rv = PHYMOD_E_RESOURCE;
    842 #endif
    843                 SESTO_IF_ERR_RETURN
    844                     (wr_trnsum_error_count_en(0));
    845             }
    846         }
    847     }
    848 
    849 ERR:
    850     SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD);
    851     PHYMOD_FREE(config.device_aux_modes);
    852 
    853     return rv;
    854 }