merlin16_pcieg3_internal.c (52012B)
1 /*********************************************************************************** 2 *********************************************************************************** 3 * File Name : merlin16_pcieg3_internal.c * 4 * Created On : 13/02/2014 * 5 * Created By : Justin Gaither * 6 * Description : APIs for Serdes IPs * 7 * Revision : * 8 * * 9 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 10 * 11 * Copyright 2007-2019 Broadcom Inc. All rights reserved. * 12 * No portions of this material may be reproduced in any form without * 13 * the written permission of: * 14 * Broadcom Corporation * 15 * 5300 California Avenue * 16 * Irvine, CA 92617 * 17 * * 18 * All information contained in this document is Broadcom Corporation * 19 * company private proprietary, and trade secret. * 20 */ 21 22 /** @file merlin16_pcieg3_internal.c 23 * Implementation of API functions 24 */ 25 26 #include "merlin16_pcieg3_internal.h" 27 #include "merlin16_pcieg3_internal_error.h" 28 #include "merlin16_pcieg3_access.h" 29 #include "merlin16_pcieg3_common.h" 30 #include "merlin16_pcieg3_config.h" 31 #include "merlin16_pcieg3_functions.h" 32 #include "merlin16_pcieg3_select_defns.h" 33 #include "merlin16_pcieg3_prbs.h" 34 35 #ifndef UINT16_MAX 36 #define UINT16_MAX (65535U) 37 #endif 38 39 /* If SERDES_EVAL is defined, then is_ate_log_enabled() is queried to *\ 40 \* know whether to log ATE. merlin16_pcieg3_access.h provides that function. */ 41 42 43 static merlin16_pcieg3_info_t merlin16_pcieg3_info; 44 45 merlin16_pcieg3_info_t *merlin16_pcieg3_INTERNAL_get_merlin16_pcieg3_info_ptr(void) { 46 return &merlin16_pcieg3_info; 47 } 48 49 err_code_t merlin16_pcieg3_INTERNAL_verify_merlin16_pcieg3_info(merlin16_pcieg3_info_t const *test_info) 50 { 51 if (test_info->signature != SRDS_INFO_SIGNATURE) { 52 EFUN_PRINTF(("ERROR: Mismatch in merlin16_pcieg3_info signature. Expected 0x%08X, but received 0x%08X.\n", 53 SRDS_INFO_SIGNATURE, test_info->signature)); 54 return (_error(ERR_CODE_INFO_TABLE_ERROR)); 55 } 56 return (ERR_CODE_NONE); 57 } 58 59 /* Store a cached AFE version for re-use */ 60 err_code_t merlin16_pcieg3_INTERNAL_get_afe_hw_version(srds_access_t *sa__, uint8_t *afe_hw_version) { 61 static uint8_t _cached_afe_hw_version = 255; 62 63 if (!afe_hw_version) 64 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 65 if (_cached_afe_hw_version == 255) 66 ESTM(_cached_afe_hw_version = rdcv_afe_hardware_version()); 67 *afe_hw_version = _cached_afe_hw_version; 68 return(ERR_CODE_NONE); 69 } 70 71 int merlin16_pcieg3_osr_mode_enum_to_int_x1000(uint8_t osr_mode) { 72 switch(osr_mode) { 73 case MERLIN16_PCIEG3_OSX1: return 1000; 74 case MERLIN16_PCIEG3_OSX2: return 2000; 75 case MERLIN16_PCIEG3_OSX4: return 4000; 76 case MERLIN16_PCIEG3_OSX3: return 3000; 77 case MERLIN16_PCIEG3_OSX3P3: return 3300; 78 case MERLIN16_PCIEG3_OSX5: return 5000; 79 case MERLIN16_PCIEG3_OSX7P5: return 7500; 80 case MERLIN16_PCIEG3_OSX8P25: return 8250; 81 case MERLIN16_PCIEG3_OSX10: return 10000; 82 case MERLIN16_PCIEG3_OSX8: return 8000; 83 default: return 1000; 84 } 85 } 86 87 err_code_t merlin16_pcieg3_INTERNAL_get_num_bits_per_ms(srds_access_t *sa__, uint32_t *num_bits_per_ms) { 88 uint8_t osr_mode = 0; 89 #if defined(rd_rx_pam4_mode) 90 uint8_t pam4_mode = 0; 91 #endif 92 struct merlin16_pcieg3_uc_core_config_st core_config = {{0}}; 93 94 ESTM(osr_mode = rd_rx_osr_mode()); 95 96 #if defined(rd_rx_pam4_mode) 97 ESTM(pam4_mode = rd_rx_pam4_mode()); 98 #endif 99 100 *num_bits_per_ms = (((uint32_t)core_config.vco_rate_in_Mhz * 100000UL) / merlin16_pcieg3_osr_mode_enum_to_int_x1000(osr_mode))*10; 101 102 #if defined(rd_rx_pam4_mode) 103 if(pam4_mode > 0) *num_bits_per_ms <<= 1; 104 #endif 105 return(ERR_CODE_NONE); 106 } 107 108 err_code_t merlin16_pcieg3_INTERNAL_display_BER(srds_access_t *sa__, uint16_t time_ms) { 109 char string[10]; 110 EFUN(merlin16_pcieg3_INTERNAL_get_BER_string(sa__,time_ms,string)); 111 USR_PRINTF(("%s",string)); 112 return(ERR_CODE_NONE); 113 } 114 115 err_code_t merlin16_pcieg3_INTERNAL_get_BER_string(srds_access_t *sa__, uint16_t time_ms, char *string) { 116 char string2[3]; 117 struct ber_data_st ber_data = {0, 0, 0, 0}; 118 119 if(string == NULL) { 120 return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 121 } 122 123 EFUN(merlin16_pcieg3_INTERNAL_get_BER_data(sa__, time_ms, &ber_data)); 124 125 if(ber_data.prbs_chk_en == 0) { 126 USR_STRCPY(string,""); 127 return(ERR_CODE_NONE); 128 } else { 129 USR_STRCPY(string2," "); 130 } 131 132 if((ber_data.num_errs < 3) && (ber_data.lcklost == 0)) { /* lcklost = 0 */ 133 USR_STRNCAT(string2,"<",1); 134 ber_data.num_errs = 3; 135 } else { 136 USR_STRNCAT(string2," ",1); 137 } 138 if(ber_data.lcklost == 1) { /* lcklost = 1 */ 139 USR_STRCPY(string," !Lock "); 140 } else { /* lcklost = 0 */ 141 uint16_t x=0,y=0,z=0,div; 142 143 if(ber_data.num_errs >= ber_data.num_bits) { 144 x = 1;y=0;z=0; 145 }else { 146 while(1) { 147 div = (uint16_t)(((ber_data.num_errs<<1) + ber_data.num_bits)/(ber_data.num_bits<<1)); 148 if(div>=10) break; 149 ber_data.num_errs = ber_data.num_errs*10; 150 z=z+1; 151 } 152 if(div>=100) { 153 div = div/10; 154 z=z-1; 155 } 156 x=div/10; 157 y = div - 10*x; 158 z=z-1; 159 USR_SPRINTF((string,"%s%d.%1de-%02d",string2,x,y,z)); 160 } 161 162 } 163 return(ERR_CODE_NONE); 164 165 } 166 167 err_code_t merlin16_pcieg3_INTERNAL_get_BER_data(srds_access_t *sa__, uint16_t time_ms, struct ber_data_st *ber_data) { 168 uint8_t lcklost = 0; 169 uint32_t err_cnt= 0; 170 171 if(ber_data == NULL) { 172 return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 173 } 174 175 ESTM(ber_data->prbs_chk_en = rd_prbs_chk_en()); 176 if(ber_data->prbs_chk_en == 0) 177 return(ERR_CODE_NONE); 178 179 EFUN(merlin16_pcieg3_prbs_err_count_state(sa__, &err_cnt,&lcklost)); /* clear error counters */ 180 EFUN(USR_DELAY_MS(time_ms)); 181 EFUN(merlin16_pcieg3_prbs_err_count_state(sa__, &err_cnt,&lcklost)); 182 183 ber_data->lcklost = lcklost; 184 185 if(ber_data->lcklost == 0) { 186 uint32_t num_bits_per_ms=0; 187 188 EFUN(merlin16_pcieg3_INTERNAL_get_num_bits_per_ms(sa__,&num_bits_per_ms)); 189 190 ber_data->num_errs = err_cnt; 191 ber_data->num_bits = (uint64_t)num_bits_per_ms*(uint64_t)time_ms; 192 } 193 return(ERR_CODE_NONE); 194 195 } 196 197 198 err_code_t merlin16_pcieg3_INTERNAL_get_p1_threshold(srds_access_t *sa__, int8_t *val) { 199 ESTM(*val = -rd_p1_eyediag_bin()); 200 return (ERR_CODE_NONE); 201 } 202 203 204 int16_t merlin16_pcieg3_INTERNAL_ladder_setting_to_mV(srds_access_t *sa__, int8_t ctrl, uint8_t range_250) { 205 uint16_t absv; /* Absolute value of ctrl */ 206 int16_t nlmv; /* Non-linear value */ 207 208 /* Get absolute value */ 209 absv = SRDS_ABS(ctrl); 210 211 { 212 if (range_250) { 213 /* 28nm range is 250mV, but 16nm range is 200mV */ 214 /* 200mV range, 6.5519mV linear units */ 215 nlmv = absv*190/29; 216 } 217 else { 218 /* 120mV range, 3.8854mV linear units */ 219 nlmv = absv*136/35; 220 } 221 } 222 /* Add sign and return */ 223 return( (ctrl>=0) ? nlmv : -nlmv); 224 } 225 226 227 err_code_t merlin16_pcieg3_INTERNAL_compute_bin(char var, char bin[]) { 228 if(!bin) { 229 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 230 } 231 232 switch (var) { 233 case '0': ENULL_STRCPY(bin,"0000"); 234 break; 235 case '1': ENULL_STRCPY(bin,"0001"); 236 break; 237 case '2': ENULL_STRCPY(bin,"0010"); 238 break; 239 case '3': ENULL_STRCPY(bin,"0011"); 240 break; 241 case '4': ENULL_STRCPY(bin,"0100"); 242 break; 243 case '5': ENULL_STRCPY(bin,"0101"); 244 break; 245 case '6': ENULL_STRCPY(bin,"0110"); 246 break; 247 case '7': ENULL_STRCPY(bin,"0111"); 248 break; 249 case '8': ENULL_STRCPY(bin,"1000"); 250 break; 251 case '9': ENULL_STRCPY(bin,"1001"); 252 break; 253 case 'a': 254 case 'A': ENULL_STRCPY(bin,"1010"); 255 break; 256 case 'b': 257 case 'B': ENULL_STRCPY(bin,"1011"); 258 break; 259 case 'c': 260 case 'C': ENULL_STRCPY(bin,"1100"); 261 break; 262 case 'd': 263 case 'D': ENULL_STRCPY(bin,"1101"); 264 break; 265 case 'e': 266 case 'E': ENULL_STRCPY(bin,"1110"); 267 break; 268 case 'f': 269 case 'F': ENULL_STRCPY(bin,"1111"); 270 break; 271 case '_': ENULL_STRCPY(bin,""); 272 break; 273 default : ENULL_STRCPY(bin,""); 274 EFUN_PRINTF(("ERROR: Invalid Hexadecimal Pattern\n")); 275 return (_error(ERR_CODE_CFG_PATT_INVALID_HEX)); 276 } 277 return (ERR_CODE_NONE); 278 } 279 280 281 err_code_t merlin16_pcieg3_INTERNAL_compute_hex(char bin[],uint8_t *hex) { 282 if(!hex) { 283 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 284 } 285 286 if (!USR_STRCMP(bin,"0000")) { 287 *hex = 0x0; 288 } 289 else if (!USR_STRCMP(bin,"0001")) { 290 *hex = 0x1; 291 } 292 else if (!USR_STRCMP(bin,"0010")) { 293 *hex = 0x2; 294 } 295 else if (!USR_STRCMP(bin,"0011")) { 296 *hex = 0x3; 297 } 298 else if (!USR_STRCMP(bin,"0100")) { 299 *hex = 0x4; 300 } 301 else if (!USR_STRCMP(bin,"0101")) { 302 *hex = 0x5; 303 } 304 else if (!USR_STRCMP(bin,"0110")) { 305 *hex = 0x6; 306 } 307 else if (!USR_STRCMP(bin,"0111")) { 308 *hex = 0x7; 309 } 310 else if (!USR_STRCMP(bin,"1000")) { 311 *hex = 0x8; 312 } 313 else if (!USR_STRCMP(bin,"1001")) { 314 *hex = 0x9; 315 } 316 else if (!USR_STRCMP(bin,"1010")) { 317 *hex = 0xA; 318 } 319 else if (!USR_STRCMP(bin,"1011")) { 320 *hex = 0xB; 321 } 322 else if (!USR_STRCMP(bin,"1100")) { 323 *hex = 0xC; 324 } 325 else if (!USR_STRCMP(bin,"1101")) { 326 *hex = 0xD; 327 } 328 else if (!USR_STRCMP(bin,"1110")) { 329 *hex = 0xE; 330 } 331 else if (!USR_STRCMP(bin,"1111")) { 332 *hex = 0xF; 333 } 334 else { 335 EFUN_PRINTF(("ERROR: Invalid Binary to Hex Conversion\n")); 336 *hex = 0x0; 337 return (_error(ERR_CODE_CFG_PATT_INVALID_BIN2HEX)); 338 } 339 return (ERR_CODE_NONE); 340 } 341 342 uint8_t merlin16_pcieg3_INTERNAL_stop_micro(srds_access_t *sa__, uint8_t graceful, err_code_t *err_code_p) { 343 uint8_t stop_state = 0; 344 345 if(!err_code_p) { 346 return(0xFF); 347 } 348 349 /* Log current micro stop status */ 350 EPSTM2((stop_state = rdv_usr_sts_micro_stopped()),0xFF); 351 352 if(graceful) { 353 if (!(stop_state & 0x7F)) { 354 EPFUN2((merlin16_pcieg3_stop_rx_adaptation(sa__, 1)),0xFF); 355 } 356 } else { 357 EPFUN2((merlin16_pcieg3_pmd_uc_control(sa__, CMD_UC_CTRL_STOP_IMMEDIATE,GRACEFUL_STOP_TIME)),0xFF); 358 } 359 360 /* Return the previous micro stop status */ 361 return(stop_state); 362 } 363 364 365 366 367 /********************************************************/ 368 /* Global RAM access through Micro Register Interface */ 369 /********************************************************/ 370 /* Micro Global RAM Byte Read */ 371 uint8_t merlin16_pcieg3_INTERNAL_rdb_uc_var(srds_access_t *sa__, err_code_t *err_code_p, uint16_t addr) { 372 uint8_t rddata; 373 374 if(!err_code_p) { 375 return(0); 376 } 377 EPSTM(rddata = merlin16_pcieg3_rdb_uc_ram(sa__, err_code_p, addr)); /* Use Micro register interface for reading RAM */ 378 return (rddata); 379 } 380 381 /* Micro Global RAM Word Read */ 382 uint16_t merlin16_pcieg3_INTERNAL_rdw_uc_var(srds_access_t *sa__, err_code_t *err_code_p, uint16_t addr) { 383 uint16_t rddata; 384 385 if(!err_code_p) { 386 return(0); 387 } 388 if (addr%2 != 0) { /* Validate even address */ 389 *err_code_p = ERR_CODE_INVALID_RAM_ADDR; 390 USR_PRINTF(("Error incorrect addr x%04x\n",addr)); 391 return (0); 392 } 393 EPSTM(rddata = merlin16_pcieg3_rdw_uc_ram(sa__, err_code_p, (addr))); /* Use Micro register interface for reading RAM */ 394 return (rddata); 395 } 396 397 /* Micro Global RAM Byte Write */ 398 err_code_t merlin16_pcieg3_INTERNAL_wrb_uc_var(srds_access_t *sa__, uint16_t addr, uint8_t wr_val) { 399 400 return (merlin16_pcieg3_wrb_uc_ram(sa__, addr, wr_val)); /* Use Micro register interface for writing RAM */ 401 } 402 403 /* Micro Global RAM Word Write */ 404 err_code_t merlin16_pcieg3_INTERNAL_wrw_uc_var(srds_access_t *sa__, uint16_t addr, uint16_t wr_val) { 405 if (addr%2 != 0) { /* Validate even address */ 406 USR_PRINTF(("Error incorrect addr x%04x\n",addr)); 407 return (_error(ERR_CODE_INVALID_RAM_ADDR)); 408 } 409 return (merlin16_pcieg3_wrw_uc_ram(sa__, addr, wr_val)); /* Use Micro register interface for writing RAM */ 410 } 411 412 413 /***********************/ 414 /* Event Log Display */ 415 /***********************/ 416 err_code_t merlin16_pcieg3_INTERNAL_event_log_dump_callback(void *arg, uint8_t byte_count, uint16_t data) { 417 merlin16_pcieg3_INTERNAL_event_log_dump_state_t * const state_ptr = (merlin16_pcieg3_INTERNAL_event_log_dump_state_t *)arg; 418 const uint8_t bytes_per_row=16; 419 420 if (byte_count == 0) { 421 if (state_ptr->line_start_index != state_ptr->index) { 422 EFUN_PRINTF(("%*s %d\n", 4*(bytes_per_row - state_ptr->index + state_ptr->line_start_index), "", state_ptr->line_start_index)); 423 } 424 return (ERR_CODE_NONE); 425 } 426 if (byte_count == 1) { 427 /* There is a trailing byte in the event log. 428 * The simplest way to handle it is to print out a whole word, but mask 429 * the invalid upper byte. 430 */ 431 data &= 0xFF; 432 } 433 EFUN_PRINTF((" 0x%04x", ((data & 0xFF) << 8) | (data >> 8))); 434 state_ptr->index += 2; 435 if (state_ptr->index % bytes_per_row == 0) { 436 EFUN_PRINTF((" %d\n", state_ptr->line_start_index)); 437 state_ptr->line_start_index = state_ptr->index; 438 } 439 440 return(ERR_CODE_NONE); 441 } 442 443 err_code_t merlin16_pcieg3_INTERNAL_read_event_log_with_callback(srds_access_t *sa__, 444 uint8_t micro_num, 445 uint8_t bypass_micro, 446 void *arg, 447 err_code_t (*callback)(void *, uint8_t, uint16_t)) { 448 merlin16_pcieg3_info_t const * const merlin16_pcieg3_info_ptr = merlin16_pcieg3_INTERNAL_get_merlin16_pcieg3_info_ptr(); 449 uint16_t rd_idx; 450 uint8_t current_lane; 451 452 EFUN(merlin16_pcieg3_INTERNAL_verify_merlin16_pcieg3_info(merlin16_pcieg3_info_ptr)); 453 454 if (micro_num >= merlin16_pcieg3_info_ptr->micro_count) { 455 return (_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 456 } 457 /* Read Current lane so that it can be restored at the end of function */ 458 current_lane = merlin16_pcieg3_get_lane(sa__); 459 EFUN_PRINTF(("\n\n********************************************\n")); 460 EFUN_PRINTF(( "**** SERDES UC TRACE MEMORY DUMP ***********\n")); 461 EFUN_PRINTF(( "********************************************\n")); 462 463 if (bypass_micro) { 464 ESTM(rd_idx = rdcv_trace_mem_wr_idx()); 465 if (merlin16_pcieg3_info_ptr->trace_memory_descending_writes) { 466 ++rd_idx; 467 if (rd_idx >= merlin16_pcieg3_info_ptr->trace_mem_ram_size) { 468 rd_idx = 0; 469 } 470 } else { 471 if (rd_idx == 0) { 472 rd_idx = merlin16_pcieg3_info_ptr->trace_mem_ram_size; 473 } 474 --rd_idx; 475 } 476 } else { 477 /* Start Read to stop uC logging and read the word at last event written by uC */ 478 EFUN(merlin16_pcieg3_pmd_uc_cmd(sa__, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_START, GRACEFUL_STOP_TIME)); 479 ESTM(rd_idx = rdcv_trace_mem_rd_idx()); 480 } 481 482 EFUN_PRINTF(( "\n DEBUG INFO: trace memory read index = 0x%04x\n", rd_idx)); 483 484 EFUN_PRINTF((" DEBUG INFO: trace memory size = 0x%04x\n\n", merlin16_pcieg3_info_ptr->trace_mem_ram_size)); 485 486 if (merlin16_pcieg3_info_ptr->trace_memory_descending_writes) { 487 /* Micro writes trace memory using descending addresses. 488 * So read using ascending addresses using block read 489 */ 490 EFUN(merlin16_pcieg3_INTERNAL_rdblk_uc_generic_ram(sa__, 491 merlin16_pcieg3_info_ptr->trace_mem_ram_base + merlin16_pcieg3_info_ptr->grp_ram_size*micro_num, 492 merlin16_pcieg3_info_ptr->trace_mem_ram_size, 493 rd_idx, 494 merlin16_pcieg3_info_ptr->trace_mem_ram_size, 495 arg, 496 callback)); 497 } else { 498 /* Micro writes trace memory using descending addresses. 499 * So read using ascending addresses using block read 500 */ 501 EFUN(merlin16_pcieg3_INTERNAL_rdblk_uc_generic_ram_descending(sa__, 502 merlin16_pcieg3_info_ptr->trace_mem_ram_base + merlin16_pcieg3_info_ptr->grp_ram_size*micro_num, 503 merlin16_pcieg3_info_ptr->trace_mem_ram_size, 504 rd_idx, 505 merlin16_pcieg3_info_ptr->trace_mem_ram_size, 506 arg, 507 callback)); 508 } 509 510 if (!bypass_micro) { 511 /* Read Done to resume logging */ 512 EFUN(merlin16_pcieg3_pmd_uc_cmd(sa__, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_DONE, 50)); 513 } 514 EFUN(merlin16_pcieg3_set_lane(sa__,current_lane)); 515 return(ERR_CODE_NONE); 516 } 517 518 #ifdef TO_FLOATS 519 /* convert uint32_t to float8 */ 520 float8_t merlin16_pcieg3_INTERNAL_int32_to_float8(uint32_t input) { 521 int8_t cnt; 522 uint8_t output; 523 524 if(input == 0) { 525 return(0); 526 } else if(input == 1) { 527 return(0xe0); 528 } else { 529 cnt = 0; 530 input = input & 0x7FFFFFFF; /* get rid of MSB which may be lock indicator */ 531 do { 532 input = input << 1; 533 cnt++; 534 } while ((input & 0x80000000) == 0); 535 536 output = (uint8_t)((input & 0x70000000)>>23)+(31 - cnt%32); 537 return(output); 538 } 539 } 540 #endif 541 542 /* convert float8 to uint32_t */ 543 uint32_t merlin16_pcieg3_INTERNAL_float8_to_int32(float8_t input) { 544 uint32_t x; 545 if(input == 0) return(0); 546 x = (input>>5) + 8; 547 if((input & 0x1F) < 3) { 548 return(x>>(3-(input & 0x1f))); 549 } 550 return(x<<((input & 0x1F)-3)); 551 } 552 553 /* Convert uint8 to 8-bit gray code */ 554 uint8_t merlin16_pcieg3_INTERNAL_uint8_to_gray(uint8_t input) { 555 return input ^ (input >> 1); 556 } 557 558 /* Convert 8-bit gray code to uint8 */ 559 uint8_t merlin16_pcieg3_INTERNAL_gray_to_uint8(uint8_t input) { 560 input = input ^ (input >> 4); 561 input = input ^ (input >> 2); 562 input = input ^ (input >> 1); 563 return input; 564 } 565 566 567 /* convert float12 to uint32 */ 568 uint32_t merlin16_pcieg3_INTERNAL_float12_to_uint32(uint8_t byte, uint8_t multi) { 569 570 return(((uint32_t)byte)<<multi); 571 } 572 573 #ifdef TO_FLOATS 574 /* convert uint32 to float12 */ 575 uint8_t merlin16_pcieg3_INTERNAL_uint32_to_float12(uint32_t input, uint8_t *multi) { 576 int8_t cnt; 577 uint8_t output; 578 if(!multi) { 579 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 580 } 581 582 if((input == 0) || (!multi)) { 583 *multi = 0; 584 return(0); 585 } else { 586 cnt = 0; 587 if(input > 0x007FFFFF) input = 0x007FFFFF; /* limit to 23bits so multi is 4 bits */ 588 do { 589 input = input << 1; 590 cnt++; 591 } while ((input & 0x80000000) == 0); 592 593 *multi = (31 - (cnt%32)); 594 if(*multi < 8) { 595 output = (uint8_t)((input & 0xFF000000)>>(24 + (7-*multi))); 596 *multi = 0; 597 } else { 598 output = (uint8_t)((input & 0xFF000000)>>24); 599 *multi = *multi - 7; 600 } 601 return(output); 602 } 603 } 604 #endif 605 606 err_code_t merlin16_pcieg3_INTERNAL_set_rx_pf_main(srds_access_t *sa__, uint8_t val) { 607 if (val > 15) { 608 return (_error(ERR_CODE_PF_INVALID)); 609 } 610 EFUN(WR_RX_PF_CTRL(val)); 611 return(ERR_CODE_NONE); 612 } 613 614 err_code_t merlin16_pcieg3_INTERNAL_get_rx_pf_main(srds_access_t *sa__, int8_t *val) { 615 ESTM(*val = (int8_t)RD_RX_PF_CTRL()); 616 return (ERR_CODE_NONE); 617 } 618 619 err_code_t merlin16_pcieg3_INTERNAL_set_rx_pf2(srds_access_t *sa__, uint8_t val) { 620 if (val > 7) { 621 return (_error(ERR_CODE_PF_INVALID)); 622 } 623 EFUN(WR_RX_PF2_CTRL(val)); 624 return(ERR_CODE_NONE); 625 } 626 627 err_code_t merlin16_pcieg3_INTERNAL_get_rx_pf2(srds_access_t *sa__, int8_t *val) { 628 ESTM(*val = (int8_t)RD_RX_PF2_CTRL()); 629 return (ERR_CODE_NONE); 630 } 631 632 633 err_code_t merlin16_pcieg3_INTERNAL_set_rx_vga(srds_access_t *sa__, uint8_t val) { 634 635 EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 636 637 if (val > RX_VGA_CTRL_VAL_MAX) { 638 return (_error(ERR_CODE_VGA_INVALID)); 639 } 640 #if defined(RX_VGA_CTRL_VAL_MIN) && (RX_VGA_CTRL_VAL_MIN > 0) 641 if (val < RX_VGA_CTRL_VAL_MIN) { 642 return (_error(ERR_CODE_VGA_INVALID)); 643 } 644 #endif 645 646 { 647 uint8_t rate_sel; 648 ESTM(rate_sel = rd_rate_sel()); 649 if (rate_sel < MERLIN16_PCIEG3_GEN3) { 650 if (val <= 15) { 651 EFUN(wr_rx_vga1_ctrl_G1G2(val)); 652 EFUN(wr_rx_vga2_ctrl_G1G2(0)); 653 EFUN(wr_rx_vga3_ctrl_G1G2(0)); 654 } else if (val <= 30) { 655 EFUN(wr_rx_vga1_ctrl_G1G2(15)); 656 EFUN(wr_rx_vga2_ctrl_G1G2(val-15)); 657 EFUN(wr_rx_vga3_ctrl_G1G2(0)); 658 }else{ 659 EFUN(wr_rx_vga1_ctrl_G1G2(15)); 660 EFUN(wr_rx_vga2_ctrl_G1G2(15)); 661 EFUN(wr_rx_vga3_ctrl_G1G2(val-30)); 662 } 663 } else { 664 EFUN(wr_hwtune_ovr_write_sel(0)); /* Configure hwtune_ovr_write_sel to VGA */ 665 EFUN(wr_hwtune_ovr_write_val(val<<3)); /* hwtune_ovr_write_val[8:3] are used to drive the analog control port */ 666 EFUN(wr_hwtune_ovr_write_en(1)); 667 } 668 } 669 return(ERR_CODE_NONE); 670 } 671 672 err_code_t merlin16_pcieg3_INTERNAL_get_rx_vga(srds_access_t *sa__, int8_t *val) { 673 { 674 uint8_t rate_sel; 675 ESTM(rate_sel = rd_rate_sel()); 676 if (rate_sel < MERLIN16_PCIEG3_GEN3) { 677 ESTM(*val = (int8_t)(rd_rx_vga1_ctrl_G1G2() + rd_rx_vga2_ctrl_G1G2() + rd_rx_vga3_ctrl_G1G2())); 678 } else { 679 ESTM(*val = (int8_t)rd_vga_bin()); 680 } 681 } 682 return (ERR_CODE_NONE); 683 } 684 685 686 err_code_t merlin16_pcieg3_INTERNAL_set_rx_dfe1(srds_access_t *sa__, int8_t val) { 687 688 EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 689 690 { 691 int8_t tap_eo; 692 693 if (val > 63) { 694 return (_error(ERR_CODE_DFE1_INVALID)); 695 } 696 /* Compute tap1 even/odd component */ 697 tap_eo = 0; /* Not supporting dfe_dcd values */ 698 EFUN(wr_hwtune_ovr_write_sel(2)); /* Write tap1_odd */ 699 EFUN(wr_hwtune_ovr_write_val(tap_eo)); 700 EFUN(wr_hwtune_ovr_write_en(1)); 701 EFUN(wr_hwtune_ovr_write_sel(3)); /* Write tap1_even */ 702 EFUN(wr_hwtune_ovr_write_val(tap_eo)); 703 EFUN(wr_hwtune_ovr_write_en(1)); 704 EFUN(wr_hwtune_ovr_write_sel(1)); 705 EFUN(wr_hwtune_ovr_write_val(val-tap_eo)); /* Write the common tap */ 706 EFUN(wr_hwtune_ovr_write_en(1)); 707 } 708 return(ERR_CODE_NONE); 709 } 710 err_code_t merlin16_pcieg3_INTERNAL_get_rx_dfe1(srds_access_t *sa__, int8_t *val) { 711 ESTM(*val = (int8_t)(rd_dfe_1_e() + rd_dfe_1_cmn())); 712 return (ERR_CODE_NONE); 713 } 714 715 716 err_code_t merlin16_pcieg3_INTERNAL_set_rx_dfe2(srds_access_t *sa__, int8_t val) { 717 int8_t tap_eo; 718 719 if ((val > 31) || (val < -31)) { 720 return (_error(ERR_CODE_DFE2_INVALID)); 721 } 722 723 EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 724 725 /* Compute tap2 odd/even component */ 726 tap_eo = 0; /* Not supporting dfe_dcd values */ 727 EFUN(wr_hwtune_ovr_write_sel(5)); /* Write tap2_odd */ 728 EFUN(wr_hwtune_ovr_write_val(tap_eo)); 729 EFUN(wr_hwtune_ovr_write_en(1)); 730 EFUN(wr_hwtune_ovr_write_sel(6)); /* Write tap2_even */ 731 EFUN(wr_hwtune_ovr_write_val(tap_eo)); 732 EFUN(wr_hwtune_ovr_write_en(1)); 733 EFUN(wr_hwtune_ovr_write_sel(4)); 734 EFUN(wr_hwtune_ovr_write_val(SRDS_ABS(val)-tap_eo));/* Write the common tap */ 735 EFUN(wr_hwtune_ovr_write_en(1)); 736 EFUN(wr_hwtune_ovr_write_sel(10)); /* Write tap2_even_sign */ 737 EFUN(wr_hwtune_ovr_write_val(val<0?1:0)); 738 EFUN(wr_hwtune_ovr_write_en(1)); 739 EFUN(wr_hwtune_ovr_write_sel(11)); /* Write tap2_odd_sign */ 740 EFUN(wr_hwtune_ovr_write_val(val<0?1:0)); 741 EFUN(wr_hwtune_ovr_write_en(1)); 742 return(ERR_CODE_NONE); 743 } 744 745 err_code_t merlin16_pcieg3_INTERNAL_get_rx_dfe2(srds_access_t *sa__, int8_t *val) { 746 ESTM(*val = rd_dfe_2_se() ? -(rd_dfe_2_e()+rd_dfe_2_cmn()) : (rd_dfe_2_e()+rd_dfe_2_cmn())); 747 return (ERR_CODE_NONE); 748 } 749 750 err_code_t merlin16_pcieg3_INTERNAL_set_rx_dfe3(srds_access_t *sa__, int8_t val) { 751 if ((val > 31) || (val < -31)) { 752 return (_error(ERR_CODE_DFE3_INVALID)); 753 } 754 755 EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 756 757 EFUN(wr_hwtune_ovr_write_sel(7)); /* Write tap3 */ 758 EFUN(wr_hwtune_ovr_write_val(val)); 759 EFUN(wr_hwtune_ovr_write_en(1)); 760 return(ERR_CODE_NONE); 761 } 762 763 err_code_t merlin16_pcieg3_INTERNAL_get_rx_dfe3(srds_access_t *sa__, int8_t *val) { 764 ESTM(*val = rd_dfe_3_cmn()); 765 return (ERR_CODE_NONE); 766 } 767 768 err_code_t merlin16_pcieg3_INTERNAL_set_rx_dfe4(srds_access_t *sa__, int8_t val) { 769 if ((val > 15) || (val < -15)) { 770 return (_error(ERR_CODE_DFE4_INVALID)); 771 } 772 773 EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 774 775 EFUN(wr_hwtune_ovr_write_sel(8)); /* Write tap4 */ 776 EFUN(wr_hwtune_ovr_write_val(val)); 777 EFUN(wr_hwtune_ovr_write_en(1)); 778 return(ERR_CODE_NONE); 779 } 780 781 err_code_t merlin16_pcieg3_INTERNAL_get_rx_dfe4(srds_access_t *sa__, int8_t *val) { 782 ESTM(*val = rd_dfe_4_cmn()); 783 return (ERR_CODE_NONE); 784 } 785 786 err_code_t merlin16_pcieg3_INTERNAL_set_rx_dfe5(srds_access_t *sa__, int8_t val) { 787 if ((val > 15) || (val < -15)) { 788 return (_error(ERR_CODE_DFE5_INVALID)); 789 } 790 791 EFUN(merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 792 793 EFUN(wr_hwtune_ovr_write_sel(9)); /* Write tap5 */ 794 EFUN(wr_hwtune_ovr_write_val(val)); 795 EFUN(wr_hwtune_ovr_write_en(1)); 796 return(ERR_CODE_NONE); 797 } 798 799 err_code_t merlin16_pcieg3_INTERNAL_get_rx_dfe5(srds_access_t *sa__, int8_t *val) { 800 ESTM(*val = rd_dfe_5_cmn()); 801 return (ERR_CODE_NONE); 802 } 803 804 805 806 807 808 809 810 811 err_code_t merlin16_pcieg3_INTERNAL_core_clkgate(srds_access_t *sa__, uint8_t enable) { 812 813 if (enable) { 814 } 815 else { 816 } 817 return (ERR_CODE_NONE); 818 } 819 820 err_code_t merlin16_pcieg3_INTERNAL_lane_clkgate(srds_access_t *sa__, uint8_t enable) { 821 822 if (enable) { 823 /* Use frc/frc_val to force all RX and TX clk_vld signals to 0 */ 824 EFUN(wr_pmd_rx_clk_vld_frc_val(0x0)); 825 EFUN(wr_pmd_rx_clk_vld_frc(0x1)); 826 EFUN(wr_pmd_tx_clk_vld_frc_val(0x0)); 827 EFUN(wr_pmd_tx_clk_vld_frc(0x1)); 828 829 /* Use frc_on to force clkgate */ 830 EFUN(wr_ln_rx_s_clkgate_frc_on(0x1)); 831 832 EFUN(wr_ln_tx_s_clkgate_frc_on(0x1)); 833 834 } 835 else { 836 EFUN(wr_pmd_rx_clk_vld_frc_val(0x0)); 837 EFUN(wr_pmd_rx_clk_vld_frc(0x0)); 838 EFUN(wr_pmd_tx_clk_vld_frc_val(0x0)); 839 EFUN(wr_pmd_tx_clk_vld_frc(0x1)); 840 841 EFUN(wr_ln_rx_s_clkgate_frc_on(0x0)); 842 843 EFUN(wr_ln_tx_s_clkgate_frc_on(0x0)); 844 } 845 return (ERR_CODE_NONE); 846 } 847 848 849 err_code_t merlin16_pcieg3_INTERNAL_get_osr_mode(srds_access_t *sa__, merlin16_pcieg3_osr_mode_st *imode) { 850 merlin16_pcieg3_osr_mode_st mode; 851 852 ENULL_MEMSET(&mode, 0, sizeof(merlin16_pcieg3_osr_mode_st)); 853 854 if(!imode) 855 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 856 857 ESTM(mode.tx = rd_tx_osr_mode()); 858 ESTM(mode.rx = rd_rx_osr_mode()); 859 mode.tx_rx = 255; 860 *imode = mode; 861 return (ERR_CODE_NONE); 862 863 } 864 865 866 err_code_t merlin16_pcieg3_INTERNAL_pmd_lock_status(srds_access_t *sa__, uint8_t *pmd_lock, uint8_t *pmd_lock_chg) { 867 uint16_t rddata; 868 #if defined(reg_rd_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS) 869 ESTM(rddata = reg_rd_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS()); 870 ESTM(*pmd_lock = ex_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS__dbg_pmd_rx_lock(rddata)); 871 ESTM(*pmd_lock_chg = ex_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS__dbg_pmd_rx_lock_change(rddata)); 872 #else 873 ESTM(rddata = reg_rd_TLB_RX_PMD_RX_LOCK_STATUS()); 874 ESTM(*pmd_lock = ex_TLB_RX_PMD_RX_LOCK_STATUS__pmd_rx_lock(rddata)); 875 ESTM(*pmd_lock_chg = ex_TLB_RX_PMD_RX_LOCK_STATUS__pmd_rx_lock_change(rddata)); 876 #endif 877 return(ERR_CODE_NONE); 878 } 879 880 err_code_t merlin16_pcieg3_INTERNAL_sigdet_status(srds_access_t *sa__, uint8_t *sig_det, uint8_t *sig_det_chg) { 881 ESTM(*sig_det = ((rd_rx_sigdet() >> 1) & 0x1)); 882 ESTM(*sig_det_chg = (uint8_t)rd_rg_sigdet_tggl_cnt()); 883 return(ERR_CODE_NONE); 884 } 885 886 err_code_t merlin16_pcieg3_INTERNAL_pll_lock_status(srds_access_t *sa__, uint8_t *pll_lock, uint8_t *pll_lock_chg) { 887 888 uint16_t rddata; 889 uint8_t pll_fail; 890 ESTM(rddata = reg_rdc_PLL_CAL_COM_STS_0()); 891 ESTM(*pll_lock = exc_PLL_CAL_COM_STS_0__pll_lock(rddata)); 892 ESTM(pll_fail = exc_PLL_CAL_COM_STS_0__pll_fail_stky(rddata)); 893 ESTM(*pll_lock_chg = ((*pll_lock ^ !exc_PLL_CAL_COM_STS_0__pll_lock_bar_stky(rddata)) | (*pll_lock ^ !pll_fail))); 894 return(ERR_CODE_NONE); 895 } 896 897 err_code_t merlin16_pcieg3_INTERNAL_read_lane_state(srds_access_t *sa__, merlin16_pcieg3_lane_state_st *istate) { 898 899 merlin16_pcieg3_lane_state_st state; 900 uint8_t ladder_range = 0; 901 902 ENULL_MEMSET(&state, 0, sizeof(merlin16_pcieg3_lane_state_st)); 903 904 if(!istate) 905 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 906 907 EFUN(merlin16_pcieg3_INTERNAL_pmd_lock_status(sa__,&state.rx_lock, &state.rx_lock_chg)); 908 { 909 err_code_t err_code = 0; 910 state.stop_state = merlin16_pcieg3_INTERNAL_stop_micro(sa__,state.rx_lock,&err_code); 911 if(err_code) USR_PRINTF(("Unable to stop microcontroller, following data is suspect\n")); 912 } 913 914 ESTM(state.rate_select = (rd_rate_sel()+1)); 915 ESTM(state.dsc_one_hot_0_0 = rd_dsc_state_one_hot_0()); 916 ESTM(state.dsc_one_hot_0_1 = rd_dsc_state_one_hot_0()); 917 { merlin16_pcieg3_osr_mode_st osr_mode; 918 ENULL_MEMSET(&osr_mode, 0, sizeof(merlin16_pcieg3_osr_mode_st)); 919 EFUN(merlin16_pcieg3_INTERNAL_get_osr_mode(sa__, &osr_mode)); 920 state.osr_mode = osr_mode; 921 } 922 ESTM(state.reset_state = rd_lane_dp_reset_state()); 923 EFUN(merlin16_pcieg3_INTERNAL_sigdet_status(sa__,&state.sig_det, &state.sig_det_chg)); 924 ESTM(state.rx_ppm = rd_cdr_integ_reg()/84); 925 ESTM(state.clk90 = rd_cnt_d_minus_m1()); 926 ESTM(state.clkp1 = rd_cnt_d_minus_p1()); 927 ESTM(state.br_pd_en = rd_br_pd_en()); 928 /* drop the MSB, the result is actually valid modulo 128 */ 929 /* Also flip the sign to account for d-m1, versus m1-d */ 930 state.clk90 = state.clk90<<1; 931 state.clk90 = -(state.clk90>>1); 932 state.clkp1 = state.clkp1<<1; 933 state.clkp1 = -(state.clkp1>>1); 934 935 EFUN(merlin16_pcieg3_INTERNAL_get_rx_pf_main(sa__, &state.pf_main)); 936 ESTM(state.pf_hiz = rd_pf_hiz()); 937 { 938 uint8_t rate_sel; 939 ESTM(rate_sel = rd_rate_sel()); 940 if (rate_sel == MERLIN16_PCIEG3_GEN1) { 941 ESTM(state.pf2_ctrl = merlin16_pcieg3_INTERNAL_gray_to_uint8(rd_pf2_lowp_ctrl_g1())); 942 } else if (rate_sel == MERLIN16_PCIEG3_GEN2) { 943 ESTM(state.pf2_ctrl = merlin16_pcieg3_INTERNAL_gray_to_uint8(rd_pf2_lowp_ctrl_g2())); 944 } else { 945 ESTM(state.pf2_ctrl = rd_pf2_lowp_ctrl()); 946 } 947 } 948 EFUN(merlin16_pcieg3_INTERNAL_get_rx_vga(sa__, &state.vga)); 949 ESTM(state.dc_offset = rd_dc_offset_bin()); 950 ESTM(ladder_range = rd_p1_thresh_sel()); 951 EFUN(merlin16_pcieg3_INTERNAL_get_p1_threshold(sa__, &state.p1_lvl_ctrl)); 952 state.p1_lvl = merlin16_pcieg3_INTERNAL_ladder_setting_to_mV(sa__, state.p1_lvl_ctrl, ladder_range); 953 state.m1_lvl = 0; 954 955 EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe1(sa__, &state.dfe1)); 956 EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe2(sa__, &state.dfe2)); 957 EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe3(sa__, &state.dfe3)); 958 EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe4(sa__, &state.dfe4)); 959 EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe5(sa__, &state.dfe5)); 960 961 ESTM(state.dfe1_dcd = rd_dfe_1_e()-rd_dfe_1_o()); 962 ESTM(state.dfe2_dcd = (rd_dfe_2_se() ? -rd_dfe_2_e(): rd_dfe_2_e()) -(rd_dfe_2_so() ? -rd_dfe_2_o(): rd_dfe_2_o())); 963 ESTM(state.pe = rd_p1_offset_evn_bin()); 964 ESTM(state.ze = rd_data_offset_evn_bin()); 965 ESTM(state.me = rd_m1_offset_evn_bin()); 966 967 ESTM(state.po = rd_p1_offset_odd_bin()); 968 ESTM(state.zo = rd_data_offset_odd_bin()); 969 ESTM(state.mo = rd_m1_offset_odd_bin()); 970 971 /* tx_ppm = register/10.84 */ 972 ESTM(state.tx_ppm = (int16_t)(((int32_t)(rd_tx_pi_integ2_reg()))*3125/32768)); 973 974 975 if (!state.stop_state) { 976 EFUN(merlin16_pcieg3_stop_rx_adaptation(sa__, 0)); 977 } 978 979 *istate = state; 980 return (ERR_CODE_NONE); 981 } 982 983 err_code_t merlin16_pcieg3_INTERNAL_display_lane_state_no_newline(srds_access_t *sa__) { 984 uint16_t lane_idx; 985 merlin16_pcieg3_lane_state_st state; 986 987 988 989 ENULL_MEMSET(&state, 0, sizeof(merlin16_pcieg3_lane_state_st)); 990 991 EFUN(merlin16_pcieg3_INTERNAL_read_lane_state(sa__, &state)); 992 993 lane_idx = merlin16_pcieg3_get_lane(sa__); 994 EFUN_PRINTF(("%2d ", lane_idx)); 995 EFUN_PRINTF((" %01x ",state.stop_state)); 996 EFUN_PRINTF((" GEN%1d", state.rate_select)); 997 EFUN_PRINTF((" %04X,%04X", state.dsc_one_hot_0_0, state.dsc_one_hot_0_1)); 998 EFUN_PRINTF((" %1d,%3u", state.sig_det, state.sig_det_chg)); 999 EFUN_PRINTF((" %1d%s", state.rx_lock, state.rx_lock_chg ? "*" : " ")); 1000 EFUN_PRINTF(("%4d ", state.rx_ppm)); 1001 EFUN_PRINTF((" %3d ", state.clk90)); 1002 EFUN_PRINTF((" %3d ", state.clkp1)); 1003 EFUN_PRINTF((" %2d,%1d ", state.pf_main, state.pf2_ctrl)); 1004 EFUN_PRINTF((" %2d ", state.vga)); 1005 EFUN_PRINTF(("%3d ", state.dc_offset)); 1006 EFUN_PRINTF(("%3d ", state.p1_lvl)); 1007 EFUN_PRINTF(("%3d,%3d,%3d,%3d,%3d,%3d,%3d ", state.dfe1, state.dfe2, state.dfe3, state.dfe4, state.dfe5, state.dfe1_dcd, state.dfe2_dcd)); 1008 EFUN_PRINTF(("%3d,%3d,%3d,%3d,%3d,%3d ", state.ze, state.zo, state.pe, state.po, state.me, state.mo)); 1009 EFUN_PRINTF((" %4d ", state.tx_ppm)); 1010 1011 return (ERR_CODE_NONE); 1012 } 1013 1014 1015 err_code_t merlin16_pcieg3_INTERNAL_read_core_state(srds_access_t *sa__, merlin16_pcieg3_core_state_st *istate) { 1016 merlin16_pcieg3_core_state_st state; 1017 struct merlin16_pcieg3_uc_core_config_st core_cfg; 1018 1019 ENULL_MEMSET(&state, 0, sizeof(merlin16_pcieg3_core_state_st)); 1020 ENULL_MEMSET(&core_cfg, 0, sizeof(struct merlin16_pcieg3_uc_core_config_st)); 1021 1022 if(!istate) 1023 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 1024 /* pllpon_mux is read in case the rescal value is overriden. */ 1025 ESTM(state.rescal = rdc_pllpon_mux()); 1026 ESTM(state.core_reset = rdc_core_dp_reset_state()); 1027 ESTM(state.uc_active = rdc_uc_active()); 1028 ESTM(state.comclk_mhz = rdc_heartbeat_count_1us()); 1029 ESTM(state.ucode_version = rdcv_common_ucode_version()); 1030 ESTM(state.ucode_minor_version = rdcv_common_ucode_minor_version()); 1031 ESTM(state.afe_hardware_version = rdcv_afe_hardware_version()); 1032 ESTM(state.temp_idx = rdcv_temp_idx()); 1033 { int16_t die_temp = 0; 1034 EFUN(merlin16_pcieg3_read_die_temperature(sa__, &die_temp)); 1035 state.die_temp = die_temp; 1036 } 1037 ESTM(state.avg_tmon = _bin_to_degC(rdcv_avg_tmon_reg13bit()>>3)); 1038 state.vco_rate_mhz = (uint16_t)core_cfg.vco_rate_in_Mhz; 1039 ESTM(state.analog_vco_range = rdc_pll_range()); 1040 EFUN(merlin16_pcieg3_INTERNAL_pll_lock_status(sa__, &state.pll_lock, &state.pll_lock_chg)); 1041 ESTM(state.core_status = rdcv_status_byte()); 1042 ESTM(state.rate_select = (rd_rate_sel()+1)); 1043 1044 *istate = state; 1045 return (ERR_CODE_NONE); 1046 } 1047 1048 1049 err_code_t merlin16_pcieg3_INTERNAL_display_core_state_no_newline(srds_access_t *sa__) { 1050 merlin16_pcieg3_core_state_st state; 1051 ENULL_MEMSET(&state , 0, sizeof(state )); 1052 EFUN(merlin16_pcieg3_INTERNAL_read_core_state(sa__, &state)); 1053 1054 if ((state.avg_tmon<-50)||(state.avg_tmon>135)) { 1055 EFUN_PRINTF(("\n*** WARNING: Core die temperature (LIVE_TEMP) out of bounds -50C to 130C\n")); 1056 } 1057 if ((state.rescal < 6) || (state.rescal > 13)) { 1058 EFUN_PRINTF(("\n*** WARNING: RESCAL value is out of bounds 6 to 13\n")); 1059 } 1060 1061 EFUN_PRINTF((" %02d " , merlin16_pcieg3_get_core(sa__))); 1062 EFUN_PRINTF((" %02x " , state.core_status)); 1063 EFUN_PRINTF((" %1d " , state.pll_pwrdn)); 1064 EFUN_PRINTF((" %3d.%2dMHz" , (state.comclk_mhz/4),((state.comclk_mhz%4)*25))); /* comclk in Mhz = heartbeat_count_1us / 4 */ 1065 EFUN_PRINTF((" %4X_%02X " , state.ucode_version, state.ucode_minor_version)); 1066 EFUN_PRINTF((" 0x%02x " , state.afe_hardware_version)); 1067 EFUN_PRINTF((" %3dC " , state.die_temp)); 1068 EFUN_PRINTF((" (%02d)%3dC " , state.temp_idx, state.avg_tmon)); 1069 EFUN_PRINTF((" 0x%02x " , state.rescal)); 1070 EFUN_PRINTF((" GEN%d " , state.rate_select)); 1071 EFUN_PRINTF((" %03d " , state.analog_vco_range)); 1072 EFUN_PRINTF((" %01d%s " , state.pll_lock, state.pll_lock_chg ? "*" : " ")); 1073 1074 return (ERR_CODE_NONE); 1075 } 1076 1077 1078 1079 err_code_t merlin16_pcieg3_INTERNAL_check_uc_lane_stopped(srds_access_t *sa__) { 1080 1081 uint8_t is_micro_stopped; 1082 ESTM(is_micro_stopped = rdv_usr_sts_micro_stopped()); 1083 if (!is_micro_stopped) { 1084 return(_error(ERR_CODE_UC_NOT_STOPPED)); 1085 } else { 1086 return(ERR_CODE_NONE); 1087 } 1088 } 1089 1090 err_code_t merlin16_pcieg3_INTERNAL_calc_patt_gen_mode_sel(uint8_t *mode_sel, uint8_t *zero_pad_len, uint8_t patt_length) { 1091 1092 if(!mode_sel) { 1093 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 1094 } 1095 if(!zero_pad_len) { 1096 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 1097 } 1098 1099 /* Select the correct Pattern generator Mode depending on Pattern length */ 1100 if (!(140 % patt_length)) { 1101 *mode_sel = 6; 1102 *zero_pad_len = 100; 1103 } 1104 else if (!(160 % patt_length)) { 1105 *mode_sel = 5; 1106 *zero_pad_len = 80; 1107 } 1108 else if (!(180 % patt_length)) { 1109 *mode_sel = 4; 1110 *zero_pad_len = 60; 1111 } 1112 else if (!(200 % patt_length)) { 1113 *mode_sel = 3; 1114 *zero_pad_len = 40; 1115 } 1116 else if (!(220 % patt_length)) { 1117 *mode_sel = 2; 1118 *zero_pad_len = 20; 1119 } 1120 else if (!(240 % patt_length)) { 1121 *mode_sel = 1; 1122 *zero_pad_len = 0; 1123 } else { 1124 EFUN_PRINTF(("ERROR: Unsupported Pattern Length\n")); 1125 return (_error(ERR_CODE_CFG_PATT_INVALID_PATT_LENGTH)); 1126 } 1127 return(ERR_CODE_NONE); 1128 } 1129 1130 1131 err_code_t merlin16_pcieg3_INTERNAL_print_uc_dsc_error(srds_access_t *sa__, enum srds_pmd_uc_cmd_enum cmd) { 1132 uint32_t supp_info; 1133 1134 ESTM(supp_info = (rd_uc_dsc_supp_info()) & 0xFF); 1135 switch (SUPP_INFO_TO_ERROR_CODE(supp_info)) { 1136 case UC_CMD_ERROR_INVALID_COMMAND: 1137 ESTM_PRINTF(("ERROR : UC reported invalid command %d. (other_info = 0x%X)\n", 1138 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1139 break; 1140 case UC_CMD_ERROR_BUSY: 1141 ESTM_PRINTF(("ERROR : UC reported busy for command %d. (other_info = 0x%X)\n", 1142 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1143 break; 1144 case UC_CMD_ERROR_GET_EYE_SAMPLE_ERROR: 1145 ESTM_PRINTF(("ERROR : UC reported error in getting eye sample. (command %d, other_info = 0x%X)\n", 1146 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1147 break; 1148 case UC_CMD_ERROR_PRBS_NOT_LOCKED: 1149 ESTM_PRINTF(("ERROR : UC reported PRBS not locked. (command %d, other_info = 0x%X)\n", 1150 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1151 break; 1152 case UC_CMD_ERROR_COMMAND_IN_PROGRESS: 1153 ESTM_PRINTF(("ERROR : UC reported command already in progress. (command %d, other_info = 0x%X)\n", 1154 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1155 break; 1156 case UC_CMD_ERROR_INVALID_MODE: 1157 ESTM_PRINTF(("ERROR : UC reported invalid mode for command %d. (other_info = 0x%X)\n", 1158 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1159 break; 1160 default: 1161 ESTM_PRINTF(("ERROR : UC reported unknown error 0x%X for command %d. (other_info = 0x%X)\n", 1162 SUPP_INFO_TO_ERROR_CODE(supp_info), cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1163 } 1164 /* Cleanup cmd register */ 1165 EFUN(reg_wr_DSC_A_DSC_UC_CTRL(0x80)); 1166 EFUN(wr_uc_dsc_data(0)); 1167 1168 return(ERR_CODE_NONE); 1169 } 1170 1171 /******************************************/ 1172 /* Serdes Register field Poll functions */ 1173 /******************************************/ 1174 1175 #ifndef CUSTOM_REG_POLLING 1176 1177 /* poll for microcontroller to populate the dsc_data register */ 1178 err_code_t merlin16_pcieg3_INTERNAL_poll_diag_done(srds_access_t *sa__, uint16_t *status, uint32_t timeout_ms) { 1179 uint8_t loop; 1180 1181 if(!status) { 1182 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 1183 } 1184 1185 for(loop=0;loop < 100; loop++) { 1186 ESTM(*status=rdv_usr_diag_status()); 1187 1188 if((*status & 0x8000) > 0) { 1189 return(ERR_CODE_NONE); 1190 } 1191 if(loop>10) { 1192 EFUN(USR_DELAY_US(10*timeout_ms)); 1193 } 1194 } 1195 return(_error(ERR_CODE_DIAG_TIMEOUT)); 1196 } 1197 1198 /** Poll for field "uc_dsc_ready_for_cmd" = 1 [Return Val => Error_code (0 = Polling Pass)] */ 1199 err_code_t merlin16_pcieg3_INTERNAL_poll_uc_dsc_ready_for_cmd_equals_1(srds_access_t *sa__, uint32_t timeout_ms, enum srds_pmd_uc_cmd_enum cmd) { 1200 /* read quickly for 10 tries */ 1201 uint16_t loop; 1202 1203 for (loop = 0; loop < 100; loop++) { 1204 uint16_t rddata; 1205 ESTM(rddata = reg_rd_DSC_A_DSC_UC_CTRL()); 1206 if (rddata & 0x0080) { /* bit 7 is uc_dsc_ready_for_cmd */ 1207 if (rddata & 0x0040) { /* bit 6 is uc_dsc_error_found */ 1208 EFUN(merlin16_pcieg3_INTERNAL_print_uc_dsc_error(sa__, cmd)); 1209 return(_error(ERR_CODE_UC_CMD_RETURN_ERROR)); 1210 } 1211 return (ERR_CODE_NONE); 1212 } 1213 if(loop>10) { 1214 EFUN(USR_DELAY_US(10*timeout_ms)); 1215 } 1216 } 1217 EFUN_PRINTF(("ERROR : DSC ready for command is not working, applying workaround and getting debug info !\n")); 1218 DISP(rd_uc_dsc_supp_info()); 1219 DISP(rd_uc_dsc_gp_uc_req()); 1220 DISP(rd_dsc_state()); 1221 ESTM_PRINTF(("Uc Core Status Byte = 0x%x\n",rdcv_status_byte())); 1222 DISP(rdv_usr_sts_micro_stopped()); 1223 /* DISP(rdv_stop_graceful_trigger()); */ 1224 /* artifically terminate the command to re-enable the command interface */ 1225 EFUN(wr_uc_dsc_ready_for_cmd(0x1)); 1226 return (_error(ERR_CODE_POLLING_TIMEOUT)); /* Error Code for polling timeout */ 1227 } 1228 1229 /* Poll for field "dsc_state" = DSC_STATE_UC_TUNE [Return Val => Error_code (0 = Polling Pass)] */ 1230 err_code_t merlin16_pcieg3_INTERNAL_poll_dsc_state_equals_uc_tune(srds_access_t *sa__, uint32_t timeout_ms) { 1231 uint16_t loop; 1232 uint16_t dsc_state; 1233 /* poll 10 times to avoid longer delays later */ 1234 for (loop = 0; loop < 100; loop++) { 1235 ESTM(dsc_state = rd_dsc_state()); 1236 if (dsc_state == DSC_STATE_UC_TUNE) { 1237 return (ERR_CODE_NONE); 1238 } 1239 if(loop>10) { 1240 EFUN(USR_DELAY_US(10*timeout_ms)); 1241 } 1242 } 1243 ESTM_PRINTF(("DSC_STATE = %d\n", rd_dsc_state())); 1244 return (_error(ERR_CODE_POLLING_TIMEOUT)); /* Error Code for polling timeout */ 1245 } 1246 1247 1248 1249 1250 /* Poll for field "micro_ra_initdone" = 1 [Return Val => Error_code (0 = Polling Pass)] */ 1251 err_code_t merlin16_pcieg3_INTERNAL_poll_micro_ra_initdone(srds_access_t *sa__, uint32_t timeout_ms) { 1252 uint16_t loop; 1253 1254 uint8_t result; 1255 for (loop = 0; loop <= 100; loop++) { 1256 ESTM(result = rdc_micro_ra_initdone()); 1257 if (result) { 1258 return (ERR_CODE_NONE); 1259 } 1260 EFUN(USR_DELAY_US(10*timeout_ms)); 1261 } 1262 return (_error(ERR_CODE_POLLING_TIMEOUT)); /* Error Code for polling timeout */ 1263 } 1264 1265 #endif /* CUSTOM_REG_POLLING */ 1266 1267 1268 1269 err_code_t merlin16_pcieg3_INTERNAL_rdblk_callback(void *arg, uint8_t byte_count, uint16_t data) { 1270 merlin16_pcieg3_INTERNAL_rdblk_callback_arg_t * const cast_arg = (merlin16_pcieg3_INTERNAL_rdblk_callback_arg_t *)arg; 1271 *(cast_arg->mem_ptr + get_endian_offset(cast_arg->mem_ptr)) = data & 0xFF; 1272 cast_arg->mem_ptr++; 1273 if (byte_count == 2) { 1274 *(cast_arg->mem_ptr + get_endian_offset(cast_arg->mem_ptr)) = data >> 8; 1275 cast_arg->mem_ptr++; 1276 } 1277 return (ERR_CODE_NONE); 1278 } 1279 1280 err_code_t merlin16_pcieg3_INTERNAL_rdblk_uc_generic_ram(srds_access_t *sa__, 1281 uint32_t block_addr, 1282 uint16_t block_size, 1283 uint16_t start_offset, 1284 uint16_t cnt, 1285 void *arg, 1286 err_code_t (*callback)(void *, uint8_t, uint16_t)) { 1287 uint32_t read_val = 0; 1288 uint8_t defecit = 0; 1289 uint32_t addr = block_addr + start_offset; 1290 1291 if (cnt == 0) { 1292 return (ERR_CODE_NONE); 1293 } 1294 1295 /* Check for bad start offset and block size. */ 1296 if (start_offset >= block_size) { 1297 return (ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1298 } 1299 1300 while (cnt > 0) { 1301 /* Determine how many bytes to read before wrapping back to start of block. */ 1302 uint16_t block_cnt = SRDS_MIN(cnt, block_addr + block_size - addr); 1303 cnt -= block_cnt; 1304 1305 /* Set up the word reads. */ 1306 EFUN(wrc_micro_autoinc_rdaddr_en(1)); 1307 EFUN(wrc_micro_ra_rddatasize(0x1)); /* Select 16bit read datasize */ 1308 EFUN(wrc_micro_ra_rdaddr_msw(addr >> 16)); /* Upper 16bits of RAM address to be read */ 1309 EFUN(wrc_micro_ra_rdaddr_lsw(addr & 0xFFFE)); /* Lower 16bits of RAM address to be read */ 1310 1311 /* Read the leading byte, if starting at an odd address. */ 1312 if ((addr & 1) == 1) { 1313 ESTM(read_val |= ((rdc_micro_ra_rddata_lsw() >> 8) << defecit)); 1314 if (defecit == 8) { 1315 EFUN(callback(arg, 2, (uint16_t)read_val)); 1316 read_val = 0; 1317 } 1318 /* We just read a byte. This toggles the defecit from 0 to 8 or from 8 to 0. */ 1319 defecit ^= 8; 1320 --block_cnt; 1321 } 1322 1323 /* Read the whole words, and call the callback with two bytes at a time. */ 1324 while (block_cnt >= 2) { 1325 ESTM(read_val |= (rdc_micro_ra_rddata_lsw() << defecit)); 1326 EFUN(callback(arg, 2, (uint16_t)read_val)); 1327 read_val >>= 16; 1328 /* We just read two bytes. This preserves whatever defecit (8 or 0) is there. */ 1329 block_cnt -= 2; 1330 } 1331 1332 /* Read the trailing byte, if leftover after reading whole words. */ 1333 if (block_cnt > 0) { 1334 ESTM(read_val |= ((rdc_micro_ra_rddata_lsw() & 0xFF) << defecit)); 1335 if (defecit == 8) { 1336 EFUN(callback(arg, 2, (uint16_t)read_val)); 1337 read_val = 0; 1338 } 1339 /* We just read a byte. This toggles the defecit from 0 to 8 or from 8 to 0. */ 1340 defecit ^= 8; 1341 } 1342 addr = block_addr; 1343 } 1344 1345 /* If a final byte is left behind, then call the callback with it. */ 1346 if (defecit > 0) { 1347 EFUN(callback(arg, 1, (uint16_t)read_val)); 1348 } 1349 1350 return(ERR_CODE_NONE); 1351 } 1352 1353 err_code_t merlin16_pcieg3_INTERNAL_rdblk_uc_generic_ram_descending(srds_access_t *sa__, 1354 uint32_t block_addr, 1355 uint16_t block_size, 1356 uint16_t start_offset, 1357 uint16_t cnt, 1358 void *arg, 1359 err_code_t (*callback)(void *, uint8_t, uint16_t)) { 1360 uint32_t read_val = 0; 1361 uint8_t defecit = 0; 1362 uint32_t addr = block_addr + start_offset; 1363 uint16_t configured_addr_msw = (addr >> 16) + 1; 1364 1365 if (cnt == 0) { 1366 return (ERR_CODE_NONE); 1367 } 1368 1369 /* Check for bad start offset and block size. */ 1370 if (start_offset >= block_size) { 1371 return (ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1372 } 1373 1374 EFUN(wrc_micro_autoinc_rdaddr_en(0)); 1375 EFUN(wrc_micro_ra_rddatasize(0x1)); /* Select 16bit read datasize */ 1376 1377 while (cnt > 0) { 1378 /* Determine how many bytes to read before wrapping back to end of block. */ 1379 uint16_t block_cnt = SRDS_MIN(cnt, start_offset+1); 1380 cnt -= block_cnt; 1381 1382 while (block_cnt > 0) { 1383 const uint16_t addr_msw = addr >> 16; 1384 uint16_t read_val2; 1385 if (addr_msw != configured_addr_msw) { 1386 EFUN(wrc_micro_ra_rdaddr_msw(addr_msw)); /* Upper 16bits of RAM address to be read */ 1387 configured_addr_msw = addr_msw; 1388 } 1389 1390 EFUN(wrc_micro_ra_rdaddr_lsw(addr & 0xFFFE)); /* Lower 16bits of RAM address to be read */ 1391 ESTM(read_val2 = rdc_micro_ra_rddata_lsw()); 1392 1393 if (((addr & 1) == 1) && (block_cnt >= 2)) { 1394 /* Reading two bytes. Since we're reading in descending address order, they 1395 * will be reversed before they are sent out. */ 1396 read_val |= ((((read_val2 & 0xFF) << 8) | (read_val2 >> 8)) << defecit); 1397 EFUN(callback(arg, 2, (uint16_t)read_val)); 1398 read_val >>= 16; 1399 /* We just read two bytes. This preserves whatever defecit (8 or 0) is there. */ 1400 block_cnt -= 2; 1401 addr -= 2; 1402 } else { 1403 if ((addr & 1) == 1) { 1404 /* Reading upper byte of word. */ 1405 read_val |= ((read_val2 >> 8) << defecit); 1406 } else { 1407 /* Reading lower byte of word. */ 1408 read_val |= ((read_val2 & 0xFF) << defecit); 1409 } 1410 if (defecit == 8) { 1411 EFUN(callback(arg, 2, (uint16_t)read_val)); 1412 read_val = 0; 1413 } 1414 /* We just read a byte. This toggles the defecit from 0 to 8 or from 8 to 0. */ 1415 defecit ^= 8; 1416 --block_cnt; 1417 --addr; 1418 } 1419 } 1420 1421 addr = block_addr + block_size - 1; 1422 start_offset = block_size - 1; 1423 } 1424 1425 /* If a final byte is left behind, then call the callback with it. */ 1426 if (defecit > 0) { 1427 EFUN(callback(arg, 1, (uint16_t)read_val)); 1428 } 1429 1430 return(ERR_CODE_NONE); 1431 } 1432 1433 uint8_t merlin16_pcieg3_INTERNAL_grp_idx_from_lane(uint8_t lane) { 1434 return(0); 1435 } 1436 1437