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