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 }