eagle_tsc_functions.c (106705B)
1 /*********************************************************************************** 2 *********************************************************************************** 3 * File Name : eagle_tsc_functions.c * 4 * Created On : 29/04/2013 * 5 * Created By : Kiran Divakar * 6 * Description : APIs for Serdes IPs * 7 * * 8 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 9 * 10 * Copyright 2007-2019 Broadcom Inc. All rights reserved. * 11 * No portions of this material may be reproduced in any form without * 12 * the written permission of: * 13 * Broadcom Corporation * 14 * 5300 California Avenue * 15 * Irvine, CA 92617 * 16 * * 17 * All information contained in this document is Broadcom Corporation * 18 * company private proprietary, and trade secret. * 19 */ 20 21 /** @file eagle_tsc_functions.c 22 * Implementation of API functions 23 */ 24 25 #include <phymod/phymod.h> 26 #include <phymod/phymod_system.h> 27 28 #ifdef _MSC_VER 29 /* Enclose all standard headers in a pragma to remove warings for MS compiler */ 30 #pragma warning( push, 0 ) 31 #endif 32 33 #ifdef SERDES_API_FLOATING_POINT 34 #include <math.h> 35 #endif 36 #ifdef _MSC_VER 37 #pragma warning( pop ) 38 #endif 39 40 #include "eagle_tsc_functions.h" 41 #include "eagle_tsc_field_access_c.h" 42 #include "eagle_tsc_internal_c.h" 43 #include "eagle_tsc_dv_functions_c.h" 44 45 46 #include "eagle_tsc_pll_config_c.h" 47 48 49 50 51 52 /************************************/ 53 /* Display Eye Scan */ 54 /************************************/ 55 56 /* This is best method for terminal ASCII display */ 57 err_code_t eagle_tsc_display_eye_scan( const phymod_access_t *pa ){ 58 uint32_t stripe[64]; 59 uint16_t status = 0; 60 int8_t y; 61 62 EFUN(eagle_tsc_display_eye_scan_header( pa, 1)); 63 64 /* start horizontal acquisition */ 65 { err_code_t err_code = eagle_tsc_meas_eye_scan_start(pa, EYE_SCAN_HORIZ); 66 if (err_code) 67 EFUN((eagle_tsc_meas_eye_scan_done( pa ), err_code)); } 68 69 /* display stripes */ 70 for (y = 31; y >= -31; y = y - 1) { 71 { err_code_t err_code = eagle_tsc_read_eye_scan_stripe( pa, &stripe[0], &status); 72 if (err_code) 73 EFUN((eagle_tsc_meas_eye_scan_done( pa ), err_code)); } 74 EFUN(eagle_tsc_display_eye_scan_stripe( pa, y, &stripe[0])); 75 EFUN_PRINTF(("\n")); 76 } 77 /* stop acquisition */ 78 EFUN(eagle_tsc_meas_eye_scan_done( pa )); 79 EFUN(eagle_tsc_display_eye_scan_footer( pa, 1)); 80 81 return ERR_CODE_NONE; 82 } 83 84 /* This function is for Falcon and is configured for passive mode */ 85 err_code_t eagle_tsc_meas_lowber_eye( const phymod_access_t *pa, const struct eagle_tsc_eyescan_options_st eyescan_options, uint32_t *buffer){ 86 int8_t y, x; 87 int16_t i; 88 uint16_t status; 89 uint32_t errors = 0; 90 uint16_t timeout; 91 uint8_t stopped_state; 92 93 if (!buffer) 94 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 95 i = 0; 96 ESTM(stopped_state = rdv_usr_sts_micro_stopped()); 97 98 timeout = eyescan_options.timeout_in_milliseconds; 99 EFUN(wrcv_diag_max_time_control((uint8_t)timeout)); 100 101 EFUN(wrv_usr_diag_mode(eyescan_options.mode)); 102 103 EFUN_PRINTF(("Calculating\n")); 104 for (y = eyescan_options.vert_max; y >= eyescan_options.vert_min; y = y - eyescan_options.vstep) { 105 for (x = eyescan_options.horz_min; x <= eyescan_options.horz_max; x = x + eyescan_options.hstep) { 106 /* acquire sample */ 107 EFUN(eagle_tsc_pmd_uc_cmd_with_data( pa, CMD_DIAG_EN, CMD_UC_DIAG_GET_EYE_SAMPLE, ((uint16_t)x) << 8 | (uint8_t)y, 200)); 108 /* wait for sample complete */ 109 #if 0 110 do { 111 EFUN(eagle_tsc_delay_us(1000)); 112 ESTM(status = rdv_usr_diag_status()); 113 EFUN_PRINTF(("status=%04x\n", status)); 114 } while ((status & 0x8000) == 0); 115 #else 116 EFUN(eagle_tsc_poll_diag_done( pa, &status, (((uint32_t)timeout) << 7) * 10 + 20000)); 117 #endif 118 { 119 eagle_tsc_osr_mode_st osr_mode; 120 ENULL_MEMSET(&osr_mode, 0, sizeof(eagle_tsc_osr_mode_st)); 121 EFUN(_eagle_tsc_get_osr_mode( pa, &osr_mode)); 122 if (osr_mode.tx_rx == EAGLE_TSC_OSX1) 123 EFUN(eagle_tsc_prbs_err_count_ll( pa, &errors)); 124 else if (osr_mode.tx_rx == EAGLE_TSC_OSX2) 125 ESTM(errors = ((uint32_t)rdv_usr_var_msb()) << 16 | rdv_usr_var_lsb()); 126 else { 127 EFUN_PRINTF(("Error: 2D eye scan is not supported for OSR Mode > 2\n")); 128 return ERR_CODE_BAD_PTR_OR_INVALID_INPUT; 129 } 130 } 131 /* EFUN_PRINTF(("(%d,%d) = %u\n",x,y,errors & 0x7FFFFFF)); */ 132 133 buffer[i] = errors & 0x7FFFFFFF; 134 135 i++; 136 EFUN_PRINTF((".")); 137 } 138 EFUN_PRINTF(("\n")); 139 } 140 EFUN_PRINTF(("\n")); 141 EFUN(eagle_tsc_meas_eye_scan_done( pa )); 142 EFUN(wrv_usr_sts_micro_stopped(stopped_state)); 143 return ERR_CODE_NONE; 144 } 145 146 147 /* Display the LOW BER EyeScan */ 148 err_code_t eagle_tsc_display_lowber_eye( const phymod_access_t *pa, const struct eagle_tsc_eyescan_options_st eyescan_options, uint32_t *buffer){ 149 int8_t x, y, i, z; 150 int16_t j; /* buffer pointer */ 151 uint32_t val; 152 uint8_t overflow; 153 uint32_t limits[13]; /* allows upto 400 sec test time per point (1e-13 BER @ 10G) */ 154 155 if (!buffer) 156 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 157 158 /* Calculate initial total bitcount BER 1e-1 */ 159 limits[0] = _mult_with_overflow_check(eyescan_options.linerate_in_khz / 10, eyescan_options.timeout_in_milliseconds, &overflow); 160 if (overflow > 0) { 161 limits[0] = UINT32_MAX; 162 EFUN_PRINTF(("Very long timout_in_milliseconds results in saturation of Err counter can cause in accurate results\n")); 163 } 164 165 for (i = 1; i < 13; i++) /* calculate thresholds */ 166 limits[i] = limits[i - 1] / 10; 167 168 EFUN(eagle_tsc_display_eye_scan_header( pa, 1)); 169 j = 0; 170 for (y = eyescan_options.vert_max; y >= eyescan_options.vert_min; y = y - eyescan_options.vstep) { 171 ESTM_PRINTF(("%6dmV : ", _ladder_setting_to_mV(y, rd_p1_thresh_sel()))); 172 for (z = -31; z < eyescan_options.horz_min; z++) 173 EFUN_PRINTF((" ")); /* add leading spaces if any */ 174 for (x = eyescan_options.horz_min; x <= eyescan_options.horz_max; x = x + eyescan_options.hstep) { 175 /* val = float8_to_int32(buffer[j); */ 176 val = buffer[j]; 177 178 for (i = 0; i < 13; i++) { 179 if ((val != 0) & ((val >= limits[i]) | (limits[i] == 0))) { 180 for (z = 1; z <= eyescan_options.hstep; z++) { 181 if (z == 1) { 182 if (i <= 8) 183 EFUN_PRINTF(("%c", '1' + i)); 184 else 185 EFUN_PRINTF(("%c", 'A' + i - 9)); 186 } else 187 EFUN_PRINTF((" ")); 188 } 189 break; 190 } 191 } 192 if (i == 13) { 193 for (z = 1; z <= eyescan_options.hstep; z++) { 194 if (z == 1) { 195 if ((x % 5) == 0 && (y % 5) == 0) 196 EFUN_PRINTF(("+")); 197 else if ((x % 5) != 0 && (y % 5) == 0) 198 EFUN_PRINTF(("-")); 199 else if ((x % 5) == 0 && (y % 5) != 0) 200 EFUN_PRINTF((":")); 201 else 202 EFUN_PRINTF((" ")); 203 } else 204 EFUN_PRINTF((" ")); 205 } 206 } 207 j++; 208 } 209 EFUN_PRINTF(("\n")); 210 } 211 EFUN(eagle_tsc_display_eye_scan_footer( pa, 1)); 212 return ERR_CODE_NONE; 213 } 214 215 err_code_t eagle_tsc_meas_eye_scan_start( const phymod_access_t *pa, uint8_t direction){ 216 uint8_t lock; 217 218 ESTM(lock = rd_pmd_rx_lock()); 219 if (lock == 0) { 220 EFUN_PRINTF(("Error: No PMD_RX_LOCK on lane requesting 2D eye scan\n")); 221 return ERR_CODE_DIAG_SCAN_NOT_COMPLETE; 222 } 223 if (direction == EYE_SCAN_VERTICAL) 224 EFUN(eagle_tsc_pmd_uc_diag_cmd( pa, CMD_UC_DIAG_START_VSCAN_EYE, 200)); 225 else 226 EFUN(eagle_tsc_pmd_uc_diag_cmd( pa, CMD_UC_DIAG_START_HSCAN_EYE, 200)); 227 return ERR_CODE_NONE; 228 } 229 230 err_code_t eagle_tsc_read_eye_scan_stripe( const phymod_access_t *pa, uint32_t *buffer, uint16_t *status){ 231 uint32_t val[2] = { 0, 0 }; 232 uint16_t sts = 0; 233 int8_t i; 234 235 if (!buffer || !status) 236 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 237 *status = 0; 238 for (i = 0; i < 32; i++) { 239 { err_code_t err_code = eagle_tsc_poll_diag_eye_data(pa,&val[0], &sts, 200); 240 *status |= sts & 0xF000; 241 if (err_code) 242 return err_code; } 243 buffer[i * 2] = val[0]; 244 buffer[(i * 2) + 1] = val[1]; 245 } 246 *status |= sts & 0x00FF; 247 return ERR_CODE_NONE; 248 } 249 250 err_code_t eagle_tsc_display_eye_scan_stripe( const phymod_access_t *pa, int8_t y, uint32_t *buffer){ 251 252 const uint32_t limits[7] = { 917504, 91750, 9175, 917, 91, 9, 1 }; 253 254 int8_t x, i; 255 int8_t data_thresh; 256 int16_t level; 257 258 ESTM(data_thresh = rd_p1_thresh_sel()); 259 level = _ladder_setting_to_mV(y, data_thresh); 260 261 if (!buffer) 262 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 263 264 EFUN_PRINTF(("%6dmV : ", level)); 265 266 for (x = -31; x < 32; x++) { 267 for (i = 0; i < 7; i++) 268 if (buffer[x + 31] >= limits[i]) { 269 EFUN_PRINTF(("%c", '0' + i + 1)); 270 break; 271 } 272 if (i == 7) { 273 if ((x % 5) == 0 && (y % 5) == 0) EFUN_PRINTF(("+")); else if ((x % 5) != 0 && (y % 5) == 0) EFUN_PRINTF(("-")); else if ((x % 5) == 0 && (y % 5) != 0) EFUN_PRINTF((":")); else EFUN_PRINTF((" ")); 274 } 275 } 276 return ERR_CODE_NONE; 277 } 278 279 /* Measure LOW BER Eye Scan. */ 280 err_code_t eagle_tsc_meas_eye_density_data( const phymod_access_t *pa, const struct eagle_tsc_eyescan_options_st eyescan_options, int32_t *buffer, uint16_t *buffer_size){ 281 int8_t y, x, z; 282 int16_t i; 283 int8_t hzcnt; 284 285 /*uint32_t errcnt; */ 286 /*uint8_t lock_lost; */ 287 288 if (!buffer || !buffer_size) 289 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 290 291 EFUN(eagle_tsc_pmd_uc_diag_cmd( pa, CMD_UC_DIAG_DENSITY, 2000)); 292 i = 0; hzcnt = 0; 293 ESTM_PRINTF(("Calculating %d\n", rd_cnt_d_minus_m1())); 294 for (y = eyescan_options.vert_max; y >= eyescan_options.vert_min; y = y - eyescan_options.vstep) { 295 EFUN(_set_p1_threshold( pa, y)); 296 EFUN(_move_clkp1_offset( pa, eyescan_options.horz_min - 1)); /* Walk back 32 steps */ 297 EFUN(_move_clkp1_offset( pa, 1)); /* Walk forward one (net -31). This sets up the registers for 1 write increments */ 298 hzcnt = eyescan_options.horz_min; 299 for (x = eyescan_options.horz_min; x <= eyescan_options.horz_max; x = x + eyescan_options.hstep) { 300 EFUN(_trnsum_clear_and_enable( pa )); 301 EFUN(eagle_tsc_poll_dsc_state_equals_uc_tune( pa, 2000)); 302 ESTM(buffer[i] = (((int32_t)rd_trnsum_high()) << 10) | rd_trnsum_low()); 303 EFUN_PRINTF(("D %d\n", (uint32_t)buffer[i])); 304 i++; 305 for (z = 1; z <= eyescan_options.hstep; z++) { 306 EFUN(wr_rx_pi_manual_strobe(1)); /* hstep */ 307 hzcnt++; 308 } 309 EFUN_PRINTF((".")); 310 } 311 EFUN(_move_clkp1_offset( pa, -hzcnt)); /* Walk back center */ 312 EFUN_PRINTF(("\n")); 313 } 314 EFUN_PRINTF(("\n")); 315 *buffer_size = i; 316 EFUN(eagle_tsc_meas_eye_scan_done( pa )); 317 318 return ERR_CODE_NONE; 319 } 320 321 err_code_t eagle_tsc_display_eye_density_data( const phymod_access_t *pa, const struct eagle_tsc_eyescan_options_st eyescan_options, int32_t *buffer, uint16_t buffer_size){ 322 int8_t x, y, i, z; 323 int16_t j; /* buffer pointer */ 324 int32_t val; 325 int32_t maxval = 0; 326 uint8_t range; 327 int32_t scaled; 328 int32_t scalen; 329 330 ESTM(range = rd_p1_thresh_sel()); 331 332 if (!buffer) 333 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 334 335 /* Find maxval */ 336 i = 0; 337 for (x = eyescan_options.horz_min; x <= eyescan_options.horz_max; x += eyescan_options.hstep) 338 i++; /* determine row length */ 339 j = buffer_size; /* init to last row */ 340 for ( y = eyescan_options.vert_min; y <= eyescan_options.vert_max; y += eyescan_options.vstep) { 341 for (x = eyescan_options.horz_min; x <= eyescan_options.horz_max; x += eyescan_options.hstep) { 342 if (y == eyescan_options.vert_max) { 343 buffer[i] = 0; /* zero out top row */ 344 i--; /* count number of samples in row */ 345 } else { 346 val = buffer[j] - buffer[j - i]; /* Subtract from above row */ 347 if (val < 0) val = 0; 348 if (val > maxval) maxval = val; 349 buffer[j] = val; 350 j--; 351 } 352 } 353 } 354 EFUN(eagle_tsc_display_eye_scan_header( pa, 1)); 355 /* Normalize peak to 15--avoid overflow while mitigating precision loss */ 356 if (maxval == (((int32_t)0) )) { 357 scalen = 0; scaled = 1; 358 }else if (maxval >= (((int32_t)1) << 27)) { 359 scalen = 1; scaled = maxval / 16; 360 }else { scalen = 16; scaled = maxval; } 361 for (y = eyescan_options.vert_max - 1; y >= eyescan_options.vert_min; y = y - eyescan_options.vstep) { 362 EFUN_PRINTF(("%6dmV : ", (_ladder_setting_to_mV(y, range) + _ladder_setting_to_mV(y + 1, range)) / 2)); 363 for (z = -31; z < eyescan_options.horz_min; ++z) 364 EFUN_PRINTF((" ")); /* add leading spaces if any */ 365 for (x = eyescan_options.horz_min; x <= eyescan_options.horz_max; x = x + eyescan_options.hstep) { 366 val = (buffer[j] * scalen) / scaled; 367 if (val > 15) 368 val = 15; 369 for (z = 1; z <= eyescan_options.hstep; z++) { 370 if (z != 1) EFUN_PRINTF((" ")); else if (val) EFUN_PRINTF(("%X", (uint32_t)val)); else if ((x % 5) == 0 && ((y + 3) % 5) == 0) EFUN_PRINTF(("+")); else if ((x % 5) != 0 && ((y + 3) % 5) == 0) EFUN_PRINTF(("-")); else if ((x % 5) == 0 && ((y + 3) % 5) != 0) EFUN_PRINTF((":")); else EFUN_PRINTF((" ")); 371 } 372 j++; 373 } 374 EFUN_PRINTF(("\n")); 375 } 376 EFUN(eagle_tsc_display_eye_scan_footer( pa, 1)); 377 return ERR_CODE_NONE; 378 } 379 err_code_t eagle_tsc_display_eye_scan_header( const phymod_access_t *pa, int8_t i){ 380 int8_t x; 381 382 EFUN_PRINTF(("\n")); 383 EFUN_PRINTF((" Each character N represents approximate error rate 1e-N at that location\n")); 384 for (x = 1; x <= i; x++) 385 EFUN_PRINTF((" UI/64 : -30 -25 -20 -15 -10 -5 0 5 10 15 20 25 30")); 386 EFUN_PRINTF(("\n")); 387 for (x = 1; x <= i; x++) 388 EFUN_PRINTF((" : -|----|----|----|----|----|----|----|----|----|----|----|----|-")); 389 EFUN_PRINTF(("\n")); 390 return ERR_CODE_NONE; 391 } 392 393 err_code_t eagle_tsc_display_eye_scan_footer( const phymod_access_t *pa, int8_t i){ 394 int8_t x; 395 396 for (x = 1; x <= i; x++) 397 EFUN_PRINTF((" : -|----|----|----|----|----|----|----|----|----|----|----|----|-")); 398 EFUN_PRINTF(("\n")); 399 for (x = 1; x <= i; x++) 400 EFUN_PRINTF((" UI/64 : -30 -25 -20 -15 -10 -5 0 5 10 15 20 25 30")); 401 EFUN_PRINTF(("\n")); 402 return ERR_CODE_NONE; 403 } 404 405 406 /*eye_scan_status_t eagle_tsc_read_eye_scan_status() */ 407 err_code_t eagle_tsc_read_eye_scan_status( const phymod_access_t *pa, uint16_t *status){ 408 409 if (!status) 410 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 411 412 ESTM(*status = rdv_usr_diag_status()); 413 414 return ERR_CODE_NONE; 415 } 416 417 418 err_code_t eagle_tsc_meas_eye_scan_done( const phymod_access_t *pa ){ 419 EFUN(eagle_tsc_pmd_uc_diag_cmd( pa, CMD_UC_DIAG_DISABLE, 200)); 420 return ERR_CODE_NONE; 421 } 422 423 424 err_code_t eagle_tsc_start_ber_scan_test( const phymod_access_t *pa, uint8_t ber_scan_mode, uint8_t timer_control, uint8_t max_error_control){ 425 uint8_t lock, sts; 426 427 ESTM(lock = rd_pmd_rx_lock()); 428 if (lock == 0) { 429 EFUN_PRINTF(("Error: No PMD_RX_LOCK on lane requesting BER scan\n")); 430 return ERR_CODE_DIAG_SCAN_NOT_COMPLETE; 431 } 432 ESTM(sts = rdv_usr_sts_micro_stopped()); 433 if (sts > 1) { 434 EFUN_PRINTF(("Error: Lane is busy (%d) requesting BER scan\n", sts)); 435 return ERR_CODE_DIAG_SCAN_NOT_COMPLETE; 436 } 437 438 EFUN(wrcv_diag_max_time_control(timer_control)); 439 EFUN(wrcv_diag_max_err_control(max_error_control)); 440 EFUN(eagle_tsc_pmd_uc_cmd( pa, CMD_CAPTURE_BER_START, ber_scan_mode, 500)); 441 return ERR_CODE_NONE; 442 } 443 444 err_code_t eagle_tsc_read_ber_scan_data( const phymod_access_t *pa, uint32_t *errors, uint32_t *timer_values, uint8_t *cnt, uint32_t timeout){ 445 uint8_t i, prbs_byte, prbs_multi, time_byte, time_multi; 446 uint16_t sts, dataword; 447 448 if (!errors || !timer_values || !cnt) 449 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 450 /* init data arrays */ 451 for (i = 0; i < DIAG_MAX_SAMPLES; i++) { 452 errors[i] = 0; 453 timer_values[i] = 0; 454 } 455 /* Check for completion read ln.diag_status byte?*/ 456 ESTM(sts = rdv_usr_diag_status()); 457 if ((sts & 0x8000) == 0) 458 return _error(ERR_CODE_DATA_NOTAVAIL); 459 *cnt = (sts & 0x00FF) / 3; 460 for (i = 0; i < *cnt; i++) { 461 /* Read 2 bytes of data */ 462 EFUN(eagle_tsc_pmd_uc_cmd( pa, CMD_READ_DIAG_DATA_WORD, 0, timeout)); 463 ESTM(dataword = rd_uc_dsc_data()); /* LSB contains 2 -4bit nibbles */ 464 time_byte = (uint8_t)(dataword >> 8); /* MSB is time byte */ 465 prbs_multi = (uint8_t)dataword & 0x0F; /* split nibbles */ 466 time_multi = (uint8_t)dataword >> 4; 467 /* Read 1 bytes of data */ 468 EFUN(eagle_tsc_pmd_uc_cmd( pa, CMD_READ_DIAG_DATA_BYTE, 0, timeout)); 469 ESTM(prbs_byte = (uint8_t)rd_uc_dsc_data()); 470 errors[i] = _float12_to_uint32( pa, prbs_byte, prbs_multi); /* convert 12bits to uint32 */ 471 timer_values[i] = (_float12_to_uint32( pa, time_byte, time_multi) << 3); 472 /* EFUN_PRINTF(("Err=%d (%02x<<%d); Time=%d (%02x<<%d)\n",errors[i],prbs_byte,prbs_multi,timer_values[i],time_byte,time_multi<<3)); */ 473 /*if(timer_values[i] == 0 && errors[i] == 0) break;*/ 474 } 475 476 return ERR_CODE_NONE; 477 } 478 479 480 /* This is good example function to do BER extrapolation */ 481 err_code_t eagle_tsc_eye_margin_proj( const phymod_access_t *pa, USR_DOUBLE rate, uint8_t ber_scan_mode, uint8_t timer_control, uint8_t max_error_control){ 482 uint32_t errs[DIAG_MAX_SAMPLES]; 483 uint32_t time[DIAG_MAX_SAMPLES]; 484 uint8_t i, cnt; 485 uint16_t sts; 486 int16_t offset_start; 487 /* Below 'verbose' level is intended to be modified only within a debug */ 488 /* session immediately after a breakpoint, and to retain its state only */ 489 /* through function exit: therefore it must be 'volatile' to prevent a */ 490 /* compiler from eliding code conditioned on it, but NOT 'static'. */ 491 uint8_t volatile verbose = 0; 492 493 494 for (i = 0; i < DIAG_MAX_SAMPLES; i++) { 495 errs[i] = 0; 496 time[i] = 0; 497 } 498 /* start UC acquisition */ 499 if (verbose > 2) EFUN_PRINTF(("start begin\n")); 500 EFUN(eagle_tsc_start_ber_scan_test( pa, ber_scan_mode, timer_control, max_error_control)); 501 ESTM(offset_start = rd_uc_dsc_data()); 502 if (verbose > 2) EFUN_PRINTF(("offset_start = %d:%dmV\n", offset_start, _ladder_setting_to_mV((int8_t)offset_start, 0))); 503 if (verbose > 2) EFUN_PRINTF(("start done\n")); 504 505 /* This wait is VERY LONG and should be replaced with interupt or something */ 506 if (verbose > 5) { 507 do { 508 EFUN(eagle_tsc_delay_us(2000000)); 509 ESTM(sts = rdv_usr_diag_status()); 510 EFUN_PRINTF(("sts=%04x\n", sts)); 511 512 } while ((sts & 0x8000) == 0); 513 } else { 514 EFUN_PRINTF(("Waiting for measurement time approx %d seconds", timer_control + (timer_control >> 1))); 515 EFUN(eagle_tsc_poll_diag_done( pa, &sts, timer_control * 2000)); 516 } 517 if (verbose > 2) EFUN_PRINTF(("delay done\n")); 518 519 EFUN(eagle_tsc_read_ber_scan_data( pa, &errs[0], &time[0], &cnt, 2000)); 520 521 if (verbose > 2) EFUN_PRINTF(("read done cnt=%d\n", cnt)); 522 523 EFUN(eagle_tsc_pmd_uc_cmd( pa, CMD_CAPTURE_BER_END, 0x00, 50)); 524 525 if (verbose > 2) EFUN_PRINTF(("end function done\n")); 526 /* if(cnt == 1) { */ 527 /* EFUN_PRINTF(("Not enough points found to extrapolate BER\n")); */ 528 /* return(ERR_CODE_NONE); */ 529 /* } */ 530 531 EFUN(eagle_tsc_display_ber_scan_data(pa, rate, ber_scan_mode, &errs[0], &time[0], (uint8_t)_abs(offset_start))); 532 533 if (verbose > 2) EFUN_PRINTF(("display done\n")); 534 535 return ERR_CODE_NONE; 536 } 537 538 539 540 err_code_t eagle_tsc_display_ber_scan_data(const phymod_access_t *pa, USR_DOUBLE rate, uint8_t ber_scan_mode, uint32_t *total_errs, uint32_t *total_time, uint8_t max_offset){ 541 542 #ifdef SERDES_API_FLOATING_POINT 543 /* 'margins_mv[]' vector maps the p1 threshold code with actual mV 544 Only relevant when mode=0 545 This is not totally linear: for code 0~25 step=6mV; code 25~30 step=18mV; code 30~31 step=12 546 'margins_mv[]' is valid only for Merlin. This vector would need to be modified accordingly for different Serdes 547 USR_DOUBLE margins_mv[] = {0,6,12,18,24,30,36,42,48,54,60,66,72,78,84, 548 90,96,102,108,114,120,126,132,138,144,150,168,186,204,222,240,252}; 549 const USR_DOUBLE narrow_margins_mv[] = {0,3.6,7.2,10.8,14.4,18,21.6,25.5,28.8,32.4,36,39.6,43.2,46.8,50.4, 550 54,57.6,61.2,64.8,68.4,72,75.6,79.2,82.8,86.4,90,100.8,111.6,122.4,133.2,144,151.2}; */ 551 #ifndef STANDALONE_EVENT 552 const USR_DOUBLE intrusive_margins_mv[] = { 2, 6, 10, 14, 18, 22, 26, 30, 32, 36, 40, 44, 48, 52, 56, 60 }; 553 #endif 554 const unsigned int HI_CONFIDENCE_ERR_CNT = 100; /* bit errors */ 555 const unsigned int HI_CONFIDENCE_MIN_ERR_CNT = 20; /* bit errors */ 556 const unsigned int MAX_CLIPPED_ERR_CNT = 8355840; 557 const USR_DOUBLE ARTIFICIAL_BER = 0.5; /* used along ARTIFICIAL_MARGIN(_V/_H) when not enough points to extrapolate */ 558 const int ARTIFICIAL_MARGIN_V = 500; /* Used along ARTIFICIAL_BER when not enough points to extrapolate. Unit: mV. Based on the concept of max Vpp of 1 Volt */ 559 const int ARTIFICIAL_MARGIN_H = 1; /* Used along ARTIFICIAL_BER when not enough points to extrapolate. Unit: UI. Based on the concept of two consecutive scrambled bits (1 UI appart) being uncorrelated */ 560 const int MIN_BER_TO_REPORT = -24; /* we clip the projected BER using this number */ 561 const USR_DOUBLE MIN_BER_FOR_FIT = -8.0; /* all points with BER <= 10^MIN_BER_FOR_FIT will be used for line fit (i.e used for extrapolation) */ 562 const int8_t verbose = 1; /* set verbosity to 1 for normal API operation */ 563 564 /* BER confidence scale */ 565 const USR_DOUBLE ber_conf_scale[104] = { 566 2.9957, 5.5717, 3.6123, 2.9224, 2.5604, 2.3337, 2.1765, 2.0604, 1.9704, 1.8983, 567 1.8391, 1.7893, 1.7468, 1.7100, 1.6778, 1.6494, 1.6239, 1.6011, 1.5804, 1.5616, 568 1.5444, 1.5286, 1.5140, 1.5005, 1.4879, 1.4762, 1.4652, 1.4550, 1.4453, 1.4362, 569 1.4276, 1.4194, 1.4117, 1.4044, 1.3974, 1.3908, 1.3844, 1.3784, 1.3726, 1.3670, 570 1.3617, 1.3566, 1.3517, 1.3470, 1.3425, 1.3381, 1.3339, 1.3298, 1.3259, 1.3221, 571 1.3184, 1.3148, 1.3114, 1.3080, 1.3048, 1.3016, 1.2986, 1.2956, 1.2927, 1.2899, 572 1.2872, 1.2845, 1.2820, 1.2794, 1.2770, 1.2746, 1.2722, 1.2700, 1.2677, 1.2656, 573 1.2634, 1.2614, 1.2593, 1.2573, 1.2554, 1.2535, 1.2516, 1.2498, 1.2481, 1.2463, 574 1.2446, 1.2429, 1.2413, 1.2397, 1.2381, 1.2365, 1.2350, 1.2335, 1.2320, 1.2306, 575 1.2292, 1.2278, 1.2264, 1.2251, 1.2238, 1.2225, 1.2212, 1.2199, 1.2187, 1.2175, 576 1.2163, /* starts in index: 100 for #errors: 100,200,300,400 */ 577 1.1486, /* 200 */ 578 1.1198, /* 300 */ 579 1.1030 580 }; /*400 */ 581 582 583 /* Define variables */ 584 USR_DOUBLE lbers[DIAG_MAX_SAMPLES]; /* Internal linear scale sqrt(-log(ber)) */ 585 USR_DOUBLE margins[DIAG_MAX_SAMPLES]; /* Eye margin @ each measurement */ 586 USR_DOUBLE bers[DIAG_MAX_SAMPLES]; /* computed bit error rate */ 587 uint32_t i; 588 int8_t offset[DIAG_MAX_SAMPLES]; 589 int8_t mono_flags[DIAG_MAX_SAMPLES]; 590 591 int8_t direction; 592 uint8_t heye; 593 int8_t delta_n; 594 USR_DOUBLE Exy = 0.0; 595 USR_DOUBLE Eyy = 0.0; 596 USR_DOUBLE Exx = 0.0; 597 USR_DOUBLE Ey = 0.0; 598 USR_DOUBLE Ex = 0.0; 599 USR_DOUBLE alpha = 0.0; 600 USR_DOUBLE gauss_noise = -1; 601 USR_DOUBLE beta = 0.0; 602 USR_DOUBLE sq_r = 0.0, alpha2 = 0.0; 603 USR_DOUBLE proj_ber = 0.0, proj_ber_aux = 0.0; 604 USR_DOUBLE proj_margin_12 = 0.0; 605 USR_DOUBLE proj_margin_15 = 0.0; 606 USR_DOUBLE proj_margin_18 = 0.0; 607 USR_DOUBLE sq_err1 = 0.0, sq_err2 = 0.0; 608 USR_DOUBLE ierr; 609 uint8_t start_n; 610 uint8_t stop_n; 611 uint8_t low_confidence; 612 uint8_t loop_index; 613 uint8_t n_mono = 0; 614 uint8_t eye_cnt = 1; 615 uint8_t hi_confidence_cnt = 0; 616 int8_t first_good_ber_idx = -1; 617 int8_t first_small_errcnt_idx = -1; 618 int8_t first_non_clipped_errcnt_idx = -1; 619 uint8_t range250; 620 uint8_t intrusive; 621 uint8_t ber_clipped = 0; 622 uint8_t last_point_discard; 623 uint8_t fit_count; 624 int artificial_margin; 625 int proj_case = 0; /* this variable will be used to signal what particular extrapolation case has happened at the end (after discarding invalid points of all sorts). To avoid potential issues: NEVER RE-USE VALUES... new cases should receive brand-new integer value */ 626 USR_DOUBLE artificial_lber; 627 char message[256] = "NO MESSAGE"; 628 char unit[5]; 629 630 if (!total_errs || !total_time ) 631 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 632 633 /* Initialize BER array */ 634 for (i = 0; i < DIAG_MAX_SAMPLES; i++) { 635 bers[i] = 0; 636 mono_flags[i] = 0; 637 } 638 639 /* Decode mode/direction/etc. */ 640 heye = (ber_scan_mode & DIAG_BER_HORZ) >> 1; 641 direction = (ber_scan_mode & DIAG_BER_NEG) ? -1 : 1; 642 range250 = (ber_scan_mode & DIAG_BER_P1_NARROW) ? 0 : 1; 643 intrusive = (ber_scan_mode & DIAG_BER_INTR) ? 1 : 0; 644 645 /* Prepare artificial points in case they are needed */ 646 if (heye == 1) 647 artificial_margin = direction * ARTIFICIAL_MARGIN_H; 648 else 649 artificial_margin = direction * ARTIFICIAL_MARGIN_V; 650 artificial_lber = (USR_DOUBLE)sqrt(-log10(ARTIFICIAL_BER)); 651 652 /* Printing on-screen message */ 653 if (heye == 1) { 654 if (verbose > 0) { 655 if (direction == -1) EFUN_PRINTF(("\n\n********** HORIZONTAL PROJECTION: LEFT SIDE ******************\n")); 656 if (direction == 1) EFUN_PRINTF(("\n\n********** HORIZONTAL PROJECTION: RIGHT SIDE *****************\n")); 657 } 658 } else { 659 if (verbose > 0) { 660 if (direction == -1) EFUN_PRINTF(("\n\n********** VERTICAL PROJECTION: BOTTOM ***********************\n")); 661 if (direction == 1) EFUN_PRINTF(("\n\n********** VERTICAL PROJECTION: TOP **************************\n")); 662 } 663 } 664 665 /* ******************************************* 666 * Generate margins[] 667 * Generate ber[] 668 * Find first and last points for linear fit 669 */ 670 i = 0; 671 do { 672 if (heye == 1) { 673 ENULL_STRCPY(unit, "mUI"); 674 offset[i] = (int8_t)(max_offset - i); 675 #ifndef STANDALONE_EVENT 676 margins[i] = direction * offset[i] * 1000.0 / 64.0; 677 #else 678 margins[i] = info_out->margins[i]; 679 #endif 680 } else { 681 ENULL_STRCPY(unit, "mV"); 682 offset[i] = (int8_t)(max_offset - i); 683 #ifndef STANDALONE_EVENT 684 if (intrusive) 685 margins[i] = direction * intrusive_margins_mv[offset[i]]; 686 else 687 margins[i] = direction * _ladder_setting_to_mV(offset[i], range250); 688 689 #else 690 margins[i] = info_out->margins[i]; 691 #endif 692 } 693 if (total_errs[i] == 0) 694 bers[i] = 1.0 / (((USR_DOUBLE)total_time[i]) * 0.00001 * rate); 695 else 696 bers[i] = (USR_DOUBLE)total_errs[i] / (((USR_DOUBLE)total_time[i]) * 0.00001 * rate); 697 698 /* Find the first data point with good BER (BER <= 10^MIN_BER_FOR_FIT) 699 NOTE: no need for lower bound on BER, since correction factors will be applied for all total_errs>=0 */ 700 if ((log10(bers[i]) <= MIN_BER_FOR_FIT) && (first_good_ber_idx == -1)) 701 first_good_ber_idx = (int8_t)i; 702 703 /* Determine high-confidence iterations */ 704 if (total_errs[i] >= HI_CONFIDENCE_ERR_CNT) 705 hi_confidence_cnt++; 706 else if ((total_errs[i] < HI_CONFIDENCE_MIN_ERR_CNT) && (first_small_errcnt_idx == -1)) 707 /* find the first data point with small error count */ 708 first_small_errcnt_idx = (int8_t)i; 709 710 /* Determine first NON-clipped error count 711 NOTE: Originally this limit was created for post processing of micro-generated data; however, this could be used for PC-generated data as well */ 712 if ((total_errs[i] < MAX_CLIPPED_ERR_CNT) && (first_non_clipped_errcnt_idx == -1) ) 713 first_non_clipped_errcnt_idx = (int8_t)i; 714 715 i++; 716 717 } while (((total_errs[i] != 0) || (total_time[i] != 0)) && (i <= max_offset)); 718 719 eye_cnt = (int8_t)i; 720 721 722 /* ******************************************* 723 Setting up stop_n variable. 724 Check if: 725 - There is only one point in measurement vector (i.e. eye_cnt = 1) 726 - The very last point's measurement time was "too short" 727 */ 728 729 i = eye_cnt - 1; 730 if (i >= 1) { 731 if ((total_time[i] >= 0.5 * total_time[i - 1]) || (total_errs[i] >= HI_CONFIDENCE_MIN_ERR_CNT) ) { 732 stop_n = eye_cnt; /* last point will be included in linear fit */ 733 last_point_discard = 0; 734 } else { 735 stop_n = eye_cnt - 1; /* discards the very last point */ 736 last_point_discard = 1; 737 } 738 } else 739 stop_n = 1; /* there is ONLY one measurement */ 740 741 742 /* ******************************************* 743 Print on screen (prints RAW BER data. i.e. conf factors) 744 */ 745 if (verbose > 0) { 746 i = 0; 747 do { 748 if (total_errs[i] == 0) 749 EFUN_PRINTF(("BER @ %4.0f %s < 1e%6.2f (%u errors in %0.2f sec)\n", margins[i], unit, log10(bers[i]), total_errs[i], ((USR_DOUBLE)total_time[i]) * 0.00001)); 750 else if (total_errs[i] >= MAX_CLIPPED_ERR_CNT) 751 EFUN_PRINTF(("BER @ %4.0f %s > 1e%6.2f (%u errors in %0.2f sec)\n", margins[i], unit, log10(bers[i]), total_errs[i], ((USR_DOUBLE)total_time[i]) * 0.00001)); 752 else 753 EFUN_PRINTF(("BER @ %4.0f %s = 1e%6.2f (%u errors in %0.2f sec)\n", margins[i], unit, log10(bers[i]), total_errs[i], ((USR_DOUBLE)total_time[i]) * 0.00001)); 754 i++; 755 } while (i < stop_n); 756 } 757 758 /* ******************************************* 759 Correcting *all* BER values using confidence factors in 'ber_conf_scale' vector 760 This step is done for extrapolation purposes 761 */ 762 for (loop_index = 0; loop_index < eye_cnt; loop_index++) { 763 if (total_errs[loop_index] <= 100) 764 bers[loop_index] = ber_conf_scale[total_errs[loop_index]] * bers[loop_index]; 765 else if (total_errs[loop_index] > 100 && total_errs[loop_index] < 200) 766 bers[loop_index] = ber_conf_scale[100] * bers[loop_index]; 767 else if (total_errs[loop_index] >= 200 && total_errs[loop_index] < 300) 768 bers[loop_index] = ber_conf_scale[101] * bers[loop_index]; 769 else if (total_errs[loop_index] >= 300 && total_errs[loop_index] < 400) 770 bers[loop_index] = ber_conf_scale[102] * bers[loop_index]; 771 else if (total_errs[loop_index] >= 400) 772 bers[loop_index] = ber_conf_scale[103] * bers[loop_index]; 773 } 774 775 /* ******************************************* 776 Computes the "linearised" ber vector 777 */ 778 for (loop_index = 0; loop_index < eye_cnt; loop_index++) 779 lbers[loop_index] = (USR_DOUBLE)sqrt(-log10(bers[loop_index])); 780 781 /* ******************************************* 782 Assign highest data point to use 783 */ 784 if (first_good_ber_idx == -1) 785 start_n = stop_n; 786 else 787 start_n = first_good_ber_idx; 788 789 790 791 /* ****************************************************** 792 *********** EXTRAPOLATION (START) ********************** 793 ********************************************************* 794 Different data set profiles can be received by this code. 795 Each case is processed accordingly here (IF-ELSE IF cases) 796 */ 797 798 /* ====> Errors encountered all the way to sampling point */ 799 if (start_n >= eye_cnt) { 800 proj_case = 1; 801 ENULL_STRCPY(message, "No low-BER point measured"); 802 803 /* confidence factor of 0.96 is applied in this case to set a LOWER bound and report accordingly. 804 This factor corresponds to approximately 3000 errors @95% confidence 805 For reference: factors for 900, 2000, 3000, 5000, 20000 and 50000 errors are: 0.96, 0.96, 0.97, 0.99, 0.99, respectively */ 806 proj_ber = 0.96 * log10(bers[eye_cnt - 1]); 807 proj_ber_aux = proj_ber; 808 EFUN_PRINTF(("BER *worse* than 1e%0.2f\n", proj_ber)); 809 EFUN_PRINTF(("No margin @ 1e-12, 1e-15 & 1e-18\n\n\n")); 810 fit_count = 1; 811 }else { 812 813 /* ====> Only ONE measured point. Typically when the eye is wide open. 814 Artificial points will be used to make extrapolation possible */ 815 if (stop_n == 1) { 816 proj_case = 2; 817 ENULL_STRCPY(message, "Not enough points (single measured point). Using artificial point"); 818 819 low_confidence = 1; 820 delta_n = 1; /* 'delta_n' and 'fit_count' variables were kept for future use in case a new approach to handle low confidence case is adopted */ 821 fit_count = 2; 822 823 /* Compute covariances and means... but only for two points: artificial and the single measured point */ 824 Exy = ((margins[0] * lbers[0] + artificial_margin * artificial_lber) / 2.0); 825 Eyy = ((lbers[0] * lbers[0] + artificial_lber * artificial_lber) / 2.0); 826 Exx = ((margins[0] * margins[0] + artificial_margin * artificial_margin) / 2.0); 827 Ey = ((lbers[0] + artificial_lber) / 2.0); 828 Ex = ((margins[0] + artificial_margin) / 2.0); 829 } 830 /* ====> "NORMAL" case (when there are more than 1 measurements) */ 831 else { 832 833 /* Detect and record nonmonotonic data points */ 834 for (loop_index = 0; loop_index < stop_n; loop_index++) { 835 if ((loop_index > start_n) && (log10(bers[loop_index]) > log10(bers[loop_index - 1]))) { 836 mono_flags[loop_index] = 1; 837 if (first_good_ber_idx != -1) 838 n_mono++; 839 } 840 } 841 842 /* Finds number of MEASURED points available for extrapolation */ 843 delta_n = (stop_n - start_n - n_mono); 844 845 846 /* HIGH CONFIDENCE case */ 847 848 if (delta_n >= 2) { /* there are at least 2 points to trace a line */ 849 proj_case = 3; 850 ENULL_STRCPY(message, "Normal case"); 851 low_confidence = 0; 852 853 /* Compute covariances and means */ 854 fit_count = 0; 855 for (loop_index = start_n; loop_index < stop_n; loop_index++) { 856 if (mono_flags[loop_index] == 0) { 857 Exy += (margins[loop_index] * lbers[loop_index] / (USR_DOUBLE)delta_n); 858 Eyy += (lbers[loop_index] * lbers[loop_index] / (USR_DOUBLE)delta_n); 859 Exx += (margins[loop_index] * margins[loop_index] / (USR_DOUBLE)delta_n); 860 Ey += (lbers[loop_index] / (USR_DOUBLE)delta_n); 861 Ex += (margins[loop_index] / (USR_DOUBLE)delta_n); 862 fit_count++; 863 } 864 } 865 } 866 /* LOW CONFIDENCE case */ 867 else { /* NEW APPROACH (08/28/2014): consider very first point (error count < MAX_CLIPPED_ERR_CNT) and very last point for linear fit. This will give pessimistic/conservative extrapolation */ 868 low_confidence = 1; 869 if ( (first_non_clipped_errcnt_idx >= 0) && (first_non_clipped_errcnt_idx < start_n)) { 870 proj_case = 4; 871 ENULL_STRCPY(message, "Not enough points. Using first measured point for conservative estimation"); 872 fit_count = 2; 873 /* Compute covariances and means... but only for two points: first and last */ 874 Exy = ((margins[stop_n - 1] * lbers[stop_n - 1] + margins[first_non_clipped_errcnt_idx] * lbers[first_non_clipped_errcnt_idx]) / 2.0); 875 Eyy = ((lbers[stop_n - 1] * lbers[stop_n - 1] + lbers[first_non_clipped_errcnt_idx] * lbers[first_non_clipped_errcnt_idx]) / 2.0); 876 Exx = ((margins[stop_n - 1] * margins[stop_n - 1] + margins[first_non_clipped_errcnt_idx] * margins[first_non_clipped_errcnt_idx]) / 2.0); 877 Ey = ((lbers[stop_n - 1] + lbers[first_non_clipped_errcnt_idx]) / 2.0); 878 Ex = ((margins[stop_n - 1] + margins[first_non_clipped_errcnt_idx]) / 2.0); 879 } else { 880 proj_case = 5; 881 ENULL_STRCPY(message, "Not enough points (cannot use non-clipped ErrorCount point). Using artificial point"); 882 /* Compute covariances and means... but only for two points: artificial and the single measured point */ 883 Exy = (artificial_margin * artificial_lber) / 2.0; 884 Eyy = (artificial_lber * artificial_lber) / 2.0; 885 Exx = (artificial_margin * artificial_margin) / 2.0; 886 Ey = (artificial_lber) / 2.0; 887 Ex = (artificial_margin) / 2.0; 888 fit_count = 1; 889 /* This FOR loop checks for monotonicity as well */ 890 for (loop_index = start_n; loop_index < stop_n; loop_index++) { 891 if (mono_flags[loop_index] == 0) { 892 Exy += (margins[loop_index] * lbers[loop_index] / 2.0); 893 Eyy += (lbers[loop_index] * lbers[loop_index] / 2.0); 894 Exx += (margins[loop_index] * margins[loop_index] / 2.0); 895 Ey += (lbers[loop_index] / 2.0); 896 Ex += (margins[loop_index] / 2.0); 897 fit_count++; 898 } 899 } 900 } 901 } 902 } 903 904 /* Compute fit slope and offset: ber = alpha*margin + beta */ 905 alpha = (Exy - Ey * Ex) / (Exx - Ex * Ex); 906 beta = Ey - Ex * alpha; 907 /* Compute alpha2: slope of regression: margin = alpha2*ber + beta2 */ 908 alpha2 = (Exy - Ey * Ex) / (Eyy - Ey * Ey); 909 /* Compute correlation index sq_r */ 910 sq_r = alpha * alpha2; 911 912 proj_ber = pow(10, (-beta * beta)); 913 proj_margin_12 = direction * (sqrt(-log10(1e-12)) - beta) / alpha; 914 proj_margin_15 = direction * (sqrt(-log10(1e-15)) - beta) / alpha; 915 proj_margin_18 = direction * (sqrt(-log10(1e-18)) - beta) / alpha; 916 917 /* Estimate modeled gaussian noise. 918 919 The following is based on the Q-function model and the following table: 920 Q | log10(BER) 921 ======================= 922 7.033 | -12 923 7.941 | -15 924 8.757 | -18 925 926 Based on the above, we solve for sigma: 927 7.033*sigma = u - proj_margin_12 , and 928 7.941*sigma = u - proj_margin_15 929 */ 930 gauss_noise = (proj_margin_12 - proj_margin_15) / 0.908; 931 932 sq_err1 = (Eyy + (beta * beta) + (Exx * alpha * alpha) - 933 (2 * Ey * beta) - (2 * Exy * alpha) + (2 * Ex * beta * alpha)); 934 sq_err2 = 0; 935 for (loop_index = start_n; loop_index < stop_n; loop_index++) { 936 ierr = (lbers[loop_index] - (alpha * margins[loop_index] + beta)); 937 sq_err2 += (ierr * ierr / (USR_DOUBLE)delta_n); 938 } 939 940 proj_ber = log10(proj_ber); 941 proj_ber_aux = proj_ber; 942 943 if (proj_ber < MIN_BER_TO_REPORT) { 944 proj_ber = MIN_BER_TO_REPORT; 945 ber_clipped = 1; 946 } 947 948 /* Extrapolated results, low confidence */ 949 if (low_confidence == 1) { 950 951 EFUN_PRINTF(("BER(extrapolated) < 1e%0.2f\n", proj_ber)); 952 EFUN_PRINTF(("Margin @ 1e-12 > %0.2f %s\n", (proj_ber < -12) ? _abs(proj_margin_12) : 0, unit)); 953 EFUN_PRINTF(("Margin @ 1e-15 > %0.2f %s\n", (proj_ber < -15) ? _abs(proj_margin_15) : 0, unit)); 954 EFUN_PRINTF(("Margin @ 1e-18 > %0.2f %s\n", (proj_ber < -18) ? _abs(proj_margin_18) : 0, unit)); 955 956 /* Extrapolated results, HIGH confidence */ 957 } else { 958 959 if (ber_clipped == 1) 960 EFUN_PRINTF(("BER(extrapolated) < 1e%0.2f\n", proj_ber)); 961 else 962 EFUN_PRINTF(("BER(extrapolated) = 1e%0.2f\n", proj_ber)); 963 EFUN_PRINTF(("Margin @ 1e-12 = %0.2f %s\n", (proj_ber < -12) ? _abs(proj_margin_12) : 0, unit)); 964 EFUN_PRINTF(("Margin @ 1e-15 = %0.2f %s\n", (proj_ber < -15) ? _abs(proj_margin_15) : 0, unit)); 965 EFUN_PRINTF(("Margin @ 1e-18 = %0.2f %s\n", (proj_ber < -18) ? _abs(proj_margin_18) : 0, unit)); 966 } 967 968 EFUN_PRINTF(("\n\n")); 969 970 /* Print non-monotonic outliers */ 971 if (n_mono != 0) { 972 EFUN_PRINTF(("Detected non-monotonicity at { ")); 973 for (loop_index = start_n; loop_index < stop_n; loop_index++) 974 if (mono_flags[loop_index] == 1) 975 EFUN_PRINTF(("%0.2f ", margins[loop_index])); 976 EFUN_PRINTF(("} %s\n\n\n", unit)); 977 } 978 979 } 980 /* ******************************************* 981 *********** EXTRAPOLATION (END) ************* 982 */ 983 984 985 986 /* SUMMARY (for debugging purposes */ 987 if (verbose > 2) EFUN_PRINTF(("\t=====> DEBUG INFO (start)\n\n")); 988 if (verbose > 2) { 989 EFUN_PRINTF((" loop Margin total_errors time(sec) logBER lber")); 990 for (loop_index = 0; loop_index < stop_n + last_point_discard; loop_index++) 991 EFUN_PRINTF(("\n%5d %11.0f %14d %10.3f %8.2f %10.3f", loop_index, margins[loop_index], total_errs[loop_index], ((USR_DOUBLE)total_time[loop_index]) * 0.00001, log10(bers[loop_index]), lbers[loop_index])); 992 EFUN_PRINTF(("\n\n")); 993 } 994 if (verbose > 2) EFUN_PRINTF(("Max Offset = %d\n", max_offset)); 995 if (verbose > 2) EFUN_PRINTF(("ber_clipped: %d, Projected BER (proj_ber_aux) = %.2f\n", ber_clipped, proj_ber_aux)); 996 if (verbose > 2) EFUN_PRINTF(("first good ber idx at %d, ber = 1e%f\n", first_good_ber_idx, ((first_good_ber_idx >= 0) ? log10(bers[first_good_ber_idx]) : 0.0))); 997 if (verbose > 2) EFUN_PRINTF(("first small errcnt idx at %d, errors = %d\n", first_small_errcnt_idx, ((first_small_errcnt_idx >= 0) ? total_errs[first_small_errcnt_idx] : -1))); 998 if (verbose > 2) EFUN_PRINTF(("last point discarded?: %d, low_confidence: %d, first_non_clipped_errcnt_idx: %d, start_n: %d, stop_n: %d, eye_cnt: %d, n_mono: %d, first_good_ber_idx = %d, first_small_errcnt_idx = %d, fit_count: %d, delta_n: %d\n", 999 last_point_discard, low_confidence, first_non_clipped_errcnt_idx, start_n, stop_n, eye_cnt, n_mono, first_good_ber_idx, first_small_errcnt_idx, fit_count, delta_n)); 1000 if (verbose > 2) EFUN_PRINTF(("Exy=%.2f, Eyy=%.4f, Exx=%.2f, Ey=%.4f, Ex=%.2f, alpha=%.4f, beta=%.4f, alpha2=%.3f, sq_r=%.3f, sq_err1=%g, sq_err2=%g, gauss_noise=%.3f\n", Exy, Eyy, Exx, Ey, Ex, alpha, beta, alpha2, sq_r, sq_err1, sq_err2, gauss_noise)); 1001 if (verbose > 2) EFUN_PRINTF(("%s\n", message)); 1002 if (verbose > 2) EFUN_PRINTF(("proj_case %d\n", proj_case)); 1003 if (verbose > 2) EFUN_PRINTF(("\n\t=====> DEBUG INFO (end)\n\n")); 1004 EFUN_PRINTF(("\n\n\n")); 1005 1006 1007 1008 #else 1009 (void)rate; 1010 (void)ber_scan_mode; 1011 (void)max_offset; 1012 1013 EFUN_PRINTF(("This function needs SERDES_API_FLOATING_POINT define to operate \n")); 1014 1015 if (!total_errs || !total_time ) 1016 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1017 1018 #endif 1019 return ERR_CODE_NONE; 1020 1021 } 1022 1023 1024 1025 1026 /*****************************/ 1027 /* Display Lane/Core State */ 1028 /*****************************/ 1029 1030 err_code_t eagle_tsc_display_lane_state_hdr( const phymod_access_t *pa ){ 1031 EFUN_PRINTF(("LN (CDRxN , UC_CFG,RST,STP) ")); 1032 EFUN_PRINTF(("SD LCK RXPPM ")); 1033 EFUN_PRINTF(("CLK90 CLKP1 ")); 1034 EFUN_PRINTF(("PF(M,L) ")); 1035 EFUN_PRINTF(("VGA DCO ")); 1036 EFUN_PRINTF(("P1mV ")); 1037 EFUN_PRINTF((" DFE(1,2,3,4,5,dcd1,dcd2) SLICER(ze,zo,pe,po,me,mo) ")); 1038 EFUN_PRINTF(("TXPPM ")); 1039 EFUN_PRINTF(("TXEQ(n1,m,p1,2,3) ")); 1040 EFUN_PRINTF(("TXAMP ")); 1041 EFUN_PRINTF((" EYE(L,R,U,D) ")); 1042 EFUN_PRINTF(("LINK_TIME")); 1043 EFUN_PRINTF(("\n")); 1044 return ERR_CODE_NONE; 1045 } 1046 1047 err_code_t eagle_tsc_display_lane_state_legend( const phymod_access_t *pa ){ 1048 EFUN_PRINTF(("\n")); 1049 EFUN_PRINTF(("**********************************************************************************************\n")); 1050 EFUN_PRINTF(("**** Legend of Entries in display_lane_state() ****\n")); 1051 EFUN_PRINTF(("**********************************************************************************************\n")); 1052 EFUN_PRINTF(("LN : lane index within IP core\n")); 1053 EFUN_PRINTF(("CDRxN : CDR type x OSR ratio\n")); 1054 EFUN_PRINTF(("UC_CFG : micro lane configuration variable\n")); 1055 EFUN_PRINTF(("RST : Reset State{reset_active, reset_occured, reset_held}\n")); 1056 EFUN_PRINTF(("STP : uC Stopped State\n")); 1057 EFUN_PRINTF(("SD : signal detect\n")); 1058 EFUN_PRINTF(("LOCK : pmd_rx_lock\n")); 1059 EFUN_PRINTF(("RXPPM : Frequency offset of local reference clock with respect to RX data in ppm\n")); 1060 EFUN_PRINTF(("CLK90 : Delay of zero crossing slicer, m1, wrt to data in PI codes\n")); 1061 EFUN_PRINTF(("CLKP1 : Delay of diagnostic/lms slicer, p1, wrt to data in PI codes\n")); 1062 EFUN_PRINTF(("PF(M,L) : Peaking Filter Main (0..15) and Low Frequency (0..7) settings\n")); 1063 EFUN_PRINTF(("VGA : Variable Gain Amplifier settings (0..42)\n")); 1064 EFUN_PRINTF(("DCO : DC offset DAC control value\n")); 1065 EFUN_PRINTF(("P1mV : Vertical threshold voltage of p1 slicer\n")); 1066 EFUN_PRINTF(("DFE taps : ISI correction taps in units of 2.35mV (for 1 & 2 even values are displayed, dcd = even-odd)\n")); 1067 EFUN_PRINTF(("SLICER(ze,zo,pe,po,me,mo) : Slicer calibration control codes\n")); 1068 EFUN_PRINTF(("TXPPM : Frequency offset of local reference clock with respect to TX data in ppm\n")); 1069 EFUN_PRINTF(("TXEQ(n1,m,p1,p2,p3) : TX equalization FIR tap weights in units of 1Vpp/160 units\n")); 1070 EFUN_PRINTF(("TXAMP : TX amplitude, Drivermode\n")); 1071 EFUN_PRINTF(("EYE(L,R,U,D) : Eye margin @ 1e-5 as seen by internal diagnostic slicer in mUI and mV\n")); 1072 EFUN_PRINTF(("LINK_TIME : Link time in milliseconds\n")); 1073 EFUN_PRINTF(("**********************************************************************************************\n")); 1074 return ERR_CODE_NONE; 1075 } 1076 1077 err_code_t eagle_tsc_display_lane_state( const phymod_access_t *pa ){ 1078 err_code_t err_code = _eagle_tsc_display_lane_state_no_newline( pa ); 1079 1080 EFUN_PRINTF(("\n")); 1081 return err_code; 1082 } 1083 1084 err_code_t eagle_tsc_get_eye_margin_est (const phymod_access_t *pa, int *left_eye_mUI, int *right_eye_mUI, int *upper_eye_mV, int *lower_eye_mV){ 1085 uint8_t ladder_range = 0; 1086 1087 ESTM(ladder_range = rd_p1_thresh_sel()); 1088 ESTM(*left_eye_mUI = _eye_to_mUI (pa, rdv_usr_sts_heye_left())); 1089 ESTM(*right_eye_mUI = _eye_to_mUI (pa, rdv_usr_sts_heye_right())); 1090 ESTM(*upper_eye_mV = _eye_to_mV (pa, rdv_usr_sts_veye_upper(), ladder_range)); 1091 ESTM(*lower_eye_mV = _eye_to_mV (pa, rdv_usr_sts_veye_lower(), ladder_range)); 1092 return ERR_CODE_NONE; 1093 } 1094 1095 1096 err_code_t eagle_tsc_display_core_state_hdr( const phymod_access_t *pa ){ 1097 EFUN_PRINTF(("CORE RST_ST PLL_PWDN UC_ATV COM_CLK UCODE_VER AFE_VER LIVE_TEMP AVG_TMON RESCAL VCO_RATE ANA_VCO_RANGE PLL_DIV PLL_LOCK\n")); 1098 return ERR_CODE_NONE; 1099 } 1100 1101 err_code_t eagle_tsc_display_core_state_line( const phymod_access_t *pa ){ 1102 err_code_t err_code = _eagle_tsc_display_core_state_no_newline( pa ); 1103 1104 EFUN_PRINTF(("\n")); 1105 return err_code; 1106 } 1107 1108 err_code_t eagle_tsc_display_core_state_legend( const phymod_access_t *pa ){ 1109 EFUN_PRINTF(("\n")); 1110 EFUN_PRINTF(("**************************************************************************************************************\n")); 1111 EFUN_PRINTF(("**** Legend of Entries in display_core_state() ****\n")); 1112 EFUN_PRINTF(("**************************************************************************************************************\n")); 1113 EFUN_PRINTF(("* RST_ST : Core DP Reset State{reset_active, reset_occured, reset_held}, Core uC Status byte(hex) *\n")); 1114 EFUN_PRINTF(("* PLL_PWDN : PLL Powerdown Control Bit (active high) *\n")); 1115 EFUN_PRINTF(("* UC_ATV : UC Active bit *\n")); 1116 EFUN_PRINTF(("* COM_CLK : COM Clock frequency in MHz *\n")); 1117 EFUN_PRINTF(("* UCODE_VER : Microcode Version [majorversion_minorversion] *\n")); 1118 EFUN_PRINTF(("* AFE_VER : AFE Hardware Vesrion *\n")); 1119 EFUN_PRINTF(("* LIVE_TEMP : Live Die temperature in Celsius *\n")); 1120 EFUN_PRINTF(("* AVG_TMON : uC Temp_idx, Average temperature in Celsius *\n")); 1121 EFUN_PRINTF(("* RESCAL : Analog Resistor Calibration value *\n")); 1122 EFUN_PRINTF(("* VCO_RATE : uC VCO Rate in GHz (approximate) *\n")); 1123 EFUN_PRINTF(("* ANA_VCO_RANGE : Analog VCO Range *\n")); 1124 EFUN_PRINTF(("* PLL_DIV : (Register Value) Actual PLL Divider Value *\n")); 1125 EFUN_PRINTF(("* PLL_Lock : PLL Lock *\n")); 1126 1127 EFUN_PRINTF(("**************************************************************************************************************\n")); 1128 return ERR_CODE_NONE; 1129 } 1130 1131 /**********************************************/ 1132 /* Display Lane/Core Config and Debug Status */ 1133 /**********************************************/ 1134 1135 err_code_t eagle_tsc_display_core_config( const phymod_access_t *pa ){ 1136 uint16_t vco_mhz; 1137 EFUN_PRINTF(("\n\n*****************************************\n" )); 1138 EFUN_PRINTF(( "**** SERDES CORE 0x%03x CONFIGURATION ****\n", pa->addr )); 1139 EFUN_PRINTF(( "*****************************************\n\n")); 1140 { 1141 struct eagle_tsc_uc_core_config_st core_cfg; 1142 ENULL_MEMSET(&core_cfg, 0, sizeof(core_cfg)); 1143 EFUN(eagle_tsc_get_uc_core_config( pa, &core_cfg)); 1144 { 1145 vco_mhz = (uint16_t)core_cfg.vco_rate_in_Mhz; 1146 EFUN_PRINTF(( "uC Config VCO Rate = %d (~%d.%dGHz)\n", core_cfg.field.vco_rate 1147 , (vco_mhz / 1000) 1148 , (vco_mhz % 1000) )); 1149 EFUN_PRINTF(( "Core Config from PCS = %d\n\n", core_cfg.field.core_cfg_from_pcs)); 1150 } 1151 } 1152 ESTM_PRINTF(( "Lane Addr 0 = %d\n", rdc_lane_addr_0() )); 1153 ESTM_PRINTF(( "Lane Addr 1 = %d\n", rdc_lane_addr_1() )); 1154 ESTM_PRINTF(( "Lane Addr 2 = %d\n", rdc_lane_addr_2() )); 1155 ESTM_PRINTF(( "Lane Addr 3 = %d\n", rdc_lane_addr_3() )); 1156 ESTM_PRINTF(( "TX Lane Map 0 = %d\n", rdc_tx_lane_map_0() )); 1157 ESTM_PRINTF(( "TX Lane Map 1 = %d\n", rdc_tx_lane_map_1() )); 1158 ESTM_PRINTF(( "TX Lane Map 2 = %d\n", rdc_tx_lane_map_2() )); 1159 ESTM_PRINTF(( "TX Lane Map 3 = %d\n\n", rdc_tx_lane_map_3() )); 1160 return ERR_CODE_NONE; 1161 } 1162 1163 1164 err_code_t eagle_tsc_display_lane_config( const phymod_access_t *pa ){ 1165 struct eagle_tsc_uc_lane_config_st lane_cfg; 1166 1167 ENULL_MEMSET(&lane_cfg, 0, sizeof(lane_cfg)); 1168 1169 EFUN_PRINTF(("\n\n*************************************\n" )); 1170 ESTM_PRINTF(( "**** SERDES LANE %d CONFIGURATION ****\n", eagle_tsc_get_lane(pa) )); 1171 EFUN_PRINTF(( "*************************************\n\n" )); 1172 EFUN( eagle_tsc_get_uc_lane_cfg( pa, &lane_cfg) ); 1173 EFUN_PRINTF(( "Auto-Neg Enabled = %d\n", lane_cfg.field.an_enabled )); 1174 EFUN_PRINTF(( "DFE on = %d\n", lane_cfg.field.dfe_on )); 1175 EFUN_PRINTF(( "Brdfe_on = %d\n", lane_cfg.field.force_brdfe_on )); 1176 EFUN_PRINTF(( "Media Type = %d\n", lane_cfg.field.media_type )); 1177 EFUN_PRINTF(( "Unreliable LOS = %d\n", lane_cfg.field.unreliable_los )); 1178 EFUN_PRINTF(( "Scrambling Disable = %d\n", lane_cfg.field.scrambling_dis )); 1179 EFUN_PRINTF(( "Lane Config from PCS = %d\n\n", lane_cfg.field.lane_cfg_from_pcs )); 1180 ESTM_PRINTF(( "CL72 Training Enable = %d\n", rd_cl72_ieee_training_enable() )); 1181 EFUN_PRINTF(( "CL72 Auto Polarity Enable = %d\n", lane_cfg.field.cl72_auto_polarity_en )); 1182 EFUN_PRINTF(( "CL72 Restart timeout Enable = %d\n", lane_cfg.field.cl72_restart_timeout_en)); 1183 ESTM_PRINTF(( "EEE Mode Enable = %d\n", rd_eee_mode_en() )); 1184 ESTM_PRINTF(( "OSR Mode Force = %d\n", rd_osr_mode_frc() )); 1185 ESTM_PRINTF(( "OSR Mode Force Val = %d\n", rd_osr_mode_frc_val() )); 1186 ESTM_PRINTF(( "TX Polarity Invert = %d\n", rd_tx_pmd_dp_invert() )); 1187 ESTM_PRINTF(( "RX Polarity Invert = %d\n\n", rd_rx_pmd_dp_invert() )); 1188 ESTM_PRINTF(( "TXFIR Post2 = %d\n", rd_txfir_post2() )); 1189 ESTM_PRINTF(( "TXFIR Post3 = %d\n", rd_txfir_post3() )); 1190 ESTM_PRINTF(( "TXFIR Override Enable = %d\n", rd_txfir_override_en() )); 1191 ESTM_PRINTF(( "TXFIR Main Override = %d\n", rd_txfir_main_override() )); 1192 ESTM_PRINTF(( "TXFIR Pre Override = %d\n", rd_txfir_pre_override() )); 1193 ESTM_PRINTF(( "TXFIR Post Override = %d\n", rd_txfir_post_override() )); 1194 return ERR_CODE_NONE; 1195 } 1196 1197 1198 err_code_t eagle_tsc_display_core_state( const phymod_access_t *pa ){ 1199 EFUN(eagle_tsc_display_core_state_hdr( pa )); 1200 EFUN(eagle_tsc_display_core_state_line( pa )); 1201 EFUN(eagle_tsc_display_core_state_legend( pa )); 1202 return ERR_CODE_NONE; 1203 } 1204 1205 1206 1207 err_code_t eagle_tsc_display_lane_debug_status( const phymod_access_t *pa ){ 1208 /* startup */ 1209 struct eagle_tsc_usr_ctrl_disable_functions_st ds; 1210 struct eagle_tsc_usr_ctrl_disable_dfe_functions_st dsd; 1211 /* steady state */ 1212 struct eagle_tsc_usr_ctrl_disable_functions_st dss; 1213 struct eagle_tsc_usr_ctrl_disable_dfe_functions_st dssd; 1214 1215 ENULL_MEMSET(&ds, 0, sizeof(ds )); 1216 ENULL_MEMSET(&dsd, 0, sizeof(dsd )); 1217 ENULL_MEMSET(&dss, 0, sizeof(dss )); 1218 ENULL_MEMSET(&dssd, 0, sizeof(dssd)); 1219 1220 EFUN_PRINTF(("\n\n************************************\n" )); 1221 ESTM_PRINTF(( "**** SERDES LANE %d DEBUG STATUS ****\n", eagle_tsc_get_lane(pa) )); 1222 EFUN_PRINTF(( "************************************\n\n" )); 1223 ESTM_PRINTF(( "Restart Count = %d\n", rdv_usr_sts_restart_counter() )); 1224 ESTM_PRINTF(( "Reset Count = %d\n", rdv_usr_sts_reset_counter() )); 1225 ESTM_PRINTF(( "PMD Lock Count = %d\n\n", rdv_usr_sts_pmd_lock_counter() )); 1226 EFUN(eagle_tsc_get_usr_ctrl_disable_startup( pa, &ds)); 1227 EFUN_PRINTF(( "Disable Startup PF Adaptation = %d\n", ds.field.pf_adaptation )); 1228 EFUN_PRINTF(( "Disable Startup DC Adaptation = %d\n", ds.field.dc_adaptation )); 1229 EFUN_PRINTF(( "Disable Startup Slicer Offset Tuning = %d\n", ds.field.slicer_offset_tuning )); 1230 EFUN_PRINTF(( "Disable Startup Clk90 offset Adaptation = %d\n", ds.field.clk90_offset_adaptation )); 1231 EFUN_PRINTF(( "Disable Startup P1 level Tuning = %d\n", ds.field.p1_level_tuning )); 1232 EFUN_PRINTF(( "Disable Startup Eye Adaptaion = %d\n", ds.field.eye_adaptation )); 1233 EFUN_PRINTF(( "Disable Startup All Adaptaion = %d\n\n", ds.field.all_adaptation )); 1234 EFUN( eagle_tsc_get_usr_ctrl_disable_startup_dfe( pa, &dsd) ); 1235 EFUN_PRINTF(( "Disable Startup DFE Tap1 Adaptation = %d\n", dsd.field.dfe_tap1_adaptation )); 1236 EFUN_PRINTF(( "Disable Startup DFE Tap2 Adaptation = %d\n", dsd.field.dfe_tap2_adaptation )); 1237 EFUN_PRINTF(( "Disable Startup DFE Tap3 Adaptation = %d\n", dsd.field.dfe_tap3_adaptation )); 1238 EFUN_PRINTF(( "Disable Startup DFE Tap4 Adaptation = %d\n", dsd.field.dfe_tap4_adaptation )); 1239 EFUN_PRINTF(( "Disable Startup DFE Tap5 Adaptation = %d\n", dsd.field.dfe_tap5_adaptation )); 1240 EFUN_PRINTF(( "Disable Startup DFE Tap1 DCD = %d\n", dsd.field.dfe_tap1_dcd )); 1241 EFUN_PRINTF(( "Disable Startup DFE Tap2 DCD = %d\n\n", dsd.field.dfe_tap2_dcd )); 1242 EFUN( eagle_tsc_get_usr_ctrl_disable_steady_state( pa, &dss) ); 1243 EFUN_PRINTF(( "Disable Steady State PF Adaptation = %d\n", dss.field.pf_adaptation )); 1244 EFUN_PRINTF(( "Disable Steady State DC Adaptation = %d\n", dss.field.dc_adaptation )); 1245 EFUN_PRINTF(( "Disable Steady State Slicer Offset Tuning = %d\n", dss.field.slicer_offset_tuning )); 1246 EFUN_PRINTF(( "Disable Steady State Clk90 offset Adaptation = %d\n", dss.field.clk90_offset_adaptation )); 1247 EFUN_PRINTF(( "Disable Steady State P1 level Tuning = %d\n", dss.field.p1_level_tuning )); 1248 EFUN_PRINTF(( "Disable Steady State Eye Adaptaion = %d\n", dss.field.eye_adaptation )); 1249 EFUN_PRINTF(( "Disable Steady State All Adaptaion = %d\n\n", dss.field.all_adaptation )); 1250 EFUN( eagle_tsc_get_usr_ctrl_disable_steady_state_dfe( pa, &dssd) ); 1251 EFUN_PRINTF(( "Disable Steady State DFE Tap1 Adaptation = %d\n", dssd.field.dfe_tap1_adaptation )); 1252 EFUN_PRINTF(( "Disable Steady State DFE Tap2 Adaptation = %d\n", dssd.field.dfe_tap2_adaptation )); 1253 EFUN_PRINTF(( "Disable Steady State DFE Tap3 Adaptation = %d\n", dssd.field.dfe_tap3_adaptation )); 1254 EFUN_PRINTF(( "Disable Steady State DFE Tap4 Adaptation = %d\n", dssd.field.dfe_tap4_adaptation )); 1255 EFUN_PRINTF(( "Disable Steady State DFE Tap5 Adaptation = %d\n", dssd.field.dfe_tap5_adaptation )); 1256 EFUN_PRINTF(( "Disable Steady State DFE Tap1 DCD = %d\n", dssd.field.dfe_tap1_dcd )); 1257 EFUN_PRINTF(( "Disable Steady State DFE Tap2 DCD = %d\n\n", dssd.field.dfe_tap2_dcd )); 1258 ESTM_PRINTF(( "Retune after Reset = %d\n", rdv_usr_ctrl_retune_after_restart() )); 1259 ESTM_PRINTF(( "Clk90 offset Adjust = %d\n", rdv_usr_ctrl_clk90_offset_adjust() )); 1260 ESTM_PRINTF(( "Clk90 offset Override = %d\n", rdv_usr_ctrl_clk90_offset_override())); 1261 ESTM_PRINTF(( "Lane Event Log Level = %d\n", rdv_usr_ctrl_lane_event_log_level() )); 1262 1263 return ERR_CODE_NONE; 1264 } 1265 1266 1267 1268 /*************************/ 1269 /* Stop/Resume uC Lane */ 1270 /*************************/ 1271 1272 err_code_t eagle_tsc_stop_uc_lane( const phymod_access_t *pa, uint8_t enable){ 1273 1274 if (enable) 1275 return eagle_tsc_pmd_uc_control( pa, CMD_UC_CTRL_STOP_GRACEFULLY, 100); 1276 else 1277 return eagle_tsc_pmd_uc_control( pa, CMD_UC_CTRL_RESUME, 50); 1278 } 1279 1280 1281 err_code_t eagle_tsc_stop_uc_lane_status( const phymod_access_t *pa, uint8_t *uc_lane_stopped){ 1282 1283 if (!uc_lane_stopped) 1284 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1285 1286 ESTM(*uc_lane_stopped = rdv_usr_sts_micro_stopped()); 1287 1288 return ERR_CODE_NONE; 1289 } 1290 1291 1292 /*******************************/ 1293 /* Stop/Resume RX Adaptation */ 1294 /*******************************/ 1295 1296 err_code_t eagle_tsc_stop_rx_adaptation( const phymod_access_t *pa, uint8_t enable){ 1297 1298 if (enable) 1299 return eagle_tsc_pmd_uc_control( pa, CMD_UC_CTRL_STOP_GRACEFULLY, 100); 1300 else 1301 return eagle_tsc_pmd_uc_control( pa, CMD_UC_CTRL_RESUME, 50); 1302 } 1303 1304 err_code_t eagle_tsc_request_stop_rx_adaptation( const phymod_access_t *pa ){ 1305 1306 return eagle_tsc_pmd_uc_control_return_immediate( pa, CMD_UC_CTRL_STOP_GRACEFULLY); 1307 } 1308 1309 1310 /**********************/ 1311 /* uCode CRC Verify */ 1312 /**********************/ 1313 1314 err_code_t eagle_tsc_ucode_crc_verify( const phymod_access_t *pa, uint16_t ucode_len, uint16_t expected_crc_value){ 1315 uint16_t calc_crc; 1316 1317 EFUN(eagle_tsc_pmd_uc_cmd_with_data( pa, CMD_CALC_CRC, 0, ucode_len, 200)); 1318 1319 ESTM(calc_crc = rd_uc_dsc_data()); 1320 if (calc_crc != expected_crc_value) { 1321 EFUN_PRINTF(("UC CRC did not match expected=%04x : calculated=%04x\n", expected_crc_value, calc_crc)); 1322 return _error(ERR_CODE_UC_CRC_NOT_MATCH); 1323 } 1324 1325 return ERR_CODE_NONE; 1326 } 1327 1328 err_code_t eagle_tsc_start_ucode_crc_calc( const phymod_access_t *pa, uint16_t ucode_len){ 1329 1330 EFUN(eagle_tsc_pmd_uc_cmd_with_data_return_immediate( pa, CMD_CALC_CRC, 0, ucode_len)); /* Invoke Calculate CRC command and return control immediately */ 1331 return ERR_CODE_NONE; 1332 } 1333 1334 err_code_t eagle_tsc_check_ucode_crc( const phymod_access_t *pa, uint16_t expected_crc_value, uint32_t timeout_ms){ 1335 uint16_t calc_crc; 1336 err_code_t err_code; 1337 1338 err_code = eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1( pa, timeout_ms); /* Poll for uc_dsc_ready_for_cmd = 1 to indicate eagle_tsc ready for command */ 1339 if (err_code) { 1340 EFUN_PRINTF(("ERROR : DSC ready for command timed out. Previous uC command not finished yet\n")); 1341 return err_code; 1342 } 1343 ESTM(calc_crc = rd_uc_dsc_data()); 1344 if (calc_crc != expected_crc_value) { 1345 EFUN_PRINTF(("UC CRC did not match expected=%04x : calculated=%04x\n", expected_crc_value, calc_crc)); 1346 return _error(ERR_CODE_UC_CRC_NOT_MATCH); 1347 } 1348 1349 return ERR_CODE_NONE; 1350 } 1351 1352 1353 /******************************************************/ 1354 /* Commands through Serdes FW DSC Command Interface */ 1355 /******************************************************/ 1356 1357 err_code_t eagle_tsc_pmd_uc_cmd_return_immediate( const phymod_access_t *pa, enum srds_pmd_uc_cmd_enum cmd, uint8_t supp_info){ 1358 err_code_t err_code; 1359 uint16_t cmddata; 1360 1361 err_code = eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1( pa, 1); /* Poll for uc_dsc_ready_for_cmd = 1 to indicate eagle_tsc ready for command */ 1362 if (err_code) { 1363 EFUN_PRINTF(("ERROR : DSC ready for command timed out (before cmd) cmd = %d, supp_info = x%02x err=%d !\n", cmd, supp_info, err_code)); 1364 return err_code; 1365 } 1366 /*EFUN(wr_uc_dsc_supp_info(supp_info)); */ /* Supplement info field */ 1367 /*EFUN(wr_uc_dsc_error_found(0x0) ); */ /* Clear error found field */ 1368 /*EFUN(wr_uc_dsc_gp_uc_req(cmd) ); */ /* Set command code */ 1369 /*EFUN(wr_uc_dsc_ready_for_cmd(0x0) ); */ /* Issue command, by clearing "ready for command" field */ 1370 cmddata = (((uint16_t)supp_info) << 8) | (uint16_t)cmd; /* Combine writes to single write instead of 4 RMW */ 1371 1372 EFUN(eagle_tsc_pmd_wr_reg(pa,DSC_A_DSC_UC_CTRL, cmddata)); /* This address is same for Eagle, and all Merlin */ 1373 1374 return ERR_CODE_NONE; 1375 } 1376 1377 err_code_t eagle_tsc_pmd_uc_cmd( const phymod_access_t *pa, enum srds_pmd_uc_cmd_enum cmd, uint8_t supp_info, uint32_t timeout_ms){ 1378 1379 uint8_t uc_dsc_error_found; 1380 1381 EFUN(eagle_tsc_pmd_uc_cmd_return_immediate( pa, cmd, supp_info)); /* Invoke eagle_tsc_uc_cmd and return control immediately */ 1382 1383 EFUN(eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1( pa, timeout_ms)); /* Poll for uc_dsc_ready_for_cmd = 1 to indicate eagle_tsc ready for command */ 1384 ESTM(uc_dsc_error_found = rd_uc_dsc_error_found()); 1385 if (uc_dsc_error_found) { 1386 ESTM_PRINTF(("ERROR : DSC ready for command return error ( after cmd) cmd = %d, supp_info = x%02x !\n", cmd, rd_uc_dsc_supp_info())); 1387 return _error(ERR_CODE_UC_CMD_RETURN_ERROR); 1388 } 1389 return ERR_CODE_NONE; 1390 } 1391 1392 1393 err_code_t eagle_tsc_pmd_uc_cmd_with_data_return_immediate( const phymod_access_t *pa, enum srds_pmd_uc_cmd_enum cmd, uint8_t supp_info, uint16_t data){ 1394 uint16_t cmddata; 1395 err_code_t err_code; 1396 1397 err_code = eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1( pa, 1); /* Poll for uc_dsc_ready_for_cmd = 1 to indicate eagle_tsc ready for command */ 1398 if (err_code) { 1399 EFUN_PRINTF(("ERROR : DSC ready for command timed out (before cmd) cmd = %d, supp_info = x%02x, data = x%04x err=%d !\n", cmd, supp_info, data, err_code)); 1400 return err_code; 1401 } 1402 1403 EFUN(wr_uc_dsc_data(data)); /* Write value written to uc_dsc_data field */ 1404 /*EFUN(wr_uc_dsc_supp_info(supp_info)); */ /* Supplement info field */ 1405 /*EFUN(wr_uc_dsc_error_found(0x0)); */ /* Clear error found field */ 1406 /*EFUN(wr_uc_dsc_gp_uc_req(cmd)); */ /* Set command code */ 1407 /*EFUN(wr_uc_dsc_ready_for_cmd(0x0)); */ /* Issue command, by clearing "ready for command" field */ 1408 cmddata = (((uint16_t)supp_info) << 8) | (uint16_t)cmd; /* Combine writes to single write instead of 4 RMW */ 1409 1410 EFUN(eagle_tsc_pmd_wr_reg(pa,DSC_A_DSC_UC_CTRL, cmddata)); /* This address is same for Eagle, and all Merlin */ 1411 1412 return ERR_CODE_NONE; 1413 } 1414 1415 1416 err_code_t eagle_tsc_pmd_uc_cmd_with_data( const phymod_access_t *pa, enum srds_pmd_uc_cmd_enum cmd, uint8_t supp_info, uint16_t data, uint32_t timeout_ms){ 1417 1418 uint8_t uc_dsc_error_found; 1419 1420 EFUN(eagle_tsc_pmd_uc_cmd_with_data_return_immediate( pa, cmd, supp_info, data)); /* Invoke eagle_tsc_uc_cmd and return control immediately */ 1421 1422 EFUN(eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1( pa, timeout_ms)); /* Poll for uc_dsc_ready_for_cmd = 1 to indicate eagle_tsc ready for command */ 1423 ESTM(uc_dsc_error_found = rd_uc_dsc_error_found()); 1424 if (uc_dsc_error_found) { 1425 ESTM_PRINTF(("ERROR : DSC ready for command return error ( after cmd) cmd = %d, supp_info = x%02x !\n", cmd, rd_uc_dsc_supp_info())); 1426 return _error(ERR_CODE_UC_CMD_RETURN_ERROR); 1427 } 1428 return ERR_CODE_NONE; 1429 } 1430 1431 err_code_t eagle_tsc_pmd_uc_control_return_immediate( const phymod_access_t *pa, enum srds_pmd_uc_ctrl_cmd_enum control){ 1432 return eagle_tsc_pmd_uc_cmd_return_immediate( pa, CMD_UC_CTRL, (uint8_t)control); 1433 } 1434 1435 err_code_t eagle_tsc_pmd_uc_control( const phymod_access_t *pa, enum srds_pmd_uc_ctrl_cmd_enum control, uint32_t timeout_ms){ 1436 return eagle_tsc_pmd_uc_cmd( pa, CMD_UC_CTRL, (uint8_t)control, timeout_ms); 1437 } 1438 1439 err_code_t eagle_tsc_pmd_uc_diag_cmd( const phymod_access_t *pa, enum srds_pmd_uc_diag_cmd_enum control, uint32_t timeout_ms){ 1440 return eagle_tsc_pmd_uc_cmd( pa, CMD_DIAG_EN, (uint8_t)control, timeout_ms); 1441 } 1442 1443 1444 /************************************************************/ 1445 /* Serdes IP RAM access - Lane RAM Variables */ 1446 /*----------------------------------------------------------*/ 1447 /* - through Micro Register Interface for PMD IPs */ 1448 /* - through Serdes FW DSC Command Interface for Gallardo */ 1449 /************************************************************/ 1450 1451 /* Micro RAM Lane Byte Read */ 1452 uint8_t eagle_tsc_rdbl_uc_var( const phymod_access_t *pa, err_code_t *err_code_p, uint16_t addr){ 1453 uint8_t rddata; 1454 1455 if (!err_code_p) 1456 return 0; 1457 1458 EPSTM(rddata = eagle_tsc_rdb_uc_ram( pa, err_code_p, (LANE_VAR_RAM_BASE + addr + (eagle_tsc_get_lane(pa) * LANE_VAR_RAM_SIZE)))); /* Use Micro register interface for reading RAM */ 1459 1460 return rddata; 1461 } 1462 1463 /* Micro RAM Lane Byte Signed Read */ 1464 int8_t eagle_tsc_rdbls_uc_var( const phymod_access_t *pa, err_code_t *err_code_p, uint16_t addr){ 1465 return (int8_t)eagle_tsc_rdbl_uc_var( pa, err_code_p, addr); 1466 } 1467 1468 /* Micro RAM Lane Word Read */ 1469 uint16_t eagle_tsc_rdwl_uc_var( const phymod_access_t *pa, err_code_t *err_code_p, uint16_t addr){ 1470 uint16_t rddata; 1471 1472 if (!err_code_p) 1473 return 0; 1474 1475 if (addr % 2 != 0) { /* Validate even address */ 1476 *err_code_p = ERR_CODE_INVALID_RAM_ADDR; 1477 return 0; 1478 } 1479 1480 EPSTM(rddata = eagle_tsc_rdw_uc_ram( pa, err_code_p, (LANE_VAR_RAM_BASE + addr + (eagle_tsc_get_lane(pa) * LANE_VAR_RAM_SIZE)))); /* Use Micro register interface for reading RAM */ 1481 1482 return rddata; 1483 } 1484 1485 1486 /* Micro RAM Lane Word Signed Read */ 1487 int16_t eagle_tsc_rdwls_uc_var( const phymod_access_t *pa, err_code_t *err_code_p, uint16_t addr){ 1488 return (int16_t)eagle_tsc_rdwl_uc_var( pa, err_code_p, addr); 1489 } 1490 1491 /* Micro RAM Lane Byte Write */ 1492 err_code_t eagle_tsc_wrbl_uc_var( const phymod_access_t *pa, uint16_t addr, uint8_t wr_val){ 1493 1494 1495 if (addr < LANE_VAR_RAM_SIZE) 1496 return eagle_tsc_wrb_uc_ram( pa, (LANE_VAR_RAM_BASE + addr + (eagle_tsc_get_lane(pa) * LANE_VAR_RAM_SIZE)), wr_val); /* Use Micro register interface for writing RAM */ 1497 else 1498 return _error(ERR_CODE_INVALID_RAM_ADDR); 1499 } 1500 1501 /* Micro RAM Lane Byte Signed Write */ 1502 err_code_t eagle_tsc_wrbls_uc_var( const phymod_access_t *pa, uint16_t addr, int8_t wr_val){ 1503 return eagle_tsc_wrbl_uc_var( pa, addr, wr_val); 1504 } 1505 1506 /* Micro RAM Lane Word Write */ 1507 err_code_t eagle_tsc_wrwl_uc_var( const phymod_access_t *pa, uint16_t addr, uint16_t wr_val){ 1508 1509 1510 if (addr % 2 != 0) /* Validate even address */ 1511 return _error(ERR_CODE_INVALID_RAM_ADDR); 1512 if (addr < LANE_VAR_RAM_SIZE) 1513 return eagle_tsc_wrw_uc_ram( pa, (LANE_VAR_RAM_BASE + addr + (eagle_tsc_get_lane(pa) * LANE_VAR_RAM_SIZE)), wr_val); /* Use Micro register interface for writing RAM */ 1514 else 1515 return _error(ERR_CODE_INVALID_RAM_ADDR); 1516 } 1517 1518 /* Micro RAM Lane Word Signed Write */ 1519 err_code_t eagle_tsc_wrwls_uc_var( const phymod_access_t *pa, uint16_t addr, int16_t wr_val){ 1520 return eagle_tsc_wrwl_uc_var( pa, addr, wr_val); 1521 } 1522 1523 1524 /************************************************************/ 1525 /* Serdes IP RAM access - Core RAM Variables */ 1526 /*----------------------------------------------------------*/ 1527 /* - through Micro Register Interface for PMD IPs */ 1528 /* - through Serdes FW DSC Command Interface for Gallardo */ 1529 /************************************************************/ 1530 1531 /* Micro RAM Core Byte Read */ 1532 uint8_t eagle_tsc_rdbc_uc_var( const phymod_access_t *pa, err_code_t *err_code_p, uint8_t addr){ 1533 1534 uint8_t rddata; 1535 1536 if (!err_code_p) 1537 return 0; 1538 1539 EPSTM(rddata = eagle_tsc_rdb_uc_ram( pa, err_code_p, (CORE_VAR_RAM_BASE + addr))); /* Use Micro register interface for reading RAM */ 1540 1541 return rddata; 1542 } 1543 1544 /* Micro RAM Core Byte Signed Read */ 1545 int8_t eagle_tsc_rdbcs_uc_var( const phymod_access_t *pa, err_code_t *err_code_p, uint8_t addr){ 1546 return (int8_t)eagle_tsc_rdbc_uc_var( pa, err_code_p, addr); 1547 } 1548 1549 /* Micro RAM Core Word Read */ 1550 uint16_t eagle_tsc_rdwc_uc_var( const phymod_access_t *pa, err_code_t *err_code_p, uint8_t addr){ 1551 1552 uint16_t rddata; 1553 1554 if (!err_code_p) 1555 return 0; 1556 if (addr % 2 != 0) { /* Validate even address */ 1557 *err_code_p = ERR_CODE_INVALID_RAM_ADDR; 1558 return 0; 1559 } 1560 1561 EPSTM(rddata = eagle_tsc_rdw_uc_ram( pa, err_code_p, (CORE_VAR_RAM_BASE + addr))); /* Use Micro register interface for reading RAM */ 1562 1563 return rddata; 1564 } 1565 1566 /* Micro RAM Core Word Signed Read */ 1567 int16_t eagle_tsc_rdwcs_uc_var( const phymod_access_t *pa, err_code_t *err_code_p, uint8_t addr){ 1568 return (int16_t)eagle_tsc_rdwc_uc_var( pa, err_code_p, addr); 1569 } 1570 1571 /* Micro RAM Core Byte Write */ 1572 err_code_t eagle_tsc_wrbc_uc_var( const phymod_access_t *pa, uint8_t addr, uint8_t wr_val){ 1573 1574 1575 if (addr < CORE_VAR_RAM_SIZE) 1576 return eagle_tsc_wrb_uc_ram( pa, (CORE_VAR_RAM_BASE + addr), wr_val); /* Use Micro register interface for writing RAM */ 1577 else 1578 return _error(ERR_CODE_INVALID_RAM_ADDR); 1579 } 1580 1581 1582 /* Micro RAM Core Byte Signed Write */ 1583 err_code_t eagle_tsc_wrbcs_uc_var( const phymod_access_t *pa, uint8_t addr, int8_t wr_val){ 1584 return eagle_tsc_wrbc_uc_var( pa, addr, wr_val); 1585 } 1586 1587 /* Micro RAM Core Word Write */ 1588 err_code_t eagle_tsc_wrwc_uc_var( const phymod_access_t *pa, uint8_t addr, uint16_t wr_val){ 1589 if (addr % 2 != 0) /* Validate even address */ 1590 return _error(ERR_CODE_INVALID_RAM_ADDR); 1591 if (addr < CORE_VAR_RAM_SIZE) 1592 return eagle_tsc_wrw_uc_ram( pa, (CORE_VAR_RAM_BASE + addr), wr_val); /* Use Micro register interface for writing RAM */ 1593 else 1594 return _error(ERR_CODE_INVALID_RAM_ADDR); 1595 } 1596 1597 /* Micro RAM Core Word Signed Write */ 1598 err_code_t eagle_tsc_wrwcs_uc_var( const phymod_access_t *pa, uint8_t addr, int16_t wr_val){ 1599 return eagle_tsc_wrwc_uc_var( pa, addr, wr_val); 1600 } 1601 1602 1603 1604 /*******************************************************************/ 1605 /* APIs to Write Core/Lane Config and User variables into uC RAM */ 1606 /*******************************************************************/ 1607 1608 err_code_t eagle_tsc_set_uc_core_config( const phymod_access_t *pa, struct eagle_tsc_uc_core_config_st struct_val){ 1609 { 1610 #ifndef ATE_LOG 1611 uint8_t reset_state; 1612 ESTM(reset_state = rdc_core_dp_reset_state()); 1613 if (reset_state < 7) { 1614 EFUN_PRINTF(("ERROR: eagle_tsc_set_uc_core_config( pa, ..) called without core_dp_s_rstb=0 Lane=%d reset_state=%d\n", eagle_tsc_get_lane(pa), reset_state)); 1615 return _error(ERR_CODE_CORE_DP_NOT_RESET); 1616 } 1617 #endif 1618 } 1619 if (struct_val.vco_rate_in_Mhz > 0) 1620 struct_val.field.vco_rate = MHZ_TO_VCO_RATE(struct_val.vco_rate_in_Mhz); 1621 EFUN(_update_uc_core_config_word( pa, &struct_val)); 1622 EFUN(wrcv_config_word(struct_val.word)); 1623 return ERR_CODE_NONE; 1624 } 1625 1626 err_code_t eagle_tsc_set_usr_ctrl_core_event_log_level( const phymod_access_t *pa, uint8_t core_event_log_level){ 1627 return wrcv_usr_ctrl_core_event_log_level(core_event_log_level); 1628 } 1629 1630 err_code_t eagle_tsc_set_uc_lane_cfg( const phymod_access_t *pa, struct eagle_tsc_uc_lane_config_st struct_val){ 1631 #ifndef ATE_LOG 1632 uint8_t reset_state; 1633 1634 ESTM(reset_state = rd_lane_dp_reset_state()); 1635 if (reset_state < 7) { 1636 EFUN_PRINTF(("ERROR: eagle_tsc_set_uc_lane_cfg( pa, ..) called without ln_dp_s_rstb=0 Lane=%d reset_state=%d\n", eagle_tsc_get_lane(pa), reset_state)); 1637 return _error(ERR_CODE_LANE_DP_NOT_RESET); 1638 } 1639 #endif 1640 EFUN(_update_uc_lane_config_word( pa, &struct_val)); 1641 return wrv_config_word(struct_val.word); 1642 } 1643 1644 err_code_t eagle_tsc_set_usr_ctrl_lane_event_log_level( const phymod_access_t *pa, uint8_t lane_event_log_level){ 1645 return wrv_usr_ctrl_lane_event_log_level(lane_event_log_level); 1646 } 1647 1648 err_code_t eagle_tsc_set_usr_ctrl_disable_startup( const phymod_access_t *pa, struct eagle_tsc_usr_ctrl_disable_functions_st set_val){ 1649 EFUN(_update_usr_ctrl_disable_functions_byte( pa, &set_val)); 1650 return wrv_usr_ctrl_disable_startup_functions_byte(set_val.byte); 1651 } 1652 1653 err_code_t eagle_tsc_set_usr_ctrl_disable_startup_dfe( const phymod_access_t *pa, struct eagle_tsc_usr_ctrl_disable_dfe_functions_st set_val){ 1654 EFUN(_update_usr_ctrl_disable_dfe_functions_byte( pa, &set_val)); 1655 return wrv_usr_ctrl_disable_startup_dfe_functions_byte(set_val.byte); 1656 } 1657 1658 err_code_t eagle_tsc_set_usr_ctrl_disable_steady_state( const phymod_access_t *pa, struct eagle_tsc_usr_ctrl_disable_functions_st set_val){ 1659 EFUN(_update_usr_ctrl_disable_functions_byte( pa, &set_val)); 1660 return wrv_usr_ctrl_disable_steady_state_functions_byte(set_val.byte); 1661 } 1662 1663 err_code_t eagle_tsc_set_usr_ctrl_disable_steady_state_dfe( const phymod_access_t *pa, struct eagle_tsc_usr_ctrl_disable_dfe_functions_st set_val){ 1664 EFUN(_update_usr_ctrl_disable_dfe_functions_byte( pa, &set_val)); 1665 return wrv_usr_ctrl_disable_steady_state_dfe_functions_byte(set_val.byte); 1666 } 1667 1668 1669 1670 /******************************************************************/ 1671 /* APIs to Read Core/Lane Config and User variables from uC RAM */ 1672 /******************************************************************/ 1673 1674 err_code_t eagle_tsc_get_uc_core_config( const phymod_access_t *pa, struct eagle_tsc_uc_core_config_st *get_val){ 1675 1676 if (!get_val) 1677 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1678 ESTM(get_val->word = rdcv_config_word()); 1679 EFUN(_update_uc_core_config_st( pa, get_val)); 1680 return ERR_CODE_NONE; 1681 } 1682 1683 err_code_t eagle_tsc_get_usr_ctrl_core_event_log_level( const phymod_access_t *pa, uint8_t *core_event_log_level){ 1684 1685 if (!core_event_log_level) 1686 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1687 1688 ESTM(*core_event_log_level = rdcv_usr_ctrl_core_event_log_level()); 1689 1690 return ERR_CODE_NONE; 1691 } 1692 1693 err_code_t eagle_tsc_get_uc_lane_cfg( const phymod_access_t *pa, struct eagle_tsc_uc_lane_config_st *get_val){ 1694 1695 if (!get_val) 1696 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1697 1698 ESTM(get_val->word = rdv_config_word()); 1699 EFUN(_update_uc_lane_config_st( pa, get_val)); 1700 return ERR_CODE_NONE; 1701 } 1702 1703 err_code_t eagle_tsc_get_usr_ctrl_lane_event_log_level( const phymod_access_t *pa, uint8_t *lane_event_log_level){ 1704 1705 if (!lane_event_log_level) 1706 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1707 1708 ESTM(*lane_event_log_level = rdv_usr_ctrl_lane_event_log_level()); 1709 return ERR_CODE_NONE; 1710 } 1711 1712 err_code_t eagle_tsc_get_usr_ctrl_disable_startup( const phymod_access_t *pa, struct eagle_tsc_usr_ctrl_disable_functions_st *get_val){ 1713 1714 if (!get_val) 1715 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1716 1717 ESTM(get_val->byte = rdv_usr_ctrl_disable_startup_functions_byte()); 1718 EFUN(_update_usr_ctrl_disable_functions_st( pa, get_val)); 1719 return ERR_CODE_NONE; 1720 } 1721 1722 err_code_t eagle_tsc_get_usr_ctrl_disable_startup_dfe( const phymod_access_t *pa, struct eagle_tsc_usr_ctrl_disable_dfe_functions_st *get_val){ 1723 1724 if (!get_val) 1725 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1726 1727 ESTM(get_val->byte = rdv_usr_ctrl_disable_startup_dfe_functions_byte()); 1728 EFUN(_update_usr_ctrl_disable_dfe_functions_st( pa, get_val)); 1729 return ERR_CODE_NONE; 1730 } 1731 1732 err_code_t eagle_tsc_get_usr_ctrl_disable_steady_state( const phymod_access_t *pa, struct eagle_tsc_usr_ctrl_disable_functions_st *get_val){ 1733 1734 if (!get_val) 1735 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1736 1737 ESTM(get_val->byte = rdv_usr_ctrl_disable_steady_state_functions_byte()); 1738 EFUN(_update_usr_ctrl_disable_functions_st( pa, get_val)); 1739 return ERR_CODE_NONE; 1740 } 1741 1742 err_code_t eagle_tsc_get_usr_ctrl_disable_steady_state_dfe( const phymod_access_t *pa, struct eagle_tsc_usr_ctrl_disable_dfe_functions_st *get_val){ 1743 1744 if (!get_val) 1745 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1746 1747 ESTM(get_val->byte = rdv_usr_ctrl_disable_steady_state_dfe_functions_byte()); 1748 EFUN(_update_usr_ctrl_disable_dfe_functions_st( pa, get_val)); 1749 return ERR_CODE_NONE; 1750 } 1751 1752 err_code_t eagle_tsc_get_clk90_offset_adjust( const phymod_access_t *pa, int8_t *adjust){ 1753 if (!adjust) 1754 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1755 ESTM(*adjust = (int8_t)rdv_usr_ctrl_clk90_offset_adjust()); 1756 return ERR_CODE_NONE; 1757 } 1758 1759 err_code_t eagle_tsc_set_clk90_offset_adjust( const phymod_access_t *pa, int8_t adjust){ 1760 1761 EFUN(_check_uc_lane_stopped( pa )); /* make sure uC is stopped to avoid race conditions */ 1762 1763 if ((adjust > 16) || (adjust < -16)) 1764 return _error(ERR_CODE_INVALID_CLK90_ADJUST); 1765 ESTM(wrv_usr_ctrl_clk90_offset_adjust((uint8_t)(adjust))); 1766 return ERR_CODE_NONE; 1767 } 1768 1769 err_code_t eagle_tsc_get_clk90_offset_override( const phymod_access_t *pa, uint8_t *override){ 1770 if (!override) 1771 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1772 ESTM(*override = rdv_usr_ctrl_clk90_offset_override()); 1773 return ERR_CODE_NONE; 1774 } 1775 1776 err_code_t eagle_tsc_set_clk90_offset_override( const phymod_access_t *pa, uint8_t enable, uint8_t override){ 1777 1778 EFUN(_check_uc_lane_stopped( pa )); /* make sure uC is stopped to avoid race conditions */ 1779 1780 if ((override >= 52) || (override <= 24)) 1781 return _error(ERR_CODE_INVALID_CLK90_OVERRIDE); 1782 ESTM(wrv_usr_ctrl_clk90_offset_override(((enable & 1) << 7) | override)); 1783 return ERR_CODE_NONE; 1784 } 1785 1786 err_code_t eagle_tsc_get_clk90_offset( const phymod_access_t *pa, int8_t *offset){ 1787 int8_t clk90_offset; 1788 1789 if (!offset) 1790 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1791 1792 ESTM(clk90_offset = rd_cnt_d_minus_m1()); 1793 /* drop the MSB, the result is actually valid modulo 128 */ 1794 /* Also flip the sign to account for d-m1, versus m1-d */ 1795 clk90_offset = clk90_offset << 1; 1796 *offset = -(clk90_offset >> 1); 1797 1798 return ERR_CODE_NONE; 1799 } 1800 1801 1802 /******************************************/ 1803 /* Serdes Register field Poll functions */ 1804 /******************************************/ 1805 1806 #ifndef CUSTOM_REG_POLLING 1807 1808 /* poll for microcontroller to populate the dsc_data register */ 1809 err_code_t eagle_tsc_poll_diag_done( const phymod_access_t *pa, uint16_t *status, uint32_t timeout_ms){ 1810 uint8_t loop; 1811 1812 if (!status) 1813 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1814 1815 for (loop = 0; loop < 100; loop++) { 1816 ESTM(*status = rdv_usr_diag_status()); 1817 1818 if ((*status & 0x8000) > 0) 1819 return ERR_CODE_NONE; 1820 if (loop > 10) 1821 EFUN(eagle_tsc_delay_us(10 * timeout_ms)); 1822 } 1823 return _error(ERR_CODE_DIAG_TIMEOUT); 1824 } 1825 1826 /* poll for microcontroller to populate the dsc_data register */ 1827 err_code_t eagle_tsc_poll_diag_eye_data(const phymod_access_t *pa,uint32_t *data, uint16_t *status, uint32_t timeout_ms){ 1828 uint8_t loop; 1829 uint16_t dscdata; 1830 1831 if (!data || !status) 1832 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1833 1834 for (loop = 0; loop < 100; loop++) { 1835 ESTM(*status = rdv_usr_diag_status()); 1836 if (((*status & 0x00FF) > 2) || ((*status & 0x8000) > 0)) { 1837 EFUN(eagle_tsc_pmd_uc_cmd( pa, CMD_READ_DIAG_DATA_WORD, 0, 200)); 1838 ESTM(dscdata = rd_uc_dsc_data()); 1839 data[0] = _float8_to_int32((float8_t)(dscdata >> 8)); 1840 data[1] = _float8_to_int32((float8_t)(dscdata & 0x00FF)); 1841 return ERR_CODE_NONE; 1842 } 1843 if (loop > 10) 1844 EFUN(eagle_tsc_delay_us(10 * timeout_ms)); 1845 } 1846 return _error(ERR_CODE_DIAG_TIMEOUT); 1847 } 1848 1849 /** Poll for field "uc_dsc_ready_for_cmd" = 1 [Return Val => Error_code (0 = Polling Pass)] */ 1850 err_code_t eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1( const phymod_access_t *pa, uint32_t timeout_ms){ 1851 #ifndef ATE_LOG 1852 uint16_t loop; 1853 1854 /* read quickly for 4 tries */ 1855 for (loop = 0; loop < 100; loop++) { 1856 uint16_t rddata; 1857 EFUN(eagle_tsc_pmd_rdt_reg(pa,DSC_A_DSC_UC_CTRL, &rddata)); 1858 if (rddata & 0x0080) { /* bit 7 is uc_dsc_ready_for_cmd */ 1859 if (rddata & 0x0040) { /* bit 6 is uc_dsc_error_found */ 1860 ESTM_PRINTF(("ERROR : DSC command returned error (after cmd) cmd = 0x%x, supp_info = 0x%02x !\n", rd_uc_dsc_gp_uc_req(), rd_uc_dsc_supp_info())); 1861 return _error(ERR_CODE_UC_CMD_RETURN_ERROR); 1862 } 1863 return ERR_CODE_NONE; 1864 } 1865 if (loop > 10) 1866 EFUN(eagle_tsc_delay_us(10 * timeout_ms)); 1867 } 1868 1869 #else 1870 { uint16_t rddata; 1871 EFUN_PRINTF(("// ATE_LOG eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1 begin\n")); 1872 if (timeout_ms < 100) 1873 EFUN(eagle_tsc_delay_us(1000 * timeout_ms)); 1874 else 1875 EFUN(eagle_tsc_delay_ms(timeout_ms)); 1876 EFUN(eagle_tsc_pmd_rdt_reg(pa,DSC_A_DSC_UC_CTRL, &rddata)); 1877 if (rddata & 0x0080) { /* bit 7 is uc_dsc_ready_for_cmd */ 1878 if (rddata & 0x0040) { /* bit 6 is uc_dsc_error_found */ 1879 ESTM_PRINTF(("ERROR : DSC command returned error (after cmd) cmd = 0x%x, supp_info = 0x%02x !\n", rd_uc_dsc_gp_uc_req(), rd_uc_dsc_supp_info())); 1880 return _error(ERR_CODE_UC_CMD_RETURN_ERROR); 1881 } 1882 EFUN_PRINTF(("// ATE_LOG eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1 end\n")); 1883 return ERR_CODE_NONE; 1884 } 1885 EFUN_PRINTF(("// ATE_LOG eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1 timeout\n")); } 1886 #endif 1887 EFUN_PRINTF(("ERROR : DSC ready for command is not working, applying workaround and getting debug info !\n")); 1888 DISP(rd_uc_dsc_ready_for_cmd()); 1889 DISP(rd_uc_dsc_supp_info()); 1890 DISP(rd_uc_dsc_gp_uc_req()); 1891 DISP(rd_uc_dsc_data()); 1892 DISP(rd_dsc_state()); 1893 ESTM_PRINTF(("Uc Core Status Byte = %x\n", rdcv_status_byte())); 1894 /* artifically terminate the command to re-enable the command interface */ 1895 EFUN(wr_uc_dsc_ready_for_cmd(0x1)); 1896 return _error(ERR_CODE_POLLING_TIMEOUT); /* Error Code for polling timeout */ 1897 } 1898 1899 /* Poll for field "dsc_state" = DSC_STATE_UC_TUNE [Return Val => Error_code (0 = Polling Pass)] */ 1900 err_code_t eagle_tsc_poll_dsc_state_equals_uc_tune( const phymod_access_t *pa, uint32_t timeout_ms){ 1901 uint16_t loop; 1902 uint16_t dsc_state; 1903 1904 /* poll 10 times to avoid longer delays later */ 1905 for (loop = 0; loop < 100; loop++) { 1906 ESTM(dsc_state = rd_dsc_state()); 1907 if (dsc_state == DSC_STATE_UC_TUNE) 1908 return ERR_CODE_NONE; 1909 if (loop > 10) 1910 EFUN(eagle_tsc_delay_us(10 * timeout_ms)); 1911 } 1912 ESTM_PRINTF(("DSC_STATE = %d\n", rd_dsc_state())); 1913 return _error(ERR_CODE_POLLING_TIMEOUT); /* Error Code for polling timeout */ 1914 } 1915 1916 1917 1918 1919 #endif /* CUSTOM_REG_POLLING */ 1920 1921 1922 1923 1924 err_code_t eagle_tsc_init_pram_for_uc_load( const phymod_access_t *pa, uint16_t ucode_len){ 1925 uint8_t result; 1926 1927 if (ucode_len > UCODE_MAX_SIZE) /* uCode size should be less than UCODE_MAX_SIZE */ 1928 return _error(ERR_CODE_INVALID_UCODE_LEN); 1929 EFUN(wrc_micro_mdio_dw8051_reset_n(0x0)); 1930 EFUN(wrc_micro_system_clk_en(0x1)); /* Enable clock to micro */ 1931 EFUN(wrc_micro_system_reset_n(0x1)); /* De-assert reset to micro */ 1932 EFUN(wrc_micro_system_reset_n(0x0)); /* Assert reset to micro - Toggling micro reset*/ 1933 EFUN(wrc_micro_system_reset_n(0x1)); /* De-assert reset to micro */ 1934 EFUN(wrc_micro_pram_if_flop_bypass(1)); 1935 EFUN(wrc_micro_mdio_ram_access_mode(0x0)); /* Select Program Memory access mode - Program RAM load when Serdes DW8051 in reset */ 1936 EFUN(wrc_micro_byte_mode(0)); 1937 1938 EFUN(wrc_micro_ram_address(0x0)); /* RAM start address */ 1939 1940 EFUN(wrc_micro_init_cmd(0x0)); /* Clear initialization command */ 1941 EFUN(wrc_micro_init_cmd(0x1)); /* Set initialization command */ 1942 EFUN(wrc_micro_init_cmd(0x0)); /* Clear initialization command */ 1943 1944 EFUN(eagle_tsc_delay_us(500)); 1945 1946 ESTM(result = !rdc_micro_init_done()); 1947 if (result) /* Check if initialization done within 500us time interval */ 1948 return _error(ERR_CODE_MICRO_INIT_NOT_DONE); /* Else issue error code */ 1949 1950 /* ucode_len_padded = ((ucode_len + 7) & 0xFFF8); */ /* Aligning ucode size to 8-byte boundary */ 1951 EFUN(wrc_micro_pram_if_en(1)); 1952 /* set the pram_abilty input of the pram interface to 1b1 */ 1953 /* pram_abilty = 1; */ 1954 /* Wait 8 pram clocks */ 1955 EFUN(wrc_micro_pram_if_rstb(1)); 1956 /* Wait 8 pram clocks */ 1957 /* write ucode into pram */ 1958 /* Wait 8 pram clocks */ 1959 /* call eagle_tsc_finish_pram_load */ 1960 return ERR_CODE_NONE; 1961 } 1962 1963 err_code_t eagle_tsc_finish_pram_load( const phymod_access_t *pa ){ 1964 /* set the pram_abilty input of the pram interface to 1b0 */ 1965 /* pram_abilty = 0; */ 1966 EFUN(wrc_micro_pram_if_en(0)); 1967 EFUN(wrc_micro_pram_if_rstb(0)); 1968 /* EFUN(wr_mdio_dw8051_reset_n(1)); */ 1969 return ERR_CODE_NONE; 1970 } 1971 1972 /****************************************/ 1973 /* Serdes Register/Variable Dump APIs */ 1974 /****************************************/ 1975 1976 err_code_t eagle_tsc_reg_dump( const phymod_access_t *pa ){ 1977 1978 uint16_t addr, rddata; 1979 1980 EFUN_PRINTF(("\n**** SERDES REGISTER DUMP ****")); 1981 1982 for (addr = 0x0; addr < 0x10; addr++) { 1983 if (!(addr % 16)) 1984 EFUN_PRINTF(("\n%04x ", addr)); 1985 EFUN(eagle_tsc_pmd_rdt_reg(pa, addr, &rddata)); 1986 EFUN_PRINTF(("%04x ", rddata)); 1987 } 1988 1989 for (addr = 0x90; addr < 0xA0; addr++) { 1990 if (!(addr % 16)) 1991 EFUN_PRINTF(("\n%04x ", addr)); 1992 EFUN(eagle_tsc_pmd_rdt_reg(pa,addr, &rddata)); 1993 EFUN_PRINTF(("%04x ", rddata)); 1994 } 1995 1996 for (addr = 0xD000; addr < 0xD180; addr++) { 1997 if (!(addr % 16)) 1998 EFUN_PRINTF(("\n%04x ", addr)); 1999 EFUN(eagle_tsc_pmd_rdt_reg(pa, addr, &rddata)); 2000 EFUN_PRINTF(("%04x ", rddata)); 2001 } 2002 2003 2004 for (addr = 0xD200; addr < 0xD230; addr++) { 2005 if (!(addr % 16)) 2006 EFUN_PRINTF(("\n%04x ", addr)); 2007 EFUN(eagle_tsc_pmd_rdt_reg(pa, addr, &rddata)); 2008 EFUN_PRINTF(("%04x ", rddata)); 2009 } 2010 2011 for (addr = 0xFFD0; addr < 0xFFE0; addr++) { 2012 if (!(addr % 16)) 2013 EFUN_PRINTF(("\n%04x ", addr)); 2014 EFUN(eagle_tsc_pmd_rdt_reg(pa, addr, &rddata)); 2015 EFUN_PRINTF(("%04x ", rddata)); 2016 } 2017 return ERR_CODE_NONE; 2018 } 2019 2020 2021 err_code_t eagle_tsc_uc_core_var_dump( const phymod_access_t *pa ){ 2022 uint8_t addr; 2023 2024 EFUN_PRINTF(("\n**** SERDES UC CORE RAM VARIABLE DUMP ****")); 2025 2026 for (addr = 0x0; addr < 0xFF; addr++) { 2027 if (!(addr % 26)) 2028 EFUN_PRINTF(("\n%04x ", addr)); 2029 ESTM_PRINTF(("%02x ", eagle_tsc_rdbc_uc_var( pa, __ERR, addr))); 2030 } 2031 return ERR_CODE_NONE; 2032 } 2033 2034 2035 err_code_t eagle_tsc_uc_lane_var_dump( const phymod_access_t *pa ){ 2036 uint8_t rx_lock, uc_stopped = 0; 2037 uint16_t addr; 2038 2039 2040 EFUN_PRINTF(("\n**** SERDES UC LANE %d RAM VARIABLE DUMP ****", eagle_tsc_get_lane(pa))); 2041 2042 ESTM(rx_lock = rd_pmd_rx_lock()); 2043 2044 if (rx_lock == 1) { 2045 ESTM(uc_stopped = rdv_usr_sts_micro_stopped()); 2046 if (!uc_stopped) 2047 EFUN(eagle_tsc_stop_rx_adaptation( pa, 1)); 2048 } else 2049 EFUN(eagle_tsc_pmd_uc_control( pa, CMD_UC_CTRL_STOP_IMMEDIATE, 200)); 2050 2051 for (addr = 0x0; addr < LANE_VAR_RAM_SIZE; addr++) { 2052 if (!(addr % 26)) 2053 EFUN_PRINTF(("\n%04x ", addr)); 2054 ESTM_PRINTF(("%02x ", eagle_tsc_rdbl_uc_var( pa, __ERR, addr))); 2055 } 2056 2057 if (rx_lock == 1) { 2058 if (!uc_stopped) 2059 EFUN(eagle_tsc_stop_rx_adaptation( pa, 0)); 2060 } else 2061 EFUN(eagle_tsc_stop_rx_adaptation( pa, 0)); 2062 2063 return ERR_CODE_NONE; 2064 } 2065 2066 /* Required Diagnostic Functions */ 2067 err_code_t eagle_tsc_display_diag_data( const phymod_access_t *pa, int32_t diag_level){ 2068 uint8_t rx_lock, micro_stop; 2069 uint32_t api_version; 2070 2071 EFUN_PRINTF(("\n**** SERDES DISPLAY DIAG DATA ****\n")); 2072 ESTM_PRINTF(("Rev ID Letter = %02X\n", rdc_revid_rev_letter())); 2073 ESTM_PRINTF(("Rev ID Process = %02X\n", rdc_revid_process())); 2074 ESTM_PRINTF(("Rev ID Model = %02X\n", rdc_revid_model())); 2075 ESTM_PRINTF(("Rev ID Model = %02X\n", rdc_revid2())); 2076 ESTM_PRINTF(("Rev ID # Lanes = %d\n", rdc_revid_multiplicity())); 2077 ESTM_PRINTF(("Core = %d; LANE = %d\n", eagle_tsc_get_core(), eagle_tsc_get_lane(pa))); 2078 EFUN(eagle_tsc_version( pa, &api_version)); 2079 EFUN_PRINTF(("SERDES API Version = %06X\n", api_version)); 2080 ESTM_PRINTF(("Common Ucode Version = %04X", rdcv_common_ucode_version())); 2081 ESTM_PRINTF(("_%02X\n", rdcv_common_ucode_minor_version())); 2082 ESTM_PRINTF(("AFE Hardware Version = 0x%X\n\n", rdcv_afe_hardware_version())); 2083 2084 2085 /* stop micro so all accesses are consistent */ 2086 ESTM(rx_lock = rd_pmd_rx_lock()); 2087 ESTM(micro_stop = rdv_usr_sts_micro_stopped()); 2088 if (rx_lock == 1) { 2089 if (!micro_stop) 2090 EFUN(eagle_tsc_stop_rx_adaptation( pa, 1)); 2091 } else 2092 EFUN(eagle_tsc_pmd_uc_control( pa, CMD_UC_CTRL_STOP_IMMEDIATE, 200)); 2093 2094 EFUN(eagle_tsc_display_lane_state_hdr( pa )); 2095 EFUN(eagle_tsc_display_lane_state( pa )); 2096 if (diag_level & SRDS_DIAG_CORE) { 2097 EFUN(eagle_tsc_display_core_state_hdr( pa )); 2098 EFUN(eagle_tsc_display_core_state_line( pa )); 2099 } 2100 if (diag_level & SRDS_DIAG_EVENT) { 2101 uint8_t trace_mem[1000]; 2102 USR_MEMSET(trace_mem, 0, sizeof(trace_mem)); 2103 EFUN(eagle_tsc_read_event_log( pa, trace_mem, EVENT_LOG_HEX)); 2104 } 2105 if (diag_level & SRDS_DIAG_EYE) 2106 EFUN(eagle_tsc_display_eye_scan( pa )); 2107 if (diag_level & SRDS_DIAG_REG_CORE) 2108 EFUN(eagle_tsc_reg_dump( pa )); 2109 /* currently REG_CORE and REG_LANE dump same data. */ 2110 /*if(diag_level & SRDS_DIAG_REG_LANE) {*/ 2111 /* EFUN(eagle_tsc_reg_dump( pa ));*/ 2112 /*}*/ 2113 if (diag_level & SRDS_DIAG_UC_CORE) 2114 EFUN(eagle_tsc_uc_core_var_dump( pa )); 2115 if (diag_level & SRDS_DIAG_UC_LANE) 2116 EFUN(eagle_tsc_uc_lane_var_dump( pa )); 2117 if (diag_level & SRDS_DIAG_LANE_DEBUG) 2118 EFUN(eagle_tsc_display_lane_debug_status( pa )); 2119 if (diag_level & SRDS_DIAG_BER_VERT) { 2120 /* display ber projections for all channels */ 2121 uint8_t ber_mode = DIAG_BER_VERT | DIAG_BER_POS; 2122 uint8_t timer_control = 23; /* 30 seconds */ 2123 uint8_t err_threshold = 100 / 16; /* 100 errors */ 2124 EFUN(_eagle_tsc_display_ber_scan_data( pa, ber_mode, timer_control, err_threshold)); 2125 ber_mode = DIAG_BER_VERT | DIAG_BER_NEG; 2126 EFUN(_eagle_tsc_display_ber_scan_data( pa, ber_mode, timer_control, err_threshold)); 2127 } 2128 if (diag_level & SRDS_DIAG_BER_HORZ) { 2129 /* display ber projections for all channels */ 2130 uint8_t ber_mode = DIAG_BER_HORZ | DIAG_BER_POS; 2131 uint8_t timer_control = 23; /* 30 seconds */ 2132 uint8_t err_threshold = 100 / 16; /* 100 errors */ 2133 EFUN(_eagle_tsc_display_ber_scan_data( pa, ber_mode, timer_control, err_threshold)); 2134 ber_mode = DIAG_BER_HORZ | DIAG_BER_NEG; 2135 EFUN(_eagle_tsc_display_ber_scan_data( pa, ber_mode, timer_control, err_threshold)); 2136 } 2137 2138 /* re enable micro */ 2139 if (rx_lock == 1) { 2140 if (!micro_stop) 2141 EFUN(eagle_tsc_stop_rx_adaptation( pa, 0)); 2142 } else 2143 EFUN(eagle_tsc_stop_rx_adaptation( pa, 0)); 2144 2145 EFUN_PRINTF(("\n\n")); 2146 return ERR_CODE_NONE; 2147 2148 } 2149 2150 /* Required Diagnostic Functions */ 2151 err_code_t eagle_tsc_diag_access( const phymod_access_t *pa, enum srds_diag_access_enum type, uint16_t addr, uint16_t data, uint16_t param){ 2152 2153 switch (type) { 2154 case SRDS_REG_READ: { 2155 uint16_t tmp; 2156 if (data > 1) { 2157 uint16_t i; 2158 EFUN_PRINTF(("\n**** SERDES BLK REGISTER READ ****")); 2159 for (i = 0; i < data; i++) { 2160 if (!(i % 16)) 2161 ESTM_PRINTF(("\n%04x ", i + addr)); 2162 EFUN(eagle_tsc_pmd_rdt_reg(pa, i + addr, &tmp)); 2163 ESTM_PRINTF(("%04x ", tmp)); 2164 } 2165 EFUN_PRINTF(("\n")); 2166 } else { 2167 EFUN(eagle_tsc_pmd_rdt_reg(pa, addr, &tmp)); 2168 EFUN_PRINTF(("Register Read: x%04x = x%04x\n", addr, tmp)); 2169 } 2170 } break; 2171 case SRDS_REG_RMW: { 2172 uint16_t tmp, tmp2; 2173 EFUN(eagle_tsc_pmd_rdt_reg(pa, addr, &tmp)); 2174 tmp2 = (tmp & ~param) | (param & data); 2175 EFUN(eagle_tsc_pmd_wr_reg(pa, addr, tmp2)); 2176 EFUN_PRINTF(("Register RMW: x%04x = x%04x -> x%04x\n", addr, tmp, tmp2)); 2177 } break; 2178 case SRDS_CORE_RAM_READ_BYTE: { 2179 if (data > 1) { 2180 uint8_t i; 2181 EFUN_PRINTF(("\n**** SERDES BLK CORE RAM READ BYTE ****")); 2182 for (i = 0; i < (uint8_t)data; i++) { 2183 if (!(i % 26)) 2184 ESTM_PRINTF(("\n%04x ", i + (uint8_t)addr)); 2185 ESTM_PRINTF(("%02x ", eagle_tsc_rdbc_uc_var( pa, __ERR, i + (uint8_t)addr))); 2186 } 2187 EFUN_PRINTF(("\n")); 2188 } else 2189 ESTM_PRINTF(("Core RAM Read byte: x%04x = x%02x\n", (uint8_t)addr, eagle_tsc_rdbc_uc_var( pa, __ERR, (uint8_t)addr))); 2190 } break; 2191 case SRDS_LANE_RAM_READ_BYTE: { 2192 if (data > 1) { 2193 uint16_t i; 2194 EFUN_PRINTF(("\n**** SERDES BLK LANE RAM READ BYTE ****")); 2195 for (i = 0; i < data; i++) { 2196 if (!(i % 26)) 2197 ESTM_PRINTF(("\n%04x ", i + addr)); 2198 ESTM_PRINTF(("%02x ", eagle_tsc_rdbl_uc_var( pa, __ERR, i + addr))); 2199 } 2200 EFUN_PRINTF(("\n")); 2201 } else 2202 ESTM_PRINTF(("Lane RAM Read byte: x%04x = x%02x\n", addr, eagle_tsc_rdbl_uc_var( pa, __ERR, addr))); 2203 } break; 2204 case SRDS_CORE_RAM_READ_WORD: { 2205 if (data > 1) { 2206 uint8_t i; 2207 EFUN_PRINTF(("\n**** SERDES BLK CORE RAM READ WORD ****")); 2208 for (i = 0; i < (uint8_t)data; i += 2) { 2209 if (!(i % 16)) 2210 ESTM_PRINTF(("\n%04x ", i + (uint8_t)addr)); 2211 ESTM_PRINTF(("%04x ", eagle_tsc_rdwc_uc_var( pa, __ERR, i + (uint8_t)addr))); 2212 } 2213 EFUN_PRINTF(("\n")); 2214 } else 2215 ESTM_PRINTF(("Core RAM Read word: x%04x = x%04x\n", addr, eagle_tsc_rdwc_uc_var( pa, __ERR, (uint8_t)addr))); 2216 } break; 2217 case SRDS_LANE_RAM_READ_WORD: { 2218 if (data > 1) { 2219 uint16_t i; 2220 EFUN_PRINTF(("\n**** SERDES BLK LANE RAM READ WORD ****")); 2221 for (i = 0; i < data; i += 2) { 2222 if (!(i % 16)) 2223 ESTM_PRINTF(("\n%04x ", i = i + addr)); 2224 ESTM_PRINTF(("%04x ", eagle_tsc_rdwl_uc_var( pa, __ERR, i + addr))); 2225 } 2226 EFUN_PRINTF(("\n")); 2227 } else 2228 ESTM_PRINTF(("Lane RAM Read word: x%04x = x%04x\n", addr, eagle_tsc_rdwl_uc_var( pa, __ERR, addr))); 2229 } break; 2230 case SRDS_CORE_RAM_RMW_BYTE: { 2231 uint8_t tmp, tmp2; 2232 ESTM(tmp = eagle_tsc_rdbc_uc_var( pa, __ERR, (uint8_t)addr)); 2233 tmp2 = (tmp & (uint8_t) ~param) | ((uint8_t)param & data); 2234 EFUN(eagle_tsc_wrbc_uc_var( pa, (uint8_t)addr, tmp2)); 2235 EFUN_PRINTF(("Core RAM RMW byte: x%04x = x%02x -> x%02x\n", addr, tmp, tmp2)); 2236 } break; 2237 case SRDS_LANE_RAM_RMW_BYTE: { 2238 uint8_t tmp, tmp2; 2239 ESTM(tmp = eagle_tsc_rdbl_uc_var( pa, __ERR, addr)); 2240 tmp2 = (tmp & (uint8_t) ~param) | ((uint8_t)param & data); 2241 EFUN(eagle_tsc_wrbl_uc_var( pa, addr, tmp2)); 2242 EFUN_PRINTF(("Lane RAM RMW byte: x%04x = x%02x -> x%02x\n", addr, tmp, tmp2)); 2243 } break; 2244 case SRDS_CORE_RAM_RMW_WORD: { 2245 uint16_t tmp, tmp2; 2246 ESTM(tmp = eagle_tsc_rdwc_uc_var( pa, __ERR, (uint8_t)addr)); 2247 tmp2 = (tmp & ~param) | (param & data); 2248 EFUN(eagle_tsc_wrwc_uc_var( pa, (uint8_t)addr, tmp2)); 2249 EFUN_PRINTF(("Core RAM RMW word: x%04x = x%04x -> x%04x\n", addr, tmp, tmp2)); 2250 } break; 2251 case SRDS_LANE_RAM_RMW_WORD: { 2252 uint16_t tmp, tmp2; 2253 ESTM(tmp = eagle_tsc_rdwl_uc_var( pa, __ERR, addr)); 2254 tmp2 = (tmp & ~param) | (param & data); 2255 EFUN(eagle_tsc_wrwl_uc_var( pa, addr, tmp2)); 2256 EFUN_PRINTF(("Lane RAM RMW word: x%04x = x%04x -> x%04x\n", addr, tmp, tmp2)); 2257 } break; 2258 case SRDS_GLOB_RAM_READ_BYTE: { 2259 if (data > 1) { 2260 uint16_t i; 2261 EFUN_PRINTF(("\n**** SERDES BLK GLOB RAM READ BYTE ****")); 2262 for (i = 0; i < data; i++) { 2263 if (!(i % 16)) 2264 ESTM_PRINTF(("\n%04x ", i + addr)); 2265 ESTM_PRINTF(("%02x ", _eagle_tsc_rdb_uc_var( pa, __ERR, i + addr))); 2266 } 2267 EFUN_PRINTF(("\n")); 2268 } else 2269 ESTM_PRINTF(("Glob RAM Read byte: x%04x = x%02x\n", addr, _eagle_tsc_rdb_uc_var( pa, __ERR, addr))); 2270 } break; 2271 case SRDS_GLOB_RAM_RMW_BYTE: { 2272 uint8_t tmp, tmp2; 2273 ESTM(tmp = _eagle_tsc_rdb_uc_var( pa, __ERR, addr)); 2274 tmp2 = (tmp & (uint8_t) ~param) | ((uint8_t)param & data); 2275 EFUN(_eagle_tsc_wrb_uc_var( pa, addr, tmp2)); 2276 EFUN_PRINTF(("Glob RAM RMW byte: x%04x = x%02x -> x%02x\n", addr, tmp, tmp2)); 2277 } break; 2278 case SRDS_GLOB_RAM_READ_WORD: { 2279 if (data > 1) { 2280 uint16_t i; 2281 EFUN_PRINTF(("\n**** SERDES BLK GLOB RAM READ WORD ****")); 2282 for (i = 0; i < data; i += 2) { 2283 if (!(i % 16)) 2284 ESTM_PRINTF(("\n%04x ", i + addr)); 2285 ESTM_PRINTF(("%04x ", _eagle_tsc_rdw_uc_var( pa, __ERR, i + addr))); 2286 } 2287 EFUN_PRINTF(("\n")); 2288 } else 2289 ESTM_PRINTF(("Glob RAM Read word: x%04x = x%04x\n", addr, _eagle_tsc_rdw_uc_var( pa, __ERR, addr))); 2290 } break; 2291 case SRDS_GLOB_RAM_RMW_WORD: { 2292 uint16_t tmp, tmp2; 2293 ESTM(tmp = _eagle_tsc_rdw_uc_var( pa, __ERR, addr)); 2294 tmp2 = (tmp & ~param) | (param & data); 2295 EFUN(_eagle_tsc_wrw_uc_var( pa, addr, tmp2)); 2296 EFUN_PRINTF(("Glob RAM RMW word: x%04x = x%04x -> x%04x\n", addr, tmp, tmp2)); 2297 } break; 2298 case SRDS_UC_CMD: { 2299 uint16_t tmp; 2300 EFUN(eagle_tsc_pmd_uc_cmd_with_data( pa, (enum srds_pmd_uc_cmd_enum)addr, (uint8_t)param, data, 100)); 2301 ESTM(tmp = rd_uc_dsc_data()); 2302 EFUN_PRINTF(("uC Command: cmd=x%02x supp=x%02x data=x%04x returned=x%04x\n", addr, param, data, tmp)); 2303 } break; 2304 case SRDS_BER_PROJ_DATA: { 2305 /* display ber projections for all channels */ 2306 EFUN(_eagle_tsc_display_ber_scan_data( pa, (uint8_t)addr, (uint8_t)data, (uint8_t)(param >> 4))); 2307 } break; 2308 case SRDS_EN_BREAKPOINT: 2309 case SRDS_GOTO_BREAKPOINT: 2310 case SRDS_RD_BREAKPOINT: 2311 case SRDS_DIS_BREAKPOINT: 2312 default: EFUN_PRINTF(("Invalid request type eagle_tsc_diag_access\n")); 2313 } 2314 2315 return ERR_CODE_NONE; 2316 } 2317 2318 /************************/ 2319 /* Serdes API Version */ 2320 /************************/ 2321 2322 err_code_t eagle_tsc_version( const phymod_access_t *pa, uint32_t *api_version){ 2323 2324 if (!api_version) 2325 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 2326 *api_version = 0xA10209; 2327 return ERR_CODE_NONE; 2328 } 2329 2330 2331 /***************************************/ 2332 /* API Function to Read Event Logger */ 2333 /***************************************/ 2334 2335 err_code_t eagle_tsc_read_event_log( const phymod_access_t *pa, uint8_t *trace_mem, enum srds_event_log_display_mode_enum display_mode){ 2336 2337 /* validate input arguments */ 2338 if (trace_mem == NULL || (display_mode >= EVENT_LOG_MODE_MAX)) 2339 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 2340 2341 /* stop writing event log */ 2342 EFUN(eagle_tsc_event_log_stop( pa )); 2343 2344 EFUN(eagle_tsc_event_log_readmem( pa, trace_mem)); 2345 2346 EFUN(eagle_tsc_event_log_display( pa, trace_mem, display_mode)); 2347 2348 return ERR_CODE_NONE; 2349 } 2350 2351 err_code_t eagle_tsc_event_log_stop( const phymod_access_t *pa ){ 2352 2353 2354 EFUN_PRINTF(("\n\n********************************************\n")); 2355 EFUN_PRINTF(( "**** SERDES UC TRACE MEMORY DUMP ***********\n")); 2356 EFUN_PRINTF(( "********************************************\n")); 2357 2358 /* Start Read to stop uC logging and read the word at last event written by uC */ 2359 EFUN(eagle_tsc_pmd_uc_cmd( pa, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_START, 10)); 2360 2361 return ERR_CODE_NONE; 2362 } 2363 2364 err_code_t eagle_tsc_event_log_readmem( const phymod_access_t *pa, uint8_t *trace_mem){ 2365 uint8_t uc_dsc_supp_info; 2366 uint16_t addr = 0, trace_mem_size = 0; 2367 2368 /* validate input arguments */ 2369 if (trace_mem == NULL) return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 2370 2371 ESTM_PRINTF(( "\n DEBUG INFO: trace memory read index = 0x%04x\n", rdcv_trace_mem_rd_idx())); 2372 2373 trace_mem_size = 768; 2374 EFUN_PRINTF((" DEBUG INFO: trace memory size = 0x%04x\n\n", trace_mem_size)); 2375 2376 do { 2377 /* Read Next */ 2378 EFUN(eagle_tsc_pmd_uc_cmd( pa, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_NEXT, 10)); 2379 2380 if (addr >= trace_mem_size) 2381 return ERR_CODE_INVALID_EVENT_LOG_READ; 2382 else 2383 addr++; 2384 2385 ESTM(*(trace_mem++) = (uint8_t)rd_uc_dsc_data()); 2386 ESTM(uc_dsc_supp_info = rd_uc_dsc_supp_info()); 2387 } while (uc_dsc_supp_info != 1); 2388 2389 /* Read Done to resume logging */ 2390 EFUN(eagle_tsc_pmd_uc_cmd( pa, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_DONE, 10)); 2391 2392 return ERR_CODE_NONE; 2393 } 2394 2395 err_code_t eagle_tsc_event_log_display( const phymod_access_t *pa, uint8_t *trace_mem, enum srds_event_log_display_mode_enum display_mode){ 2396 #define MAX_ENTRY_SIZE (7) 2397 #define NOR_ENTRY_SIZE (4) 2398 uint16_t trace_mem_size = 0; 2399 uint8_t num_lanes = 0; 2400 uint8_t is_ref_time_found = 0, is_last_event_timewrap = 0; 2401 uint8_t post_cursor = 0, curr_cursor = 0, prev_cursor = 0; 2402 uint16_t addr = 0, rr = 0, prev_rr = 0; 2403 uint8_t cc = 0; 2404 uint16_t time = 0, ref_time = 0, num_time_wraparound = 0, this_num_time_wraparound = 0; 2405 USR_DOUBLE prev_time = 0, curr_time = 0; 2406 uint8_t word_per_row = 8; 2407 uint8_t prev_event = 0; 2408 uint8_t supp_info[MAX_ENTRY_SIZE - NOR_ENTRY_SIZE]; 2409 char uc_lane_id_str[256]; 2410 uint8_t char_0 = '0'; 2411 2412 /* validate input arguments */ 2413 if (trace_mem == NULL || (display_mode >= EVENT_LOG_MODE_MAX)) 2414 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 2415 2416 trace_mem_size = 768; 2417 num_lanes = 4; 2418 2419 /* output */ 2420 if (display_mode == EVENT_LOG_HEX || display_mode == EVENT_LOG_HEX_AND_DECODED) { 2421 /* print the 16-bit words in Hex format to screen, 8 words per row */ 2422 for (rr = 0; rr < trace_mem_size; rr += (2 * word_per_row)) { 2423 for (cc = 0; cc < 2 * word_per_row; cc += 2) 2424 EFUN_PRINTF((" 0x%02x%02x", *(trace_mem + rr + cc), *(trace_mem + rr + cc + 1))); 2425 EFUN_PRINTF((" %d\n", rr)); 2426 } 2427 } 2428 if (display_mode == EVENT_LOG_DECODED || display_mode == EVENT_LOG_HEX_AND_DECODED) { 2429 /* decode for level 1 events */ 2430 2431 /* print a text log of the events going backwards in time, showing time as T-10.340ms, where T is when the Start Read happened. */ 2432 addr = 0; 2433 while (addr < trace_mem_size - 8) { /* last 8-byte reserved for trace memory wraparound */ 2434 2435 if (*(trace_mem + addr) == 0x0) { /* reach event log end */ 2436 EFUN_PRINTF(("\n========== End of Event Log ==================\n")); 2437 break; 2438 } 2439 2440 if (*(trace_mem + addr) == 0xff) { /* timestamp wraparound event handling */ 2441 2442 this_num_time_wraparound = *(trace_mem + (++addr)); 2443 this_num_time_wraparound = ((this_num_time_wraparound << 8) | *(trace_mem + (++addr))); 2444 num_time_wraparound += this_num_time_wraparound; 2445 2446 if (!is_last_event_timewrap) { /* display the rest of previous event info */ 2447 EFUN_PRINTF((",")); 2448 EFUN(_display_event( pa, prev_event, (uint8_t)prev_rr, prev_cursor, curr_cursor, post_cursor, supp_info)); 2449 is_last_event_timewrap = 1; 2450 } 2451 2452 EFUN_PRINTF(("\n %5d timestamp wraparound(s). \n\n", this_num_time_wraparound)); 2453 this_num_time_wraparound = 0; 2454 2455 addr++; 2456 continue; 2457 }else { 2458 cc = (trace_mem[addr] & 0x1f); /* lane id */ 2459 if (cc >= num_lanes) { 2460 EFUN_PRINTF(("\n\n Incorrect lane ID. Terminating event log display for current core... \n\n")); 2461 break; 2462 } 2463 2464 rr = (uint16_t)((trace_mem[addr] >> 5) & 0x7); /* determine event entry length */ 2465 if (rr > MAX_ENTRY_SIZE) return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 2466 2467 time = *(trace_mem + (++addr)); /* timestamp */ 2468 time = ((time << 8) | *(trace_mem + (++addr))); 2469 if (is_ref_time_found == 0) { /* determine the reference time origin */ 2470 is_ref_time_found = 1; 2471 ref_time = time; 2472 }else { 2473 #ifdef SERDES_API_FLOATING_POINT 2474 curr_time = (time - ref_time - (num_time_wraparound * 65536)) / 100.0; 2475 #else 2476 curr_time = (time - ref_time - (num_time_wraparound * 65536)) / 100; 2477 #endif 2478 if (!is_last_event_timewrap) { 2479 #ifdef SERDES_API_FLOATING_POINT 2480 EFUN_PRINTF((" (+%.2f),", prev_time - curr_time)); 2481 #else 2482 EFUN_PRINTF((" (+%d),", prev_time - curr_time)); 2483 #endif 2484 EFUN(_display_event( pa, prev_event, (uint8_t)prev_rr, prev_cursor, curr_cursor, post_cursor, supp_info)); 2485 }else 2486 is_last_event_timewrap = 0; 2487 } 2488 2489 if (cc < 10) { 2490 uc_lane_id_str[0] = char_0 + cc; 2491 uc_lane_id_str[1] = '\0'; 2492 } else if (cc < 100) { 2493 uc_lane_id_str[0] = char_0 + (cc / 10); 2494 uc_lane_id_str[1] = char_0 + (cc % 10); 2495 uc_lane_id_str[2] = '\0'; 2496 } else { 2497 uc_lane_id_str[0] = char_0 + (cc / 100); 2498 uc_lane_id_str[1] = char_0 + ((cc % 100) - (cc % 10)) / 10; 2499 uc_lane_id_str[2] = char_0 + (cc % 10); 2500 uc_lane_id_str[3] = '\0'; 2501 } 2502 2503 EFUN(eagle_tsc_uc_lane_idx_to_system_id(uc_lane_id_str, cc)); 2504 EFUN_PRINTF((" Lane %s: ", uc_lane_id_str)); 2505 #ifdef SERDES_API_FLOATING_POINT 2506 EFUN_PRINTF((" t= %.2f ms", curr_time)); 2507 #else 2508 EFUN_PRINTF((" t= %d ms", curr_time)); 2509 #endif 2510 prev_time = curr_time; 2511 prev_rr = rr; 2512 2513 prev_event = *(trace_mem + (++addr)); 2514 switch (prev_event) { 2515 case EVENT_CODE_CL72_READY_FOR_COMMAND: 2516 case EVENT_CODE_EACH_WRITE_TO_CL72_TX_CHANGE_REQUEST: 2517 case EVENT_CODE_CL72_LOCAL_TX_CHANGED: 2518 if (rr != NOR_ENTRY_SIZE) { 2519 post_cursor = (*(trace_mem + (++addr)) & 0x30) >> 4; 2520 curr_cursor = (*(trace_mem + addr) & 0x0C) >> 2; 2521 prev_cursor = *(trace_mem + addr) & 0x03; 2522 addr--; /* rewind to populate supplement info */ 2523 } 2524 break; 2525 case EVENT_CODE_GENERAL_EVENT_0: 2526 case EVENT_CODE_GENERAL_EVENT_1: 2527 case EVENT_CODE_GENERAL_EVENT_2: 2528 post_cursor = *(trace_mem + (++addr)); 2529 prev_cursor = *(trace_mem + (++addr)); 2530 addr -= 2; /* rewind to populate supplement info */ 2531 break; 2532 case EVENT_CODE_ERROR_EVENT: 2533 post_cursor = *(trace_mem + (++addr)); 2534 addr--; 2535 break; 2536 case EVENT_CODE_SM_STATUS_RESTART: 2537 post_cursor = *(trace_mem + (++addr)); 2538 addr--; 2539 break; 2540 default: 2541 break; 2542 } 2543 2544 /* retrieve supplement info, if any */ 2545 for (cc = 0; cc < rr - NOR_ENTRY_SIZE; cc++) 2546 supp_info[cc] = *(trace_mem + (++addr)); 2547 2548 addr++; 2549 } 2550 } 2551 } 2552 2553 return ERR_CODE_NONE; 2554 } 2555 2556 2557 err_code_t eagle_tsc_display_state( const phymod_access_t *pa ){ 2558 EFUN(eagle_tsc_display_core_state( pa )); 2559 EFUN(eagle_tsc_display_lane_state_hdr( pa )); 2560 EFUN(eagle_tsc_display_lane_state( pa )); 2561 EFUN(eagle_tsc_display_lane_state_legend( pa )); 2562 return ERR_CODE_NONE; 2563 } 2564 2565 err_code_t eagle_tsc_display_config( const phymod_access_t *pa ){ 2566 EFUN(eagle_tsc_display_core_config( pa )); 2567 EFUN(eagle_tsc_display_lane_config( pa )); 2568 return ERR_CODE_NONE; 2569 } 2570 2571 2572 /**********************************************/ 2573 /* Temperature forcing and reading */ 2574 /**********************************************/ 2575 2576 err_code_t eagle_tsc_force_die_temperature( const phymod_access_t *pa, int16_t die_temp){ 2577 /* Formula for PVTMON: T = 410.04-0.48705*reg10bit (from PVTMON Analog Module Specification v5.0 section 6.2) */ 2578 int32_t die_temp_int; 2579 2580 if (die_temp > 130) 2581 die_temp = 130; 2582 if (die_temp < -45) 2583 die_temp = -45; 2584 2585 die_temp_int = (int32_t)die_temp; 2586 EFUN(wrcv_temp_frc_val((uint16_t)((431045 - ((die_temp_int << 10) + (die_temp_int << 4) + (die_temp_int << 3) + (die_temp_int << 1) + die_temp_int)) >> 9))); 2587 2588 return ERR_CODE_NONE; 2589 } 2590 2591 err_code_t eagle_tsc_read_die_temperature( const phymod_access_t *pa, int16_t *die_temp){ 2592 2593 uint16_t die_temp_sensor_reading; 2594 2595 EFUN(eagle_tsc_pmd_uc_cmd( pa, CMD_UC_DBG, CMD_UC_DBG_DIE_TEMP, 50)); 2596 ESTM(die_temp_sensor_reading = rd_uc_dsc_data()); 2597 *die_temp = _bin_to_degC(die_temp_sensor_reading); 2598 2599 return ERR_CODE_NONE; 2600 } 2601 2602 2603 err_code_t eagle_tsc_read_die_temperature_double(const phymod_access_t *pa, USR_DOUBLE *die_temp){ 2604 #ifdef SERDES_API_FLOATING_POINT 2605 /* Formula for PVTMON: T = 410.04-0.48705*reg10bit (from PVTMON Analog Module Specification v5.0 section 6.2) */ 2606 uint16_t die_temp_sensor_reading; 2607 2608 EFUN(eagle_tsc_pmd_uc_cmd( pa, CMD_UC_DBG, CMD_UC_DBG_DIE_TEMP, 50)); 2609 ESTM(die_temp_sensor_reading = rd_uc_dsc_data()); 2610 2611 *die_temp = 410.04 - 0.48705 * ((USR_DOUBLE)die_temp_sensor_reading); 2612 2613 return ERR_CODE_NONE; 2614 #else 2615 EFUN_PRINTF((" Function 'eagle_tsc_read_die_temperature_double' needs SERDES_API_FLOATING_POINT defined to operate \n")); 2616 return _error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 2617 #endif 2618 } 2619 2620 2621 2622