merlin16_internal.c (81904B)
1 /*********************************************************************************** 2 *********************************************************************************** 3 * File Name : merlin16_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_internal.c 23 * Implementation of API functions 24 */ 25 26 #include <phymod/phymod.h> 27 #include <phymod/phymod_system.h> 28 #include "merlin16_internal.h" 29 #include "merlin16_internal_error.h" 30 #include "merlin16_access.h" 31 #include "merlin16_common.h" 32 #include "merlin16_config.h" 33 #include "merlin16_functions.h" 34 #include "merlin16_select_defns.h" 35 #include "merlin16_prbs.h" 36 37 38 39 40 /* If SERDES_EVAL is defined, then is_ate_log_enabled() is queried to *\ 41 \* know whether to log ATE. merlin16_access.h provides that function. */ 42 uint32_t merlin16_INTERNAL_mult_with_overflow_check(uint32_t a, uint32_t b, uint8_t *of) { 43 uint16_t c,d; 44 uint32_t r,s; 45 if (a > b) return merlin16_INTERNAL_mult_with_overflow_check(b, a, of); 46 *of = 0; 47 c = b >> 16; 48 d = UINT16_MAX & b; 49 r = a * c; 50 s = a * d; 51 if (r > UINT16_MAX) *of = 1; 52 r <<= 16; 53 return (s + r); 54 } 55 56 static merlin16_info_t merlin16_info = {0}; 57 58 merlin16_info_t *merlin16_INTERNAL_get_merlin16_info_ptr(void) { 59 return &merlin16_info; 60 } 61 62 err_code_t merlin16_INTERNAL_match_ucode_from_info(srds_access_t *sa__) { 63 uint16_t ucode_version_major; 64 uint8_t ucode_version_minor; 65 uint32_t ucode_version; 66 merlin16_info_t * const merlin16_info_ptr = merlin16_INTERNAL_get_merlin16_info_ptr(); 67 ESTM(ucode_version_major = rdcv_common_ucode_version()); 68 ESTM(ucode_version_minor = rdcv_common_ucode_minor_version()); 69 ucode_version = (ucode_version_major << 8) | ucode_version_minor; 70 if (ucode_version == merlin16_info_ptr->ucode_version) { 71 return(ERR_CODE_NONE); 72 } else { 73 EFUN_PRINTF(("ERROR: ucode version of the current thread not matching with stored merlin16_info->ucode_version, Expected 0x%08X, but received 0x%08X.\n", 74 merlin16_info_ptr->ucode_version, ucode_version)); 75 return(ERR_CODE_UCODE_VERIFY_FAIL); 76 } 77 } 78 79 err_code_t merlin16_INTERNAL_verify_merlin16_info(merlin16_info_t const *test_info, srds_access_t *sa__) 80 { 81 err_code_t err_code = ERR_CODE_NONE; 82 83 if (test_info->signature != SRDS_INFO_SIGNATURE) { 84 EFUN_PRINTF(("ERROR: Mismatch in merlin16_info signature. Expected 0x%08X, but received 0x%08X.\n", 85 SRDS_INFO_SIGNATURE, test_info->signature)); 86 return (_error(ERR_CODE_INFO_TABLE_ERROR)); 87 } 88 err_code = merlin16_INTERNAL_match_ucode_from_info(sa__); 89 if (err_code != ERR_CODE_NONE) { 90 /* ucode version mismatch */ 91 return(ERR_CODE_MICRO_INIT_NOT_DONE); 92 } 93 return (ERR_CODE_NONE); 94 } 95 96 /* Store a cached AFE version for re-use */ 97 err_code_t merlin16_INTERNAL_get_afe_hw_version(srds_access_t *sa__, uint8_t *afe_hw_version) { 98 static uint8_t _cached_afe_hw_version = 255; 99 100 if (!afe_hw_version) 101 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 102 if (_cached_afe_hw_version == 255) 103 ESTM(_cached_afe_hw_version = rdcv_afe_hardware_version()); 104 *afe_hw_version = _cached_afe_hw_version; 105 return(ERR_CODE_NONE); 106 } 107 108 int merlin16_osr_mode_enum_to_int_x1000(uint8_t osr_mode) { 109 switch(osr_mode) { 110 case MERLIN16_OSX1: return 1000; 111 case MERLIN16_OSX2: return 2000; 112 case MERLIN16_OSX4: return 4000; 113 case MERLIN16_OSX3: return 3000; 114 case MERLIN16_OSX3P3: return 3300; 115 case MERLIN16_OSX5: return 5000; 116 case MERLIN16_OSX7P5: return 7500; 117 case MERLIN16_OSX8P25: return 8250; 118 case MERLIN16_OSX10: return 10000; 119 case MERLIN16_OSX8: return 8000; 120 default: return 1000; 121 } 122 } 123 124 err_code_t merlin16_INTERNAL_get_num_bits_per_ms(srds_access_t *sa__, uint32_t *num_bits_per_ms) { 125 uint8_t osr_mode = 0; 126 #if defined(rd_rx_pam4_mode) 127 uint8_t pam4_mode = 0; 128 #endif 129 struct merlin16_uc_core_config_st core_config = {{0}}; 130 131 { 132 merlin16_osr_mode_st osr_mode_st; 133 ENULL_MEMSET(&osr_mode_st, 0, sizeof(merlin16_osr_mode_st)); 134 EFUN(merlin16_INTERNAL_get_osr_mode(sa__, &osr_mode_st)); 135 osr_mode = osr_mode_st.rx; 136 } 137 138 #if defined(rd_rx_pam4_mode) 139 ESTM(pam4_mode = rd_rx_pam4_mode()); 140 #endif 141 142 EFUN(merlin16_get_uc_core_config(sa__, &core_config)); 143 *num_bits_per_ms = (((uint32_t)core_config.vco_rate_in_Mhz * 100000UL) / merlin16_osr_mode_enum_to_int_x1000(osr_mode))*10; 144 145 #if defined(rd_rx_pam4_mode) 146 if(pam4_mode > 0) *num_bits_per_ms <<= 1; 147 #endif 148 return(ERR_CODE_NONE); 149 } 150 151 err_code_t merlin16_INTERNAL_display_BER(srds_access_t *sa__, uint16_t time_ms) { 152 char string[10]; 153 EFUN(merlin16_INTERNAL_get_BER_string(sa__,time_ms,string)); 154 USR_PRINTF(("%s",string)); 155 return(ERR_CODE_NONE); 156 } 157 158 err_code_t merlin16_INTERNAL_get_BER_string(srds_access_t *sa__, uint16_t time_ms, char *string) { 159 char string2[3]; 160 struct ber_data_st ber_data_local; 161 162 ENULL_MEMSET( &ber_data_local, 0, sizeof(ber_data_local) ); 163 164 if(string == NULL) { 165 return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 166 } 167 168 EFUN(merlin16_INTERNAL_get_BER_data(sa__, time_ms, &ber_data_local)); 169 170 if(ber_data_local.prbs_chk_en == 0) { 171 USR_STRCPY(string,""); 172 return(ERR_CODE_NONE); 173 } else { 174 USR_STRCPY(string2," "); 175 } 176 177 if((COMPILER_64_HI(ber_data_local.num_errs) == 0) && 178 (COMPILER_64_LO(ber_data_local.num_errs) < 3) && 179 (ber_data_local.lcklost == 0)) { /* lcklost = 0 */ 180 USR_STRNCAT(string2,"<",1); 181 COMPILER_64_SET(ber_data_local.num_errs, 0, 3); 182 } else { 183 USR_STRNCAT(string2," ",1); 184 } 185 if(ber_data_local.lcklost == 1) { /* lcklost = 1 */ 186 USR_STRCPY(string," !Lock "); 187 } else { /* lcklost = 0 */ 188 uint16_t x=0,y=0,z=0,div; 189 190 if(COMPILER_64_GE(ber_data_local.num_errs, ber_data_local.num_bits)) { 191 x = 1;y=0;z=0; 192 }else { 193 uint64_t temp_dividend; 194 uint64_t temp_divisor; 195 while(1) { 196 COMPILER_64_COPY(temp_dividend, ber_data_local.num_errs); 197 COMPILER_64_SHL(temp_dividend, 1); 198 COMPILER_64_ADD_64(temp_dividend, ber_data_local.num_bits); 199 200 COMPILER_64_COPY(temp_divisor, ber_data_local.num_bits); 201 COMPILER_64_SHL(temp_divisor, 1); 202 203 COMPILER_64_UDIV_64(temp_dividend, temp_divisor); 204 205 div = (uint16_t) COMPILER_64_LO( temp_dividend ); 206 207 if(div>=10) { 208 break; 209 } 210 211 COMPILER_64_UMUL_32(ber_data_local.num_errs, 10); 212 z=z+1; 213 } 214 if(div>=100) { 215 div = div/10; 216 z=z-1; 217 } 218 x=div/10; 219 y = div - 10*x; 220 z=z-1; 221 } 222 USR_SPRINTF(string,"%s%d.%1de-%02d",string2,x,y,z); 223 224 } 225 return(ERR_CODE_NONE); 226 227 } 228 229 err_code_t merlin16_INTERNAL_get_BER_data(srds_access_t *sa__, uint16_t time_ms, struct ber_data_st *ber_data) { 230 uint8_t lcklost = 0; 231 uint32_t err_cnt= 0; 232 233 234 if(ber_data == NULL) { 235 return(ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 236 } 237 238 ESTM(ber_data->prbs_chk_en = rd_prbs_chk_en()); 239 if(ber_data->prbs_chk_en == 0) 240 return(ERR_CODE_NONE); 241 242 EFUN(merlin16_prbs_err_count_state(sa__, &err_cnt,&lcklost)); /* clear error counters */ 243 244 EFUN(USR_DELAY_MS(time_ms)); 245 EFUN(merlin16_prbs_err_count_state(sa__, &err_cnt,&lcklost)); 246 ber_data->lcklost = lcklost; 247 if(ber_data->lcklost == 0) { 248 uint32_t num_bits_per_ms=0; 249 EFUN(merlin16_INTERNAL_get_num_bits_per_ms(sa__,&num_bits_per_ms)); 250 COMPILER_64_SET(ber_data->num_bits, 0, num_bits_per_ms); 251 COMPILER_64_UMUL_32(ber_data->num_bits, time_ms); 252 COMPILER_64_SET(ber_data->num_errs, 0, err_cnt); 253 ESTM(lcklost = rd_prbs_chk_lock_lost_lh()); 254 } 255 256 257 258 return(ERR_CODE_NONE); 259 } 260 261 262 263 err_code_t merlin16_INTERNAL_get_p1_threshold(srds_access_t *sa__, int8_t *val) { 264 ESTM(*val = -rd_p1_eyediag_bin()); 265 return (ERR_CODE_NONE); 266 } 267 268 269 int16_t merlin16_INTERNAL_ladder_setting_to_mV(srds_access_t *sa__, int8_t ctrl, uint8_t range_250) { 270 uint16_t absv; /* Absolute value of ctrl */ 271 int16_t nlmv; /* Non-linear value */ 272 273 /* Get absolute value */ 274 absv = SRDS_ABS(ctrl); 275 276 { 277 if (range_250) { 278 /* 28nm range is 250mV, but 16nm range is 200mV */ 279 /* 200mV range, 6.5519mV linear units */ 280 nlmv = absv*190/29; 281 } 282 else { 283 /* 120mV range, 3.8854mV linear units */ 284 nlmv = absv*136/35; 285 } 286 } 287 /* Add sign and return */ 288 return( (ctrl>=0) ? nlmv : -nlmv); 289 } 290 291 292 err_code_t merlin16_INTERNAL_compute_bin(char var, char bin[]) { 293 if(!bin) { 294 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 295 } 296 297 switch (var) { 298 case '0': ENULL_STRCPY(bin,"0000"); 299 break; 300 case '1': ENULL_STRCPY(bin,"0001"); 301 break; 302 case '2': ENULL_STRCPY(bin,"0010"); 303 break; 304 case '3': ENULL_STRCPY(bin,"0011"); 305 break; 306 case '4': ENULL_STRCPY(bin,"0100"); 307 break; 308 case '5': ENULL_STRCPY(bin,"0101"); 309 break; 310 case '6': ENULL_STRCPY(bin,"0110"); 311 break; 312 case '7': ENULL_STRCPY(bin,"0111"); 313 break; 314 case '8': ENULL_STRCPY(bin,"1000"); 315 break; 316 case '9': ENULL_STRCPY(bin,"1001"); 317 break; 318 case 'a': 319 case 'A': ENULL_STRCPY(bin,"1010"); 320 break; 321 case 'b': 322 case 'B': ENULL_STRCPY(bin,"1011"); 323 break; 324 case 'c': 325 case 'C': ENULL_STRCPY(bin,"1100"); 326 break; 327 case 'd': 328 case 'D': ENULL_STRCPY(bin,"1101"); 329 break; 330 case 'e': 331 case 'E': ENULL_STRCPY(bin,"1110"); 332 break; 333 case 'f': 334 case 'F': ENULL_STRCPY(bin,"1111"); 335 break; 336 case '_': ENULL_STRCPY(bin,""); 337 break; 338 default : ENULL_STRCPY(bin,""); 339 EFUN_PRINTF(("ERROR: Invalid Hexadecimal Pattern\n")); 340 return (_error(ERR_CODE_CFG_PATT_INVALID_HEX)); 341 } 342 return (ERR_CODE_NONE); 343 } 344 345 346 err_code_t merlin16_INTERNAL_compute_hex(char bin[],uint8_t *hex) { 347 if(!hex) { 348 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 349 } 350 351 if (!USR_STRCMP(bin,"0000")) { 352 *hex = 0x0; 353 } 354 else if (!USR_STRCMP(bin,"0001")) { 355 *hex = 0x1; 356 } 357 else if (!USR_STRCMP(bin,"0010")) { 358 *hex = 0x2; 359 } 360 else if (!USR_STRCMP(bin,"0011")) { 361 *hex = 0x3; 362 } 363 else if (!USR_STRCMP(bin,"0100")) { 364 *hex = 0x4; 365 } 366 else if (!USR_STRCMP(bin,"0101")) { 367 *hex = 0x5; 368 } 369 else if (!USR_STRCMP(bin,"0110")) { 370 *hex = 0x6; 371 } 372 else if (!USR_STRCMP(bin,"0111")) { 373 *hex = 0x7; 374 } 375 else if (!USR_STRCMP(bin,"1000")) { 376 *hex = 0x8; 377 } 378 else if (!USR_STRCMP(bin,"1001")) { 379 *hex = 0x9; 380 } 381 else if (!USR_STRCMP(bin,"1010")) { 382 *hex = 0xA; 383 } 384 else if (!USR_STRCMP(bin,"1011")) { 385 *hex = 0xB; 386 } 387 else if (!USR_STRCMP(bin,"1100")) { 388 *hex = 0xC; 389 } 390 else if (!USR_STRCMP(bin,"1101")) { 391 *hex = 0xD; 392 } 393 else if (!USR_STRCMP(bin,"1110")) { 394 *hex = 0xE; 395 } 396 else if (!USR_STRCMP(bin,"1111")) { 397 *hex = 0xF; 398 } 399 else { 400 EFUN_PRINTF(("ERROR: Invalid Binary to Hex Conversion\n")); 401 *hex = 0x0; 402 return (_error(ERR_CODE_CFG_PATT_INVALID_BIN2HEX)); 403 } 404 return (ERR_CODE_NONE); 405 } 406 407 uint8_t merlin16_INTERNAL_stop_micro(srds_access_t *sa__, uint8_t graceful, err_code_t *err_code_p) { 408 uint8_t stop_state = 0; 409 410 if(!err_code_p) { 411 return(0xFF); 412 } 413 414 /* Log current micro stop status */ 415 EPSTM2((stop_state = rdv_usr_sts_micro_stopped()),0xFF); 416 417 /* Stop micro only if micro is not stopped currently */ 418 if (!(stop_state & 0x7F)) { 419 if (graceful) { 420 EPFUN2((merlin16_stop_rx_adaptation(sa__, 1)),0xFF); 421 } 422 else { 423 EPFUN2((merlin16_pmd_uc_control(sa__, CMD_UC_CTRL_STOP_IMMEDIATE,GRACEFUL_STOP_TIME)),0xFF); 424 } 425 } 426 427 /* Return the previous micro stop status */ 428 return(stop_state); 429 } 430 431 432 /* Repeater Only APIs (Not applicable to PMD) */ 433 434 435 436 /********************************************************/ 437 /* Global RAM access through Micro Register Interface */ 438 /********************************************************/ 439 /* Micro Global RAM Byte Read */ 440 uint8_t merlin16_INTERNAL_rdb_uc_var(srds_access_t *sa__, err_code_t *err_code_p, uint16_t addr) { 441 uint8_t rddata; 442 443 if(!err_code_p) { 444 return(0); 445 } 446 EPSTM(rddata = merlin16_rdb_uc_ram(sa__, err_code_p, addr)); /* Use Micro register interface for reading RAM */ 447 return (rddata); 448 } 449 450 /* Micro Global RAM Word Read */ 451 uint16_t merlin16_INTERNAL_rdw_uc_var(srds_access_t *sa__, err_code_t *err_code_p, uint16_t addr) { 452 uint16_t rddata; 453 454 if(!err_code_p) { 455 return(0); 456 } 457 if (addr%2 != 0) { /* Validate even address */ 458 *err_code_p = ERR_CODE_INVALID_RAM_ADDR; 459 USR_PRINTF(("Error incorrect addr x%04x\n",addr)); 460 return (0); 461 } 462 EPSTM(rddata = merlin16_rdw_uc_ram(sa__, err_code_p, (addr))); /* Use Micro register interface for reading RAM */ 463 return (rddata); 464 } 465 466 /* Micro Global RAM Byte Write */ 467 err_code_t merlin16_INTERNAL_wrb_uc_var(srds_access_t *sa__, uint16_t addr, uint8_t wr_val) { 468 469 return (merlin16_wrb_uc_ram(sa__, addr, wr_val)); /* Use Micro register interface for writing RAM */ 470 } 471 472 /* Micro Global RAM Word Write */ 473 err_code_t merlin16_INTERNAL_wrw_uc_var(srds_access_t *sa__, uint16_t addr, uint16_t wr_val) { 474 if (addr%2 != 0) { /* Validate even address */ 475 USR_PRINTF(("Error incorrect addr x%04x\n",addr)); 476 return (_error(ERR_CODE_INVALID_RAM_ADDR)); 477 } 478 return (merlin16_wrw_uc_ram(sa__, addr, wr_val)); /* Use Micro register interface for writing RAM */ 479 } 480 481 482 /***********************/ 483 /* Event Log Display */ 484 /***********************/ 485 err_code_t merlin16_INTERNAL_event_log_dump_callback(void *arg, uint8_t byte_count, uint16_t data) { 486 merlin16_INTERNAL_event_log_dump_state_t * const state_ptr = (merlin16_INTERNAL_event_log_dump_state_t *)arg; 487 const uint8_t bytes_per_row=16; 488 489 if (byte_count == 0) { 490 if (state_ptr->line_start_index != state_ptr->index) { 491 EFUN_PRINTF(("%*s %d\n", 4*(bytes_per_row - state_ptr->index + state_ptr->line_start_index), "", state_ptr->line_start_index)); 492 } 493 return (ERR_CODE_NONE); 494 } 495 if (byte_count == 1) { 496 /* There is a trailing byte in the event log. 497 * The simplest way to handle it is to print out a whole word, but mask 498 * the invalid upper byte. 499 */ 500 data &= 0xFF; 501 } 502 EFUN_PRINTF((" 0x%04x", ((data & 0xFF) << 8) | (data >> 8))); 503 state_ptr->index += 2; 504 if (state_ptr->index % bytes_per_row == 0) { 505 EFUN_PRINTF((" %d\n", state_ptr->line_start_index)); 506 state_ptr->line_start_index = state_ptr->index; 507 } 508 509 return(ERR_CODE_NONE); 510 } 511 512 err_code_t merlin16_INTERNAL_read_event_log_with_callback(srds_access_t *sa__, 513 uint8_t micro_num, 514 uint8_t bypass_micro, 515 void *arg, 516 err_code_t (*callback)(void *, uint8_t, uint16_t)) { 517 merlin16_info_t const * const merlin16_info_ptr = merlin16_INTERNAL_get_merlin16_info_ptr(); 518 uint16_t rd_idx; 519 uint8_t current_lane; 520 521 EFUN(merlin16_INTERNAL_verify_merlin16_info(merlin16_info_ptr, sa__)); 522 523 if (micro_num >= merlin16_info_ptr->micro_count) { 524 return (_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 525 } 526 /* Read Current lane so that it can be restored at the end of function */ 527 current_lane = merlin16_get_lane(sa__); 528 EFUN_PRINTF(("\n\n********************************************\n")); 529 EFUN_PRINTF(( "**** SERDES UC TRACE MEMORY DUMP ***********\n")); 530 EFUN_PRINTF(( "********************************************\n")); 531 532 if (bypass_micro) { 533 ESTM(rd_idx = rdcv_trace_mem_wr_idx()); 534 if (merlin16_info_ptr->trace_memory_descending_writes) { 535 ++rd_idx; 536 if (rd_idx >= merlin16_info_ptr->trace_mem_ram_size) { 537 rd_idx = 0; 538 } 539 } else { 540 if (rd_idx == 0) { 541 rd_idx = merlin16_info_ptr->trace_mem_ram_size; 542 } 543 --rd_idx; 544 } 545 } else { 546 /* Start Read to stop uC logging and read the word at last event written by uC */ 547 EFUN(merlin16_pmd_uc_cmd(sa__, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_START, GRACEFUL_STOP_TIME)); 548 ESTM(rd_idx = rdcv_trace_mem_rd_idx()); 549 } 550 551 EFUN_PRINTF(( "\n DEBUG INFO: trace memory read index = 0x%04x\n", rd_idx)); 552 553 EFUN_PRINTF((" DEBUG INFO: trace memory size = 0x%04x\n\n", merlin16_info_ptr->trace_mem_ram_size)); 554 555 if (merlin16_info_ptr->trace_memory_descending_writes) { 556 /* Micro writes trace memory using descending addresses. 557 * So read using ascending addresses using block read 558 */ 559 EFUN(merlin16_INTERNAL_rdblk_uc_generic_ram(sa__, 560 merlin16_info_ptr->trace_mem_ram_base + merlin16_info_ptr->grp_ram_size*micro_num, 561 merlin16_info_ptr->trace_mem_ram_size, 562 rd_idx, 563 merlin16_info_ptr->trace_mem_ram_size, 564 arg, 565 callback)); 566 } else { 567 /* Micro writes trace memory using descending addresses. 568 * So read using ascending addresses using block read 569 */ 570 EFUN(merlin16_INTERNAL_rdblk_uc_generic_ram_descending(sa__, 571 merlin16_info_ptr->trace_mem_ram_base + merlin16_info_ptr->grp_ram_size*micro_num, 572 merlin16_info_ptr->trace_mem_ram_size, 573 rd_idx, 574 merlin16_info_ptr->trace_mem_ram_size, 575 arg, 576 callback)); 577 } 578 579 if (!bypass_micro) { 580 /* Read Done to resume logging */ 581 EFUN(merlin16_pmd_uc_cmd(sa__, CMD_EVENT_LOG_READ, CMD_EVENT_LOG_READ_DONE, 50)); 582 } 583 EFUN(merlin16_set_lane(sa__,current_lane)); 584 return(ERR_CODE_NONE); 585 } 586 587 #ifdef TO_FLOATS 588 /* convert uint32_t to float8 */ 589 float8_t merlin16_INTERNAL_int32_to_float8(uint32_t input) { 590 int8_t cnt; 591 uint8_t output; 592 593 if(input == 0) { 594 return(0); 595 } else if(input == 1) { 596 return(0xe0); 597 } else { 598 cnt = 0; 599 input = input & 0x7FFFFFFF; /* get rid of MSB which may be lock indicator */ 600 do { 601 input = input << 1; 602 cnt++; 603 } while ((input & 0x80000000) == 0); 604 605 output = (uint8_t)((input & 0x70000000)>>23)+(31 - cnt%32); 606 return(output); 607 } 608 } 609 #endif 610 611 /* convert float8 to uint32_t */ 612 uint32_t merlin16_INTERNAL_float8_to_int32(float8_t input) { 613 uint32_t x; 614 if(input == 0) return(0); 615 x = (input>>5) + 8; 616 if((input & 0x1F) < 3) { 617 return(x>>(3-(input & 0x1f))); 618 } 619 return(x<<((input & 0x1F)-3)); 620 } 621 622 623 624 /* convert float12 to uint32 */ 625 uint32_t merlin16_INTERNAL_float12_to_uint32(uint8_t byte, uint8_t multi) { 626 627 return(((uint32_t)byte)<<multi); 628 } 629 630 #ifdef TO_FLOATS 631 /* convert uint32 to float12 */ 632 uint8_t merlin16_INTERNAL_uint32_to_float12(uint32_t input, uint8_t *multi) { 633 int8_t cnt; 634 uint8_t output; 635 if(!multi) { 636 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 637 } 638 639 if((input == 0) || (!multi)) { 640 *multi = 0; 641 return(0); 642 } else { 643 cnt = 0; 644 if(input > 0x007FFFFF) input = 0x007FFFFF; /* limit to 23bits so multi is 4 bits */ 645 do { 646 input = input << 1; 647 cnt++; 648 } while ((input & 0x80000000) == 0); 649 650 *multi = (31 - (cnt%32)); 651 if(*multi < 8) { 652 output = (uint8_t)((input & 0xFF000000)>>(24 + (7-*multi))); 653 *multi = 0; 654 } else { 655 output = (uint8_t)((input & 0xFF000000)>>24); 656 *multi = *multi - 7; 657 } 658 return(output); 659 } 660 } 661 #endif 662 663 err_code_t merlin16_INTERNAL_set_rx_pf_main(srds_access_t *sa__, uint8_t val) { 664 if (val > 15) { 665 return (_error(ERR_CODE_PF_INVALID)); 666 } 667 EFUN(WR_RX_PF_CTRL(val)); 668 return(ERR_CODE_NONE); 669 } 670 671 err_code_t merlin16_INTERNAL_get_rx_pf_main(srds_access_t *sa__, int8_t *val) { 672 ESTM(*val = (int8_t)RD_RX_PF_CTRL()); 673 return (ERR_CODE_NONE); 674 } 675 676 err_code_t merlin16_INTERNAL_set_rx_pf2(srds_access_t *sa__, uint8_t val) { 677 if (val > 7) { 678 return (_error(ERR_CODE_PF_INVALID)); 679 } 680 EFUN(WR_RX_PF2_CTRL(val)); 681 return(ERR_CODE_NONE); 682 } 683 684 err_code_t merlin16_INTERNAL_get_rx_pf2(srds_access_t *sa__, int8_t *val) { 685 ESTM(*val = (int8_t)RD_RX_PF2_CTRL()); 686 return (ERR_CODE_NONE); 687 } 688 689 690 err_code_t merlin16_INTERNAL_set_rx_vga(srds_access_t *sa__, uint8_t val) { 691 692 EFUN(merlin16_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 693 694 if (val > RX_VGA_CTRL_VAL_MAX) { 695 return (_error(ERR_CODE_VGA_INVALID)); 696 } 697 #if defined(RX_VGA_CTRL_VAL_MIN) && (RX_VGA_CTRL_VAL_MIN > 0) 698 if (val < RX_VGA_CTRL_VAL_MIN) { 699 return (_error(ERR_CODE_VGA_INVALID)); 700 } 701 #endif 702 703 EFUN(wr_hwtune_ovr_write_sel(0)); /* Configure hwtune_ovr_write_sel to VGA */ 704 EFUN(wr_hwtune_ovr_write_val(val<<3)); /* hwtune_ovr_write_val[8:3] are used to drive the analog control port */ 705 EFUN(wr_hwtune_ovr_write_en(1)); 706 return(ERR_CODE_NONE); 707 } 708 709 err_code_t merlin16_INTERNAL_get_rx_vga(srds_access_t *sa__, int8_t *val) { 710 ESTM(*val = (int8_t)rd_vga_bin()); 711 return (ERR_CODE_NONE); 712 } 713 714 715 err_code_t merlin16_INTERNAL_set_rx_dfe1(srds_access_t *sa__, int8_t val) { 716 EFUN(merlin16_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 717 718 { 719 int8_t tap_eo; 720 721 if (val > 63) { 722 return (_error(ERR_CODE_DFE1_INVALID)); 723 } 724 /* Compute tap1 even/odd component */ 725 tap_eo = 0; /* Not supporting dfe_dcd values */ 726 EFUN(wr_hwtune_ovr_write_sel(2)); /* Write tap1_odd */ 727 EFUN(wr_hwtune_ovr_write_val(tap_eo)); 728 EFUN(wr_hwtune_ovr_write_en(1)); 729 EFUN(wr_hwtune_ovr_write_sel(3)); /* Write tap1_even */ 730 EFUN(wr_hwtune_ovr_write_val(tap_eo)); 731 EFUN(wr_hwtune_ovr_write_en(1)); 732 EFUN(wr_hwtune_ovr_write_sel(1)); 733 EFUN(wr_hwtune_ovr_write_val(val-tap_eo)); /* Write the common tap */ 734 EFUN(wr_hwtune_ovr_write_en(1)); 735 } 736 return(ERR_CODE_NONE); 737 } 738 err_code_t merlin16_INTERNAL_get_rx_dfe1(srds_access_t *sa__, int8_t *val) { 739 ESTM(*val = (int8_t)(rd_dfe_1_e() + rd_dfe_1_cmn())); 740 return (ERR_CODE_NONE); 741 } 742 743 744 err_code_t merlin16_INTERNAL_set_rx_dfe2(srds_access_t *sa__, int8_t val) { 745 int8_t tap_eo; 746 747 if ((val > 31) || (val < -31)) { 748 return (_error(ERR_CODE_DFE2_INVALID)); 749 } 750 751 EFUN(merlin16_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 752 753 /* Compute tap2 odd/even component */ 754 tap_eo = 0; /* Not supporting dfe_dcd values */ 755 EFUN(wr_hwtune_ovr_write_sel(5)); /* Write tap2_odd */ 756 EFUN(wr_hwtune_ovr_write_val(tap_eo)); 757 EFUN(wr_hwtune_ovr_write_en(1)); 758 EFUN(wr_hwtune_ovr_write_sel(6)); /* Write tap2_even */ 759 EFUN(wr_hwtune_ovr_write_val(tap_eo)); 760 EFUN(wr_hwtune_ovr_write_en(1)); 761 EFUN(wr_hwtune_ovr_write_sel(4)); 762 EFUN(wr_hwtune_ovr_write_val(SRDS_ABS(val)-tap_eo));/* Write the common tap */ 763 EFUN(wr_hwtune_ovr_write_en(1)); 764 EFUN(wr_hwtune_ovr_write_sel(10)); /* Write tap2_even_sign */ 765 EFUN(wr_hwtune_ovr_write_val(val<0?1:0)); 766 EFUN(wr_hwtune_ovr_write_en(1)); 767 EFUN(wr_hwtune_ovr_write_sel(11)); /* Write tap2_odd_sign */ 768 EFUN(wr_hwtune_ovr_write_val(val<0?1:0)); 769 EFUN(wr_hwtune_ovr_write_en(1)); 770 return(ERR_CODE_NONE); 771 } 772 773 err_code_t merlin16_INTERNAL_get_rx_dfe2(srds_access_t *sa__, int8_t *val) { 774 ESTM(*val = rd_dfe_2_se() ? -(rd_dfe_2_e()+rd_dfe_2_cmn()) : (rd_dfe_2_e()+rd_dfe_2_cmn())); 775 return (ERR_CODE_NONE); 776 } 777 778 err_code_t merlin16_INTERNAL_set_rx_dfe3(srds_access_t *sa__, int8_t val) { 779 if ((val > 31) || (val < -31)) { 780 return (_error(ERR_CODE_DFE3_INVALID)); 781 } 782 783 EFUN(merlin16_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 784 785 EFUN(wr_hwtune_ovr_write_sel(7)); /* Write tap3 */ 786 EFUN(wr_hwtune_ovr_write_val(val)); 787 EFUN(wr_hwtune_ovr_write_en(1)); 788 return(ERR_CODE_NONE); 789 } 790 791 err_code_t merlin16_INTERNAL_get_rx_dfe3(srds_access_t *sa__, int8_t *val) { 792 ESTM(*val = rd_dfe_3_cmn()); 793 return (ERR_CODE_NONE); 794 } 795 796 err_code_t merlin16_INTERNAL_set_rx_dfe4(srds_access_t *sa__, int8_t val) { 797 if ((val > 15) || (val < -15)) { 798 return (_error(ERR_CODE_DFE4_INVALID)); 799 } 800 801 EFUN(merlin16_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 802 803 EFUN(wr_hwtune_ovr_write_sel(8)); /* Write tap4 */ 804 EFUN(wr_hwtune_ovr_write_val(val)); 805 EFUN(wr_hwtune_ovr_write_en(1)); 806 return(ERR_CODE_NONE); 807 } 808 809 err_code_t merlin16_INTERNAL_get_rx_dfe4(srds_access_t *sa__, int8_t *val) { 810 ESTM(*val = rd_dfe_4_cmn()); 811 return (ERR_CODE_NONE); 812 } 813 814 err_code_t merlin16_INTERNAL_set_rx_dfe5(srds_access_t *sa__, int8_t val) { 815 if ((val > 15) || (val < -15)) { 816 return (_error(ERR_CODE_DFE5_INVALID)); 817 } 818 819 EFUN(merlin16_INTERNAL_check_uc_lane_stopped(sa__)); /* make sure uC is stopped to avoid race conditions */ 820 821 EFUN(wr_hwtune_ovr_write_sel(9)); /* Write tap5 */ 822 EFUN(wr_hwtune_ovr_write_val(val)); 823 EFUN(wr_hwtune_ovr_write_en(1)); 824 return(ERR_CODE_NONE); 825 } 826 827 err_code_t merlin16_INTERNAL_get_rx_dfe5(srds_access_t *sa__, int8_t *val) { 828 ESTM(*val = rd_dfe_5_cmn()); 829 return (ERR_CODE_NONE); 830 } 831 832 833 834 835 836 err_code_t merlin16_INTERNAL_get_tx_pre(srds_access_t *sa__, int8_t *val) { 837 ESTM(*val = rd_cl72_txfir_pre()); 838 return (ERR_CODE_NONE); 839 } 840 841 842 err_code_t merlin16_INTERNAL_get_tx_main(srds_access_t *sa__, int8_t *val) { 843 ESTM(*val = rd_cl72_txfir_main()); 844 return (ERR_CODE_NONE); 845 } 846 847 848 err_code_t merlin16_INTERNAL_get_tx_post1(srds_access_t *sa__, int8_t *val) { 849 ESTM(*val = rd_cl72_txfir_post()); 850 return (ERR_CODE_NONE); 851 } 852 853 854 err_code_t merlin16_INTERNAL_get_tx_post2(srds_access_t *sa__, int8_t *val) { 855 ESTM(*val = rd_txfir_post2()); 856 return (ERR_CODE_NONE); 857 } 858 859 860 861 err_code_t merlin16_INTERNAL_core_clkgate(srds_access_t *sa__, uint8_t enable) { 862 863 if (enable) { 864 } 865 else { 866 } 867 return (ERR_CODE_NONE); 868 } 869 870 err_code_t merlin16_INTERNAL_lane_clkgate(srds_access_t *sa__, uint8_t enable) { 871 872 if (enable) { 873 /* Use frc/frc_val to force all RX and TX clk_vld signals to 0 */ 874 EFUN(wr_pmd_rx_clk_vld_frc_val(0x0)); 875 EFUN(wr_pmd_rx_clk_vld_frc(0x1)); 876 EFUN(wr_pmd_tx_clk_vld_frc_val(0x0)); 877 EFUN(wr_pmd_tx_clk_vld_frc(0x1)); 878 879 /* Use frc_on to force clkgate */ 880 EFUN(wr_ln_rx_s_clkgate_frc_on(0x1)); 881 882 EFUN(wr_ln_tx_s_clkgate_frc_on(0x1)); 883 884 } 885 else { 886 EFUN(wr_pmd_rx_clk_vld_frc_val(0x0)); 887 EFUN(wr_pmd_rx_clk_vld_frc(0x0)); 888 EFUN(wr_pmd_tx_clk_vld_frc_val(0x0)); 889 EFUN(wr_pmd_tx_clk_vld_frc(0x0)); 890 891 EFUN(wr_ln_rx_s_clkgate_frc_on(0x0)); 892 893 EFUN(wr_ln_tx_s_clkgate_frc_on(0x0)); 894 } 895 return (ERR_CODE_NONE); 896 } 897 898 /*-----------------------------------------------*/ 899 /* Get dynamic eye margin estimation values */ 900 /*-----------------------------------------------*/ 901 err_code_t merlin16_INTERNAL_get_eye_margin_est(srds_access_t *sa__, uint16_t *left_eye_mUI, uint16_t *right_eye_mUI, uint16_t *upper_eye_mV, uint16_t *lower_eye_mV) { 902 uint8_t ladder_range = 0; 903 ESTM(ladder_range = rd_p1_thresh_sel()); 904 ESTM(*left_eye_mUI = merlin16_INTERNAL_eye_to_mUI(sa__, rdv_usr_sts_heye_left())); 905 ESTM(*right_eye_mUI = merlin16_INTERNAL_eye_to_mUI(sa__, rdv_usr_sts_heye_right())); 906 ESTM(*upper_eye_mV = merlin16_INTERNAL_eye_to_mV(sa__, rdv_usr_sts_veye_upper(), ladder_range)); 907 ESTM(*lower_eye_mV = merlin16_INTERNAL_eye_to_mV(sa__, rdv_usr_sts_veye_lower(), ladder_range)); 908 909 return (ERR_CODE_NONE); 910 } 911 912 uint16_t merlin16_INTERNAL_eye_to_mUI(srds_access_t *sa__, uint8_t var) 913 { 914 /* var is in units of 1/512 th UI, so need to multiply by 1000/512 */ 915 return ((uint16_t)var)*125/64; 916 } 917 918 919 uint16_t merlin16_INTERNAL_eye_to_mV(srds_access_t *sa__, uint8_t var, uint8_t ladder_range) 920 { 921 /* find nearest two vertical levels */ 922 uint16_t vl = merlin16_INTERNAL_ladder_setting_to_mV(sa__, var/8, ladder_range); 923 uint16_t vu = merlin16_INTERNAL_ladder_setting_to_mV(sa__, SRDS_MIN(31,var/8+1), ladder_range); 924 return (vl + (vu-vl)*(var&7)/8); 925 } 926 927 err_code_t merlin16_INTERNAL_get_osr_mode(srds_access_t *sa__, merlin16_osr_mode_st *imode) { 928 merlin16_osr_mode_st mode; 929 930 ENULL_MEMSET(&mode, 0, sizeof(merlin16_osr_mode_st)); 931 932 if(!imode) 933 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 934 935 ESTM(mode.tx = rd_tx_osr_mode()); 936 ESTM(mode.rx = rd_rx_osr_mode()); 937 mode.tx_rx = 255; 938 #ifdef wr_ams_rx_rxclk_div2p5 /* Analog 2p5 OSR mode */ 939 { 940 uint8_t osr_2p5, osr_2p5_pwrup; 941 ESTM(osr_2p5 = rd_ams_tx_txclk_div2p5()); 942 ESTM(osr_2p5_pwrup = rd_ams_tx_spare_58()); 943 if ((mode.tx == MERLIN16_OSX1) && (osr_2p5 == 1) && (osr_2p5_pwrup == 1)) { 944 mode.tx = MERLIN16_OSX2P5; 945 } 946 ESTM(osr_2p5 = rd_ams_rx_rxclk_div2p5()); 947 ESTM(osr_2p5_pwrup = rd_ams_rx_spare_134()); 948 if ((mode.rx == MERLIN16_OSX1) && (osr_2p5 == 1) && (osr_2p5_pwrup == 1)) { 949 mode.rx = MERLIN16_OSX2P5; 950 } 951 } 952 #endif 953 *imode = mode; 954 return (ERR_CODE_NONE); 955 956 } 957 958 959 err_code_t merlin16_INTERNAL_pmd_lock_status(srds_access_t *sa__, uint8_t *pmd_lock, uint8_t *pmd_lock_chg) { 960 uint16_t rddata; 961 #if defined(reg_rd_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS) 962 ESTM(rddata = reg_rd_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS()); 963 ESTM(*pmd_lock = ex_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS__dbg_pmd_rx_lock(rddata)); 964 ESTM(*pmd_lock_chg = ex_TLB_RX_RXDBG_PMD_RX_LOCK_STATUS__dbg_pmd_rx_lock_change(rddata)); 965 #elif defined(reg_rd_TLB_RX_DBG_PMD_RX_LOCK_STATUS) 966 ESTM(rddata = reg_rd_TLB_RX_DBG_PMD_RX_LOCK_STATUS()); 967 ESTM(*pmd_lock = ex_TLB_RX_DBG_PMD_RX_LOCK_STATUS__dbg_pmd_rx_lock(rddata)); 968 ESTM(*pmd_lock_chg = ex_TLB_RX_DBG_PMD_RX_LOCK_STATUS__dbg_pmd_rx_lock_change(rddata)); 969 #else 970 #error "Unknown core for merlin16_INTERNAL_pmd_lock_status()" 971 #endif 972 return(ERR_CODE_NONE); 973 } 974 975 err_code_t merlin16_INTERNAL_sigdet_status(srds_access_t *sa__, uint8_t *sig_det, uint8_t *sig_det_chg) { 976 uint16_t rddata; 977 978 ESTM(rddata = reg_rd_SIGDET_SDSTATUS_0()); 979 ESTM(*sig_det = ex_SIGDET_SDSTATUS_0__signal_detect(rddata)); 980 ESTM(*sig_det_chg = ex_SIGDET_SDSTATUS_0__signal_detect_change(rddata)); 981 return(ERR_CODE_NONE); 982 } 983 984 err_code_t merlin16_INTERNAL_pll_lock_status(srds_access_t *sa__, uint8_t *pll_lock, uint8_t *pll_lock_chg) { 985 986 uint16_t rddata; 987 uint8_t pll_fail; 988 ESTM(rddata = reg_rdc_PLL_CAL_COM_STS_0()); 989 ESTM(*pll_lock = exc_PLL_CAL_COM_STS_0__pll_lock(rddata)); 990 ESTM(pll_fail = exc_PLL_CAL_COM_STS_0__pll_fail_stky(rddata)); 991 ESTM(*pll_lock_chg = ((*pll_lock ^ !exc_PLL_CAL_COM_STS_0__pll_lock_bar_stky(rddata)) | (*pll_lock ^ !pll_fail))); 992 return(ERR_CODE_NONE); 993 } 994 995 err_code_t merlin16_INTERNAL_read_lane_state(srds_access_t *sa__, merlin16_lane_state_st *istate) { 996 997 merlin16_lane_state_st state; 998 uint8_t ladder_range = 0; 999 1000 ENULL_MEMSET(&state, 0, sizeof(merlin16_lane_state_st)); 1001 1002 if(!istate) 1003 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 1004 1005 EFUN(merlin16_INTERNAL_pmd_lock_status(sa__,&state.rx_lock, &state.rx_lock_chg)); 1006 { 1007 err_code_t err_code = 0; 1008 state.stop_state = merlin16_INTERNAL_stop_micro(sa__,state.rx_lock,&err_code); 1009 if(err_code) USR_PRINTF(("Unable to stop microcontroller, following data is suspect\n")); 1010 } 1011 1012 { merlin16_osr_mode_st osr_mode; 1013 ENULL_MEMSET(&osr_mode, 0, sizeof(merlin16_osr_mode_st)); 1014 EFUN(merlin16_INTERNAL_get_osr_mode(sa__, &osr_mode)); 1015 state.osr_mode = osr_mode; 1016 } 1017 { 1018 struct merlin16_uc_lane_config_st lane_cfg; 1019 EFUN(merlin16_get_uc_lane_cfg(sa__, &lane_cfg)); 1020 state.ucv_config = lane_cfg.word; 1021 } 1022 ESTM(state.ucv_status = rdv_status_byte()); 1023 ESTM(state.reset_state = rd_rx_lane_dp_reset_state()); 1024 ESTM(state.tx_reset_state = rd_tx_lane_dp_reset_state()); 1025 EFUN(merlin16_INTERNAL_sigdet_status(sa__,&state.sig_det, &state.sig_det_chg)); 1026 ESTM(state.rx_ppm = rd_cdr_integ_reg()/84); 1027 ESTM(state.clk90 = rd_cnt_d_minus_m1()); 1028 ESTM(state.clkp1 = rd_cnt_d_minus_p1()); 1029 ESTM(state.br_pd_en = rd_br_pd_en()); 1030 /* drop the MSB, the result is actually valid modulo 128 */ 1031 /* Also flip the sign to account for d-m1, versus m1-d */ 1032 state.clk90 = state.clk90<<1; 1033 state.clk90 = -(state.clk90>>1); 1034 state.clkp1 = state.clkp1<<1; 1035 state.clkp1 = -(state.clkp1>>1); 1036 1037 EFUN(merlin16_INTERNAL_get_rx_pf_main(sa__, &state.pf_main)); 1038 ESTM(state.pf_hiz = rd_pf_hiz()); 1039 ESTM(state.pf2_ctrl = rd_pf2_lowp_ctrl()); 1040 EFUN(merlin16_INTERNAL_get_rx_vga(sa__, &state.vga)); 1041 ESTM(state.dc_offset = rd_dc_offset_bin()); 1042 ESTM(ladder_range = rd_p1_thresh_sel()); 1043 EFUN(merlin16_INTERNAL_get_p1_threshold(sa__, &state.p1_lvl_ctrl)); 1044 state.p1_lvl = merlin16_INTERNAL_ladder_setting_to_mV(sa__, state.p1_lvl_ctrl, ladder_range); 1045 state.m1_lvl = 0; 1046 1047 EFUN(merlin16_INTERNAL_get_rx_dfe1(sa__, &state.dfe1)); 1048 EFUN(merlin16_INTERNAL_get_rx_dfe2(sa__, &state.dfe2)); 1049 EFUN(merlin16_INTERNAL_get_rx_dfe3(sa__, &state.dfe3)); 1050 EFUN(merlin16_INTERNAL_get_rx_dfe4(sa__, &state.dfe4)); 1051 EFUN(merlin16_INTERNAL_get_rx_dfe5(sa__, &state.dfe5)); 1052 1053 ESTM(state.dfe1_dcd = rd_dfe_1_e()-rd_dfe_1_o()); 1054 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())); 1055 ESTM(state.pe = rd_p1_offset_evn_bin()); 1056 ESTM(state.ze = rd_data_offset_evn_bin()); 1057 ESTM(state.me = rd_m1_offset_evn_bin()); 1058 1059 ESTM(state.po = rd_p1_offset_odd_bin()); 1060 ESTM(state.zo = rd_data_offset_odd_bin()); 1061 ESTM(state.mo = rd_m1_offset_odd_bin()); 1062 1063 /* tx_ppm = register/10.84 */ 1064 ESTM(state.tx_ppm = (int16_t)(((int32_t)(rd_tx_pi_integ2_reg()))*3125/32768)); 1065 1066 EFUN(merlin16_INTERNAL_get_tx_pre(sa__, &state.txfir_pre)); 1067 EFUN(merlin16_INTERNAL_get_tx_main(sa__, &state.txfir_main)); 1068 EFUN(merlin16_INTERNAL_get_tx_post1(sa__, &state.txfir_post1)); 1069 EFUN(merlin16_INTERNAL_get_tx_post2(sa__, &state.txfir_post2)); 1070 EFUN(merlin16_INTERNAL_get_eye_margin_est(sa__, &state.heye_left, &state.heye_right, &state.veye_upper, &state.veye_lower)); 1071 1072 ESTM(state.soc_pos = rd_ams_rx_sigdet_offset_correction_pos()); 1073 ESTM(state.soc_neg = rd_ams_rx_sigdet_offset_correction_neg()); 1074 ESTM(state.link_time = (((uint32_t)rdv_usr_sts_link_time())*8)/10); /* convert from 80us to 0.1 ms units */ 1075 { 1076 /* read lock status at end and combine them to handle transient cases */ 1077 uint8_t rx_lock_at_end=0, rx_lock_chg_at_end=0; 1078 EFUN(merlin16_INTERNAL_pmd_lock_status(sa__,&rx_lock_at_end, &rx_lock_chg_at_end)); 1079 if (state.rx_lock != rx_lock_at_end) { 1080 USR_PRINTF(("rx_lock has chnaged while reading the lane state rx_lock_start=%d, rx_lock_chg_start=%d, rx_lock_at_end=%d, rx_lock_chg_at_end=%d\n", 1081 state.rx_lock, 1082 state.rx_lock_chg, 1083 rx_lock_at_end, 1084 rx_lock_chg_at_end)); 1085 } 1086 state.rx_lock &= rx_lock_at_end; 1087 state.rx_lock_chg |= rx_lock_chg_at_end; 1088 } 1089 1090 if (!state.stop_state) { 1091 EFUN(merlin16_stop_rx_adaptation(sa__, 0)); 1092 } 1093 1094 *istate = state; 1095 1096 1097 return (ERR_CODE_NONE); 1098 } 1099 1100 err_code_t merlin16_INTERNAL_display_lane_state_no_newline(srds_access_t *sa__) { 1101 uint16_t lane_idx; 1102 merlin16_lane_state_st state; 1103 1104 const char* e2s_osr_mode_enum[10] = { 1105 "x1 ", 1106 "x2 ", 1107 "x3 ", 1108 "x3.3 ", 1109 "x4 ", 1110 "x5 ", 1111 "x7.5 ", 1112 "x8 ", 1113 "x8.25", 1114 "x10 " 1115 }; 1116 1117 const char* e2s_tx_osr_mode_enum[10] = { 1118 "x1", 1119 "x2", 1120 "x3", 1121 "xT", 1122 "x4", 1123 "x5", 1124 "x7", 1125 "x8", 1126 "x9", 1127 "xA" 1128 }; 1129 1130 1131 ENULL_MEMSET(&state, 0, sizeof(merlin16_lane_state_st)); 1132 1133 EFUN(merlin16_INTERNAL_read_lane_state(sa__, &state)); 1134 1135 lane_idx = merlin16_get_lane(sa__); 1136 EFUN_PRINTF(("%2d ", lane_idx)); 1137 if(state.osr_mode.tx_rx != 255) { 1138 char *s; 1139 s = (char *)e2s_osr_mode_enum[state.osr_mode.tx_rx]; 1140 EFUN_PRINTF(("(%2s%s, 0x%04x, 0x%02x ,", (state.br_pd_en) ? "BR" : "OS", s, state.ucv_config,state.ucv_status)); 1141 } else { 1142 char *s; 1143 char *r; 1144 s = (char *)e2s_tx_osr_mode_enum[state.osr_mode.tx]; 1145 r = (char *)e2s_tx_osr_mode_enum[state.osr_mode.rx]; 1146 EFUN_PRINTF(("(%2s%s:%s, 0x%04x, 0x%02x ,", (state.br_pd_en) ? "BR" : "OS", s,r, state.ucv_config,state.ucv_status)); 1147 } 1148 EFUN_PRINTF((" %01x,%01x, %01x)",state.tx_reset_state,state.reset_state,state.stop_state)); 1149 EFUN_PRINTF((" %1d%s", state.sig_det, state.sig_det_chg ? "*" : " ")); 1150 EFUN_PRINTF((" %1d%s", state.rx_lock, state.rx_lock_chg ? "*" : " ")); 1151 EFUN_PRINTF(("%4d ", state.rx_ppm)); 1152 EFUN_PRINTF((" %3d ", state.clk90)); 1153 EFUN_PRINTF((" %3d ", state.clkp1)); 1154 EFUN_PRINTF((" %2d,%1d ", state.pf_main, state.pf2_ctrl)); 1155 EFUN_PRINTF((" %2d ", state.vga)); 1156 EFUN_PRINTF(("%3d ", state.dc_offset)); 1157 EFUN_PRINTF(("%3d ", state.p1_lvl)); 1158 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)); 1159 EFUN_PRINTF(("%3d,%3d,%3d,%3d,%3d,%3d ", state.ze, state.zo, state.pe, state.po, state.me, state.mo)); 1160 EFUN_PRINTF((" %4d ", state.tx_ppm)); 1161 EFUN_PRINTF((" %2d,%2d,%2d,%2d ", state.txfir_pre, state.txfir_main, state.txfir_post1, state.txfir_post2)); 1162 EFUN_PRINTF((" %3d,%3d,%3d,%3d ", state.heye_left, state.heye_right, state.veye_upper, state.veye_lower)); 1163 EFUN_PRINTF((" %2d,%2d ", state.soc_pos, state.soc_neg)); 1164 /* Check to see if link_time is max value after 80us to 0.1msec unit conversion */ 1165 if (state.link_time == 0xCCCC) { 1166 EFUN_PRINTF((" >%4d.%01d", state.link_time/10, state.link_time%10)); 1167 EFUN_PRINTF((" ")); 1168 } else { 1169 EFUN_PRINTF((" %4d.%01d", state.link_time/10, state.link_time%10)); 1170 EFUN_PRINTF((" ")); 1171 } 1172 EFUN(merlin16_INTERNAL_display_BER(sa__,100)); 1173 1174 return (ERR_CODE_NONE); 1175 } 1176 1177 1178 err_code_t merlin16_INTERNAL_read_core_state(srds_access_t *sa__, merlin16_core_state_st *istate) { 1179 merlin16_core_state_st state; 1180 struct merlin16_uc_core_config_st core_cfg; 1181 1182 ENULL_MEMSET(&state, 0, sizeof(merlin16_core_state_st)); 1183 ENULL_MEMSET(&core_cfg, 0, sizeof(struct merlin16_uc_core_config_st)); 1184 1185 if(!istate) 1186 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 1187 EFUN(merlin16_get_uc_core_config(sa__, &core_cfg)); 1188 /* pllpon_mux is read in case the rescal value is overriden. */ 1189 ESTM(state.rescal = rdc_pllpon_mux()); 1190 ESTM(state.core_reset = rdc_core_dp_reset_state()); 1191 ESTM(state.uc_active = rdc_uc_active()); 1192 ESTM(state.comclk_mhz = rdc_heartbeat_count_1us()); 1193 ESTM(state.pll_pwrdn = rdc_pll_pwrdn_or()); 1194 ESTM(state.ucode_version = rdcv_common_ucode_version()); 1195 ESTM(merlin16_version(&state.api_version)); 1196 ESTM(state.ucode_minor_version = rdcv_common_ucode_minor_version()); 1197 ESTM(state.afe_hardware_version = rdcv_afe_hardware_version()); 1198 ESTM(state.temp_idx = rdcv_temp_idx()); 1199 { int16_t die_temp = 0; 1200 EFUN(merlin16_read_die_temperature(sa__, &die_temp)); 1201 state.die_temp = die_temp; 1202 } 1203 ESTM(state.avg_tmon = _bin_to_degC(rdcv_avg_tmon_reg13bit()>>3)); 1204 state.vco_rate_mhz = (uint16_t)core_cfg.vco_rate_in_Mhz; 1205 ESTM(state.analog_vco_range = rdc_pll_range()); 1206 EFUN(merlin16_INTERNAL_read_pll_div(sa__, &state.pll_div)); 1207 EFUN(merlin16_INTERNAL_pll_lock_status(sa__, &state.pll_lock, &state.pll_lock_chg)); 1208 ESTM(state.core_status = rdcv_status_byte()); 1209 1210 *istate = state; 1211 return (ERR_CODE_NONE); 1212 } 1213 1214 1215 err_code_t merlin16_INTERNAL_display_core_state_no_newline(srds_access_t *sa__) { 1216 merlin16_core_state_st state; 1217 ENULL_MEMSET(&state , 0, sizeof(state )); 1218 EFUN(merlin16_INTERNAL_read_core_state(sa__, &state)); 1219 1220 if ((state.avg_tmon<-50)||(state.avg_tmon>135)) { 1221 EFUN_PRINTF(("\n*** WARNING: Core die temperature (LIVE_TEMP) out of bounds -50C to 130C\n")); 1222 } 1223 if ((state.rescal < 6) || (state.rescal > 13)) { 1224 EFUN_PRINTF(("\n*** WARNING: RESCAL value is out of bounds 6 to 13\n")); 1225 } 1226 1227 EFUN_PRINTF((" %02d " , merlin16_get_core(sa__))); 1228 EFUN_PRINTF((" %x,%02x " , state.core_reset, state.core_status)); 1229 EFUN_PRINTF((" %1d " , state.pll_pwrdn)); 1230 EFUN_PRINTF((" %1d " , state.uc_active)); 1231 EFUN_PRINTF((" %3d.%2dMHz" , (state.comclk_mhz/4),((state.comclk_mhz%4)*25))); /* comclk in Mhz = heartbeat_count_1us / 4 */ 1232 EFUN_PRINTF((" %4X_%02X " , state.ucode_version, state.ucode_minor_version)); 1233 EFUN_PRINTF((" %06X " , state.api_version)); 1234 EFUN_PRINTF((" 0x%02x " , state.afe_hardware_version)); 1235 EFUN_PRINTF((" %3dC " , state.die_temp)); 1236 EFUN_PRINTF((" (%02d)%3dC " , state.temp_idx, state.avg_tmon)); 1237 EFUN_PRINTF((" 0x%02x " , state.rescal)); 1238 EFUN_PRINTF((" %2d.%03dGHz " , state.vco_rate_mhz/1000, state.vco_rate_mhz % 1000)); 1239 EFUN_PRINTF((" %03d " , state.analog_vco_range)); 1240 EFUN(merlin16_INTERNAL_display_pll_to_divider(sa__, state.pll_div)); 1241 EFUN_PRINTF((" %01d%s " , state.pll_lock, state.pll_lock_chg ? "*" : " ")); 1242 1243 1244 return (ERR_CODE_NONE); 1245 } 1246 1247 1248 1249 /* returns 000111 (7 = 8-1), for n = 3 */ 1250 #define BFMASK(n) ((1<<((n)))-1) 1251 1252 err_code_t merlin16_INTERNAL_update_uc_lane_config_st(struct merlin16_uc_lane_config_st *st) { 1253 uint16_t in = st->word; 1254 st->field.lane_cfg_from_pcs = in & BFMASK(1); in >>= 1; 1255 st->field.an_enabled = in & BFMASK(1); in >>= 1; 1256 st->field.dfe_on = in & BFMASK(1); in >>= 1; 1257 st->field.force_brdfe_on = in & BFMASK(1); in >>= 1; 1258 st->field.media_type = in & BFMASK(2); in >>= 2; 1259 st->field.unreliable_los = in & BFMASK(1); in >>= 1; 1260 st->field.scrambling_dis = in & BFMASK(1); in >>= 1; 1261 st->field.cl72_auto_polarity_en = in & BFMASK(1); in >>= 1; 1262 st->field.cl72_restart_timeout_en = in & BFMASK(1); in >>= 1; 1263 st->field.reserved = in & BFMASK(6); in >>= 6; 1264 return(ERR_CODE_NONE); 1265 } 1266 err_code_t merlin16_INTERNAL_update_usr_ctrl_disable_functions_st(struct merlin16_usr_ctrl_disable_functions_st *st) { 1267 uint8_t in = st->byte; 1268 st->field.pf_adaptation = in & BFMASK(1); in >>= 1; 1269 st->field.dc_adaptation = in & BFMASK(1); in >>= 1; 1270 st->field.vga_adaptation = in & BFMASK(1); in >>= 1; 1271 st->field.slicer_offset_tuning = in & BFMASK(1); in >>= 1; 1272 st->field.clk90_offset_adaptation = in & BFMASK(1); in >>= 1; 1273 st->field.p1_level_tuning = in & BFMASK(1); in >>= 1; 1274 st->field.eye_adaptation = in & BFMASK(1); in >>= 1; 1275 st->field.all_adaptation = in & BFMASK(1); 1276 return ERR_CODE_NONE; 1277 } 1278 1279 1280 err_code_t merlin16_INTERNAL_update_usr_ctrl_disable_dfe_functions_st(struct merlin16_usr_ctrl_disable_dfe_functions_st *st) { 1281 uint8_t in = st->byte; 1282 st->field.dfe_tap1_adaptation = in & BFMASK(1); in >>= 1; 1283 st->field.dfe_tap2_adaptation = in & BFMASK(1); in >>= 1; 1284 st->field.dfe_tap3_adaptation = in & BFMASK(1); in >>= 1; 1285 st->field.dfe_tap4_adaptation = in & BFMASK(1); in >>= 1; 1286 st->field.dfe_tap5_adaptation = in & BFMASK(1); in >>= 1; 1287 st->field.dfe_tap1_dcd = in & BFMASK(1); in >>= 1; 1288 st->field.dfe_tap2_dcd = in & BFMASK(1); in >>= 1; 1289 return ERR_CODE_NONE; 1290 } 1291 /* word to fields, for display */ 1292 err_code_t merlin16_INTERNAL_update_uc_core_config_st(struct merlin16_uc_core_config_st *st) { 1293 uint16_t in = st->word; 1294 st->field.core_cfg_from_pcs = in & BFMASK(1); in >>= 1; 1295 st->field.vco_rate = in & BFMASK(5); in >>= 5; 1296 st->field.an_los_workaround = in & BFMASK(1); in >>= 1; 1297 st->field.reserved1 = in & BFMASK(1); in >>= 1; 1298 st->field.reserved2 = in & BFMASK(8); 1299 st->vco_rate_in_Mhz = VCO_RATE_TO_MHZ(st->field.vco_rate); 1300 return ERR_CODE_NONE; 1301 } 1302 1303 /* fields to word, to write into uC RAM */ 1304 err_code_t merlin16_INTERNAL_update_uc_core_config_word(struct merlin16_uc_core_config_st *st) { 1305 uint16_t in = 0; 1306 in <<= 8; in |= 0/*st->field.reserved2*/ & BFMASK(8); 1307 in <<= 1; in |= 0/*st->field.reserved1*/ & BFMASK(1); 1308 in <<= 1; in |= st->field.an_los_workaround & BFMASK(1); 1309 in <<= 5; in |= st->field.vco_rate & BFMASK(5); 1310 in <<= 1; in |= st->field.core_cfg_from_pcs & BFMASK(1); 1311 st->word = in; 1312 return ERR_CODE_NONE; 1313 } 1314 1315 err_code_t merlin16_INTERNAL_update_uc_lane_config_word(struct merlin16_uc_lane_config_st *st) { 1316 uint16_t in = 0; 1317 in <<= 6; in |= 0 /*st->field.reserved*/ & BFMASK(6); 1318 in <<= 1; in |= st->field.cl72_restart_timeout_en & BFMASK(1); 1319 in <<= 1; in |= st->field.cl72_auto_polarity_en & BFMASK(1); 1320 in <<= 1; in |= st->field.scrambling_dis & BFMASK(1); 1321 in <<= 1; in |= st->field.unreliable_los & BFMASK(1); 1322 in <<= 2; in |= st->field.media_type & BFMASK(2); 1323 in <<= 1; in |= st->field.force_brdfe_on & BFMASK(1); 1324 in <<= 1; in |= st->field.dfe_on & BFMASK(1); 1325 in <<= 1; in |= st->field.an_enabled & BFMASK(1); 1326 in <<= 1; in |= st->field.lane_cfg_from_pcs & BFMASK(1); 1327 st->word = in; 1328 return ERR_CODE_NONE; 1329 } 1330 err_code_t merlin16_INTERNAL_update_usr_ctrl_disable_functions_byte(struct merlin16_usr_ctrl_disable_functions_st *st) { 1331 uint8_t in = 0; 1332 in <<= 1; in |= st->field.all_adaptation & BFMASK(1); 1333 in <<= 1; in |= st->field.eye_adaptation & BFMASK(1); 1334 in <<= 1; in |= st->field.p1_level_tuning & BFMASK(1); 1335 in <<= 1; in |= st->field.clk90_offset_adaptation & BFMASK(1); 1336 in <<= 1; in |= st->field.slicer_offset_tuning & BFMASK(1); 1337 in <<= 1; in |= st->field.vga_adaptation & BFMASK(1); 1338 in <<= 1; in |= st->field.dc_adaptation & BFMASK(1); 1339 in <<= 1; in |= st->field.pf_adaptation & BFMASK(1); 1340 st->byte = in; 1341 return ERR_CODE_NONE; 1342 } 1343 1344 err_code_t merlin16_INTERNAL_update_usr_ctrl_disable_dfe_functions_byte(struct merlin16_usr_ctrl_disable_dfe_functions_st *st) { 1345 uint8_t in = 0; 1346 in <<= 1; in |= st->field.dfe_tap2_dcd & BFMASK(1); 1347 in <<= 1; in |= st->field.dfe_tap1_dcd & BFMASK(1); 1348 in <<= 1; in |= st->field.dfe_tap5_adaptation & BFMASK(1); 1349 in <<= 1; in |= st->field.dfe_tap4_adaptation & BFMASK(1); 1350 in <<= 1; in |= st->field.dfe_tap3_adaptation & BFMASK(1); 1351 in <<= 1; in |= st->field.dfe_tap2_adaptation & BFMASK(1); 1352 in <<= 1; in |= st->field.dfe_tap1_adaptation & BFMASK(1); 1353 st->byte = in; 1354 return ERR_CODE_NONE; 1355 } 1356 1357 #undef BFMASK 1358 1359 err_code_t merlin16_INTERNAL_check_uc_lane_stopped(srds_access_t *sa__) { 1360 1361 uint8_t is_micro_stopped; 1362 ESTM(is_micro_stopped = rdv_usr_sts_micro_stopped() || (rd_rx_lane_dp_reset_state() > 0)); 1363 if (!is_micro_stopped) { 1364 return(_error(ERR_CODE_UC_NOT_STOPPED)); 1365 } else { 1366 return(ERR_CODE_NONE); 1367 } 1368 } 1369 1370 err_code_t merlin16_INTERNAL_calc_patt_gen_mode_sel(uint8_t *mode_sel, uint8_t *zero_pad_len, uint8_t patt_length) { 1371 1372 if(!mode_sel) { 1373 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 1374 } 1375 if(!zero_pad_len) { 1376 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 1377 } 1378 1379 /* Select the correct Pattern generator Mode depending on Pattern length */ 1380 if (!(140 % patt_length)) { 1381 *mode_sel = 6; 1382 *zero_pad_len = 100; 1383 } 1384 else if (!(160 % patt_length)) { 1385 *mode_sel = 5; 1386 *zero_pad_len = 80; 1387 } 1388 else if (!(180 % patt_length)) { 1389 *mode_sel = 4; 1390 *zero_pad_len = 60; 1391 } 1392 else if (!(200 % patt_length)) { 1393 *mode_sel = 3; 1394 *zero_pad_len = 40; 1395 } 1396 else if (!(220 % patt_length)) { 1397 *mode_sel = 2; 1398 *zero_pad_len = 20; 1399 } 1400 else if (!(240 % patt_length)) { 1401 *mode_sel = 1; 1402 *zero_pad_len = 0; 1403 } else { 1404 EFUN_PRINTF(("ERROR: Unsupported Pattern Length\n")); 1405 return (_error(ERR_CODE_CFG_PATT_INVALID_PATT_LENGTH)); 1406 } 1407 return(ERR_CODE_NONE); 1408 } 1409 1410 /*-----------------------------------------*/ 1411 /* Write Core Config variables to uC RAM */ 1412 /*-----------------------------------------*/ 1413 1414 err_code_t merlin16_INTERNAL_set_uc_core_config(srds_access_t *sa__, struct merlin16_uc_core_config_st struct_val) { 1415 { uint8_t reset_state; 1416 ESTM(reset_state = rdc_core_dp_reset_state()); 1417 if(reset_state < 7) { 1418 EFUN_PRINTF(("ERROR: merlin16_INTERNAL_set_uc_core_config(..) called without core_dp_s_rstb=0\n")); 1419 return (_error(ERR_CODE_CORE_DP_NOT_RESET)); 1420 } 1421 } 1422 if(struct_val.vco_rate_in_Mhz > 0) { 1423 struct_val.field.vco_rate = MHZ_TO_VCO_RATE(struct_val.vco_rate_in_Mhz); 1424 } 1425 EFUN(merlin16_INTERNAL_update_uc_core_config_word(&struct_val)); 1426 EFUN(wrcv_config_word(struct_val.word)); 1427 return (ERR_CODE_NONE); 1428 } 1429 1430 /*---------------------*/ 1431 /* PLL Configuration */ 1432 /*---------------------*/ 1433 /** Extract the refclk frequency in Hz, based on a merlin16_pll_refclk_enum value. */ 1434 err_code_t _merlin16_get_refclk_in_hz(enum merlin16_pll_refclk_enum refclk, uint32_t *refclk_in_hz) { 1435 switch (refclk) { 1436 case MERLIN16_PLL_REFCLK_50MHZ: *refclk_in_hz = 50000000; break; 1437 case MERLIN16_PLL_REFCLK_125MHZ: *refclk_in_hz = 125000000; break; 1438 case MERLIN16_PLL_REFCLK_156P25MHZ: *refclk_in_hz = 156250000; break; 1439 case MERLIN16_PLL_REFCLK_161P1328125MHZ: *refclk_in_hz = 161132813; break; 1440 default: 1441 EFUN_PRINTF(("ERROR: Unknown refclk frequency: 0x%08X\n", (uint32_t)refclk)); 1442 *refclk_in_hz = 0xFFFFFFFF; 1443 return (_error(ERR_CODE_REFCLK_FREQUENCY_INVALID)); 1444 } 1445 return (ERR_CODE_NONE); 1446 } 1447 1448 /** Identify the ratio: 1449 * 1450 * (numerator / denominator) = (1000 / divisor) 1451 * 1452 * such that this has as little rounding error as possible: 1453 * 1454 * refclk_freq_hz = numerator * round(vco_freq_khz / denominator) 1455 * 1456 * This will yield the most accurate refclk_freq_hz. 1457 * Common values of vco_freq_khz are considered in this. 1458 */ 1459 static err_code_t _merlin16_get_divisor_ratio(enum merlin16_pll_div_enum div, uint16_t *numerator, uint16_t *denominator) 1460 { 1461 switch (div) { 1462 case MERLIN16_PLL_DIV_52P751515: *denominator = 162; *numerator = 3071; break; 1463 case MERLIN16_PLL_DIV_58P181818: *denominator = 16; *numerator = 275; break; 1464 case MERLIN16_PLL_DIV_62P060606: *denominator = 53; *numerator = 854; break; 1465 case MERLIN16_PLL_DIV_67P878788: *denominator = 56; *numerator = 825; break; 1466 case MERLIN16_PLL_DIV_66P460703: *denominator = 43; *numerator = 647; break; 1467 case MERLIN16_PLL_DIV_66P743079: *denominator = 58; *numerator = 869; break; 1468 case MERLIN16_PLL_DIV_68P570764: *denominator = 84; *numerator = 1225; break; 1469 case MERLIN16_PLL_DIV_68P856242: *denominator = 65; *numerator = 944; break; 1470 case MERLIN16_PLL_DIV_69P152458: *denominator = 102; *numerator = 1475; break; 1471 case MERLIN16_PLL_DIV_69P389964: *denominator = 124; *numerator = 1787; break; 1472 case MERLIN16_PLL_DIV_69P818182: *denominator = 96; *numerator = 1375; break; 1473 case MERLIN16_PLL_DIV_71P112952: *denominator = 177; *numerator = 2489; break; 1474 case MERLIN16_PLL_DIV_54P4: *denominator = 34; *numerator = 625; break; 1475 case MERLIN16_PLL_DIV_60: *denominator = 3; *numerator = 50; break; 1476 case MERLIN16_PLL_DIV_64: *denominator = 8; *numerator = 125; break; 1477 case MERLIN16_PLL_DIV_66: *denominator = 33; *numerator = 500; break; 1478 case MERLIN16_PLL_DIV_68: *denominator = 17; *numerator = 250; break; 1479 case MERLIN16_PLL_DIV_68P537598: *denominator = 127; *numerator = 1853; break; 1480 case MERLIN16_PLL_DIV_68P828796: *denominator = 104; *numerator = 1511; break; 1481 case MERLIN16_PLL_DIV_70: *denominator = 7; *numerator = 100; break; 1482 case MERLIN16_PLL_DIV_70P713596: *denominator = 106; *numerator = 1499; break; 1483 case MERLIN16_PLL_DIV_71P008: *denominator = 205; *numerator = 2887; break; 1484 case MERLIN16_PLL_DIV_71P31347: *denominator = 177; *numerator = 2482; break; 1485 case MERLIN16_PLL_DIV_71P5584: *denominator = 118; *numerator = 1649; break; 1486 case MERLIN16_PLL_DIV_72: *denominator = 9; *numerator = 125; break; 1487 case MERLIN16_PLL_DIV_73P335232: *denominator = 250; *numerator = 3409; break; 1488 case MERLIN16_PLL_DIV_73P6: *denominator = 46; *numerator = 625; break; 1489 case MERLIN16_PLL_DIV_75: *denominator = 3; *numerator = 40; break; 1490 case MERLIN16_PLL_DIV_80: *denominator = 2; *numerator = 25; break; 1491 case MERLIN16_PLL_DIV_82P5: *denominator = 33; *numerator = 400; break; 1492 case MERLIN16_PLL_DIV_85P671997: *denominator = 58; *numerator = 677; break; 1493 case MERLIN16_PLL_DIV_86P036: *denominator = 130; *numerator = 1511; break; 1494 case MERLIN16_PLL_DIV_87P5: *denominator = 7; *numerator = 80; break; 1495 case MERLIN16_PLL_DIV_88P392: *denominator = 83; *numerator = 939; break; 1496 case MERLIN16_PLL_DIV_88P76: *denominator = 199; *numerator = 2242; break; 1497 case MERLIN16_PLL_DIV_89P141838: *denominator = 243; *numerator = 2726; break; 1498 case MERLIN16_PLL_DIV_89P447998: *denominator = 128; *numerator = 1431; break; 1499 case MERLIN16_PLL_DIV_90: *denominator = 9; *numerator = 100; break; 1500 case MERLIN16_PLL_DIV_91P669037: *denominator = 296; *numerator = 3229; break; 1501 case MERLIN16_PLL_DIV_92: *denominator = 23; *numerator = 250; break; 1502 case MERLIN16_PLL_DIV_100: *denominator = 1; *numerator = 10; break; 1503 case MERLIN16_PLL_DIV_170: *denominator = 17; *numerator = 100; break; 1504 case MERLIN16_PLL_DIV_187P5: *denominator = 3; *numerator = 16; break; 1505 case MERLIN16_PLL_DIV_200: *denominator = 1; *numerator = 5; break; 1506 case MERLIN16_PLL_DIV_206P25: *denominator = 33; *numerator = 160; break; 1507 default: 1508 EFUN_PRINTF(("ERROR: Unknown divider value: 0x%08X\n", (uint32_t)div)); 1509 *numerator = 0; 1510 *denominator = 0; 1511 return (_error(ERR_CODE_PLL_DIV_INVALID)); 1512 } 1513 return (ERR_CODE_NONE); 1514 } 1515 1516 /** Get the Refclk frequency in Hz, based on the merlin16_pll_div_enum value and VCO frequency. */ 1517 static err_code_t _merlin16_get_refclk_from_div_vco(uint32_t *refclk_freq_hz, enum merlin16_pll_div_enum div, uint32_t vco_freq_khz, enum merlin16_pll_option_enum pll_option) { 1518 uint16_t numerator, denominator; 1519 EFUN(_merlin16_get_divisor_ratio(div, &numerator, &denominator)); 1520 *refclk_freq_hz = ((vco_freq_khz+(denominator>>1)) / denominator) * numerator; 1521 if (pll_option == MERLIN16_PLL_OPTION_REFCLK_DOUBLER_EN) *refclk_freq_hz /= 2; 1522 if (pll_option == MERLIN16_PLL_OPTION_REFCLK_DIV2_EN) *refclk_freq_hz *= 2; 1523 if (pll_option == MERLIN16_PLL_OPTION_REFCLK_DIV4_EN) *refclk_freq_hz *= 4; 1524 return (ERR_CODE_NONE); 1525 } 1526 1527 /** Get the VCO frequency in kHz, based on the reference clock frequency and merlin16_pll_div_enum value. */ 1528 err_code_t merlin16_INTERNAL_get_vco_from_refclk_div(uint32_t refclk_freq_hz, enum merlin16_pll_div_enum div, uint32_t *vco_freq_khz, enum merlin16_pll_option_enum pll_option) { 1529 uint16_t numerator, denominator; 1530 EFUN(_merlin16_get_divisor_ratio(div, &numerator, &denominator)); 1531 if (pll_option == MERLIN16_PLL_OPTION_REFCLK_DOUBLER_EN) refclk_freq_hz *= 2; 1532 if (pll_option == MERLIN16_PLL_OPTION_REFCLK_DIV2_EN) refclk_freq_hz /= 2; 1533 if (pll_option == MERLIN16_PLL_OPTION_REFCLK_DIV4_EN) refclk_freq_hz /= 4; 1534 *vco_freq_khz = ((refclk_freq_hz + (numerator>>1)) / numerator) * denominator; 1535 return (ERR_CODE_NONE); 1536 } 1537 1538 /* Boundaries for allowed VCO frequency */ 1539 # define SERDES_VCO_FREQ_KHZ_MIN ( 8500000) 1540 # define SERDES_VCO_FREQ_KHZ_MAX (12500000) 1541 1542 /* Allowed tolerance in resultant VCO frequency when auto-determining divider value */ 1543 # define SERDES_VCO_FREQ_KHZ_TOLERANCE (4000) 1544 1545 /* The allowed PLL divider values */ 1546 static const enum merlin16_pll_div_enum _merlin16_div_candidates[] = { 1547 MERLIN16_PLL_DIV_52P751515, 1548 MERLIN16_PLL_DIV_54P4, 1549 MERLIN16_PLL_DIV_58P181818, 1550 MERLIN16_PLL_DIV_60, 1551 MERLIN16_PLL_DIV_62P060606, 1552 MERLIN16_PLL_DIV_64, 1553 MERLIN16_PLL_DIV_66, 1554 MERLIN16_PLL_DIV_66P460703, 1555 MERLIN16_PLL_DIV_66P743079, 1556 MERLIN16_PLL_DIV_67P878788, 1557 MERLIN16_PLL_DIV_68, 1558 MERLIN16_PLL_DIV_68P537598, 1559 MERLIN16_PLL_DIV_68P570764, 1560 MERLIN16_PLL_DIV_68P828796, 1561 MERLIN16_PLL_DIV_68P856242, 1562 MERLIN16_PLL_DIV_69P152458, 1563 MERLIN16_PLL_DIV_69P389964, 1564 MERLIN16_PLL_DIV_69P818182, 1565 MERLIN16_PLL_DIV_70, 1566 MERLIN16_PLL_DIV_70P713596, 1567 MERLIN16_PLL_DIV_71P008, 1568 MERLIN16_PLL_DIV_71P112952, 1569 MERLIN16_PLL_DIV_71P31347, 1570 MERLIN16_PLL_DIV_71P5584, 1571 MERLIN16_PLL_DIV_72, 1572 MERLIN16_PLL_DIV_73P335232, 1573 MERLIN16_PLL_DIV_73P6, 1574 MERLIN16_PLL_DIV_75, 1575 MERLIN16_PLL_DIV_80, 1576 MERLIN16_PLL_DIV_82P5, 1577 MERLIN16_PLL_DIV_85P671997, 1578 MERLIN16_PLL_DIV_86P036, 1579 MERLIN16_PLL_DIV_87P5, 1580 MERLIN16_PLL_DIV_88P392, 1581 MERLIN16_PLL_DIV_88P76, 1582 MERLIN16_PLL_DIV_89P141838, 1583 MERLIN16_PLL_DIV_89P447998, 1584 MERLIN16_PLL_DIV_90, 1585 MERLIN16_PLL_DIV_91P669037, 1586 MERLIN16_PLL_DIV_92, 1587 MERLIN16_PLL_DIV_100, 1588 MERLIN16_PLL_DIV_170, 1589 MERLIN16_PLL_DIV_187P5, 1590 MERLIN16_PLL_DIV_200, 1591 MERLIN16_PLL_DIV_206P25 1592 }; 1593 1594 static const uint8_t _merlin16_div_candidates_count = sizeof(_merlin16_div_candidates) / sizeof(_merlin16_div_candidates[0]); 1595 1596 static err_code_t _merlin16_check_div(enum merlin16_pll_div_enum div) { 1597 uint8_t i, found = 0; 1598 for (i=0; i<_merlin16_div_candidates_count; i++) { 1599 found |= div == _merlin16_div_candidates[i]; 1600 } 1601 if (!found) { 1602 EFUN_PRINTF(("ERROR: Invalid divider value: 0x%08X\n", (uint32_t)div)); 1603 return (_error(ERR_CODE_PLL_DIV_INVALID)); 1604 } 1605 return (ERR_CODE_NONE); 1606 } 1607 1608 static err_code_t _merlin16_check_vco_freq_khz(uint32_t vco_freq_khz) { 1609 if (vco_freq_khz < SERDES_VCO_FREQ_KHZ_MIN - SERDES_VCO_FREQ_KHZ_TOLERANCE) { 1610 EFUN_PRINTF(("ERROR: VCO frequency too low: %d kHz is lower than minimum (%d kHz)\n", vco_freq_khz, SERDES_VCO_FREQ_KHZ_MIN)); 1611 return (_error(ERR_CODE_VCO_FREQUENCY_INVALID)); 1612 } 1613 if (vco_freq_khz > SERDES_VCO_FREQ_KHZ_MAX + SERDES_VCO_FREQ_KHZ_TOLERANCE) { 1614 EFUN_PRINTF(("ERROR: VCO frequency too high: %d kHz is higher than maximum (%d kHz)\n", vco_freq_khz, SERDES_VCO_FREQ_KHZ_MAX)); 1615 return (_error(ERR_CODE_VCO_FREQUENCY_INVALID)); 1616 } 1617 return (ERR_CODE_NONE); 1618 } 1619 1620 /** Find the entry out of _merlin16_div_candidates that is closest to matching refclk_freq_hz and vco_freq_khz. */ 1621 static err_code_t _merlin16_get_div(uint32_t refclk_freq_hz, uint32_t vco_freq_khz, enum merlin16_pll_div_enum *div, enum merlin16_pll_option_enum pll_option) { 1622 int32_t vco_freq_khz_min_error = 0x7FFFFFFF; 1623 uint8_t i; 1624 for (i=0; i<_merlin16_div_candidates_count; i++) { 1625 uint32_t actual_vco_freq_khz = 0; 1626 int32_t vco_freq_khz_error; 1627 EFUN(merlin16_INTERNAL_get_vco_from_refclk_div(refclk_freq_hz, _merlin16_div_candidates[i], &actual_vco_freq_khz, pll_option)); 1628 vco_freq_khz_error = vco_freq_khz - actual_vco_freq_khz; 1629 vco_freq_khz_error = SRDS_ABS(vco_freq_khz_error); 1630 if (vco_freq_khz_min_error > vco_freq_khz_error) { 1631 vco_freq_khz_min_error = vco_freq_khz_error; 1632 *div = _merlin16_div_candidates[i]; 1633 } 1634 } 1635 if (vco_freq_khz_min_error == 0xFFFFFFFF) { 1636 return (_error(ERR_CODE_CONFLICTING_PARAMETERS)); 1637 } 1638 return (ERR_CODE_NONE); 1639 } 1640 1641 err_code_t merlin16_INTERNAL_resolve_pll_parameters(enum merlin16_pll_refclk_enum refclk, 1642 uint32_t *refclk_freq_hz, 1643 enum merlin16_pll_div_enum *div, 1644 uint32_t *vco_freq_khz, 1645 enum merlin16_pll_option_enum pll_option) { 1646 1647 /* Parameter value and consistency checks */ 1648 const uint8_t given_param_count = (((refclk == MERLIN16_PLL_REFCLK_UNKNOWN) ? 0 : 1) 1649 + ((*div == MERLIN16_PLL_DIV_UNKNOWN) ? 0 : 1) 1650 + ((*vco_freq_khz == 0) ? 0 : 1)); 1651 const uint32_t original_vco_freq_khz = *vco_freq_khz; 1652 enum merlin16_pll_div_enum auto_div = MERLIN16_PLL_DIV_UNKNOWN; 1653 char*pll_option_e2s[] = {"no", "refclk_x2", "refclk_div2", "refclk_div4"}; 1654 COMPILER_REFERENCE(pll_option_e2s); 1655 1656 /* Verify that at least two of the three parameters is given. */ 1657 if (given_param_count < 2) { 1658 return (_error(ERR_CODE_INSUFFICIENT_PARAMETERS)); 1659 } 1660 1661 /* Skip verification if option is selected. Error if all parameters not given. */ 1662 if (pll_option == MERLIN16_PLL_OPTION_DISABLE_VERIFY) { 1663 if (given_param_count < 3) { 1664 return (_error(ERR_CODE_INSUFFICIENT_PARAMETERS)); 1665 } else { 1666 EFUN(_merlin16_get_refclk_in_hz(refclk, refclk_freq_hz)); 1667 return(ERR_CODE_NONE); 1668 } 1669 } 1670 1671 /* The refclk value is checked in various functions below. */ 1672 1673 /* Verify that the requested div value is allowed. */ 1674 if (*div != MERLIN16_PLL_DIV_UNKNOWN) { 1675 EFUN(_merlin16_check_div(*div)); 1676 } 1677 1678 /* Verify that the requested VCO frequency is allowed. */ 1679 if (*vco_freq_khz != 0) { 1680 EFUN(_merlin16_check_vco_freq_khz(*vco_freq_khz)); 1681 } 1682 1683 if (refclk == MERLIN16_PLL_REFCLK_UNKNOWN) { 1684 /* Determine refclk from vco frequency and div */ 1685 EFUN(_merlin16_get_refclk_from_div_vco(refclk_freq_hz, *div, *vco_freq_khz, pll_option)); 1686 } else { 1687 EFUN(_merlin16_get_refclk_in_hz(refclk, refclk_freq_hz)); 1688 } 1689 1690 if (*vco_freq_khz == 0) { 1691 /* Determine VCO frequency from refclk and divider */ 1692 EFUN(merlin16_INTERNAL_get_vco_from_refclk_div(*refclk_freq_hz, *div, vco_freq_khz, pll_option)); 1693 } 1694 1695 /* Determine divider from vco frequency and refclk. 1696 * This is done even if the div was provided, because if it is, 1697 * we still want to check whether the parameters are conflicting. 1698 */ 1699 EFUN(_merlin16_get_div(*refclk_freq_hz, *vco_freq_khz, &auto_div, pll_option)); 1700 if (*div == MERLIN16_PLL_DIV_UNKNOWN) { 1701 /* Use the auto-determined divider value, since the divider was not supplied. */ 1702 *div = auto_div; 1703 1704 /* Determine resultant VCO frequency from refclk and divider */ 1705 EFUN(merlin16_INTERNAL_get_vco_from_refclk_div(*refclk_freq_hz, *div, vco_freq_khz, pll_option)); 1706 } 1707 1708 /* Verify the resultant VCO frequency */ 1709 EFUN(_merlin16_check_vco_freq_khz(*vco_freq_khz)); 1710 1711 /* Verify that the requested VCO frequency is delivered. */ 1712 if ((original_vco_freq_khz != 0) 1713 && ((*vco_freq_khz < original_vco_freq_khz - SERDES_VCO_FREQ_KHZ_TOLERANCE) 1714 || (*vco_freq_khz > original_vco_freq_khz + SERDES_VCO_FREQ_KHZ_TOLERANCE))) { 1715 EFUN_PRINTF(("ERROR: Could not achieve requested VCO frequency of %d kHz.\n Refclk is %d Hz, %s option enabled, and auto-determined divider is 0x%08X, yielding a VCO frequency of %d kHz.\n", 1716 original_vco_freq_khz, *refclk_freq_hz, pll_option_e2s[pll_option], *div, *vco_freq_khz)); 1717 return (_error(ERR_CODE_VCO_FREQUENCY_INVALID)); 1718 } 1719 1720 /* Verify the auto-determined divider value. */ 1721 if (auto_div != *div) { 1722 EFUN_PRINTF(("ERROR: Conflicting PLL parameters: refclk is %d Hz, %s option enabled, divider is 0x%08X, and VCO frequency is %d kHz.\n Expected divider is 0x%08X\n", 1723 *refclk_freq_hz, pll_option_e2s[pll_option], *div, *vco_freq_khz, auto_div)); 1724 return (_error(ERR_CODE_CONFLICTING_PARAMETERS)); 1725 } 1726 1727 return (ERR_CODE_NONE); 1728 } 1729 1730 err_code_t merlin16_INTERNAL_display_pll_to_divider(srds_access_t *sa__, uint32_t div) { 1731 /* Adjust these to increase or decrease the number of digits to the right 1732 * of the decimal point. 1733 */ 1734 const uint8_t decimal_digits = 4; 1735 const uint32_t ten_to_the_decimal_digits = 10000; /* 10**decimal_digits */ 1736 1737 /* Not a const, because of carry logic below. */ 1738 uint16_t div_integer = SRDS_INTERNAL_GET_PLL_DIV_INTEGER(div); 1739 1740 if (SRDS_INTERNAL_IS_PLL_DIV_FRACTIONAL(div)) { 1741 /* fraction_num will have this many bits (ending at bit 0). */ 1742 const uint8_t fraction_num_width = 28; 1743 const uint32_t fraction_num = SRDS_INTERNAL_GET_PLL_DIV_FRACTION_NUM(div, fraction_num_width); 1744 1745 /* Identify the number that, when printed with left-padded zeros, 1746 * becomes the digits to the right of the decimal point. 1747 * 1748 * This value can be obtained by dividing fraction_num by: 1749 * 1750 * (2^fraction_num_width)/(10^decimal_digits) 1751 */ 1752 const uint32_t divisor = (((1 << fraction_num_width) + (ten_to_the_decimal_digits>>1)) 1753 / ten_to_the_decimal_digits); 1754 uint32_t fraction_as_int = (fraction_num + (divisor>>1)) / divisor; 1755 1756 /* In case the rounding above caused the fractional portion to overflow 1757 * (e.g. 4.9999999999 becomes 5.0000), implement the carry into the 1758 * integer portion. 1759 */ 1760 if (fraction_as_int >= ten_to_the_decimal_digits) { 1761 fraction_as_int -= ten_to_the_decimal_digits; 1762 ++div_integer; 1763 } 1764 1765 EFUN_PRINTF(("%3d.%0*d", div_integer, decimal_digits, fraction_as_int)); 1766 } else { 1767 const uint8_t left_spaces = (decimal_digits + 1) >> 1; 1768 COMPILER_REFERENCE(left_spaces); 1769 EFUN_PRINTF(("%*s%3d%*s", left_spaces, "", div_integer, decimal_digits - left_spaces + 1, "")); 1770 } 1771 return(ERR_CODE_NONE); 1772 } 1773 1774 1775 err_code_t merlin16_INTERNAL_print_uc_dsc_error(srds_access_t *sa__, enum srds_pmd_uc_cmd_enum cmd) { 1776 uint32_t supp_info; 1777 1778 ESTM(supp_info = (rd_uc_dsc_supp_info()) & 0xFF); 1779 switch (SUPP_INFO_TO_ERROR_CODE(supp_info)) { 1780 case UC_CMD_ERROR_INVALID_COMMAND: 1781 ESTM_PRINTF(("ERROR : UC reported invalid command %d. (other_info = 0x%X)\n", 1782 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1783 break; 1784 case UC_CMD_ERROR_BUSY: 1785 ESTM_PRINTF(("ERROR : UC reported busy for command %d. (other_info = 0x%X)\n", 1786 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1787 break; 1788 case UC_CMD_ERROR_GET_EYE_SAMPLE_ERROR: 1789 ESTM_PRINTF(("ERROR : UC reported error in getting eye sample. (command %d, other_info = 0x%X)\n", 1790 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1791 break; 1792 case UC_CMD_ERROR_PRBS_NOT_LOCKED: 1793 ESTM_PRINTF(("ERROR : UC reported PRBS not locked. (command %d, other_info = 0x%X)\n", 1794 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1795 break; 1796 case UC_CMD_ERROR_COMMAND_IN_PROGRESS: 1797 ESTM_PRINTF(("ERROR : UC reported command already in progress. (command %d, other_info = 0x%X)\n", 1798 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1799 break; 1800 case UC_CMD_ERROR_INVALID_MODE: 1801 ESTM_PRINTF(("ERROR : UC reported invalid mode for command %d. (other_info = 0x%X)\n", 1802 cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1803 break; 1804 default: 1805 ESTM_PRINTF(("ERROR : UC reported unknown error 0x%X for command %d. (other_info = 0x%X)\n", 1806 SUPP_INFO_TO_ERROR_CODE(supp_info), cmd, SUPP_INFO_TO_OTHER_INFO(supp_info))); 1807 } 1808 /* Cleanup cmd register */ 1809 EFUN(reg_wr_DSC_A_DSC_UC_CTRL(0x80)); 1810 EFUN(wr_uc_dsc_data(0)); 1811 1812 return(ERR_CODE_NONE); 1813 } 1814 1815 /******************************************/ 1816 /* Serdes Register field Poll functions */ 1817 /******************************************/ 1818 1819 #ifndef CUSTOM_REG_POLLING 1820 /* poll for microcontroller to populate the dsc_data register */ 1821 err_code_t merlin16_INTERNAL_poll_diag_done(srds_access_t *sa__, uint16_t *status, uint32_t timeout_ms) { 1822 uint8_t loop; 1823 1824 if(!status) { 1825 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 1826 } 1827 1828 for(loop=0;loop < 100; loop++) { 1829 ESTM(*status=rdv_usr_diag_status()); 1830 1831 if((*status & 0x8000) > 0) { 1832 return(ERR_CODE_NONE); 1833 } 1834 if(loop>10) { 1835 EFUN(USR_DELAY_US(10*timeout_ms)); 1836 } 1837 } 1838 return(_error(ERR_CODE_DIAG_TIMEOUT)); 1839 } 1840 /** Poll for field "uc_dsc_ready_for_cmd" = 1 [Return Val => Error_code (0 = Polling Pass)] */ 1841 err_code_t merlin16_INTERNAL_poll_uc_dsc_ready_for_cmd_equals_1(srds_access_t *sa__, uint32_t timeout_ms, enum srds_pmd_uc_cmd_enum cmd) { 1842 /* read quickly for 10 tries */ 1843 uint16_t loop; 1844 1845 for (loop = 0; loop < 100; loop++) { 1846 uint16_t rddata; 1847 ESTM(rddata = reg_rd_DSC_A_DSC_UC_CTRL()); 1848 if (rddata & 0x0080) { /* bit 7 is uc_dsc_ready_for_cmd */ 1849 if (rddata & 0x0040) { /* bit 6 is uc_dsc_error_found */ 1850 EFUN(merlin16_INTERNAL_print_uc_dsc_error(sa__, cmd)); 1851 return(_error(ERR_CODE_UC_CMD_RETURN_ERROR)); 1852 } 1853 return (ERR_CODE_NONE); 1854 } 1855 if(loop>10) { 1856 EFUN(USR_DELAY_US(10*timeout_ms)); 1857 } 1858 } 1859 EFUN_PRINTF(("ERROR : DSC ready for command is not working, applying workaround and getting debug info !\n")); 1860 DISP(rd_uc_dsc_supp_info()); 1861 DISP(rd_uc_dsc_gp_uc_req()); 1862 DISP(rd_dsc_state()); 1863 ESTM_PRINTF(("Uc Core Status Byte = 0x%x\n",rdcv_status_byte())); 1864 DISP(rdv_usr_sts_micro_stopped()); 1865 /* DISP(rdv_stop_graceful_trigger()); */ 1866 /* artifically terminate the command to re-enable the command interface */ 1867 EFUN(wr_uc_dsc_ready_for_cmd(0x1)); 1868 return (_error(ERR_CODE_POLLING_TIMEOUT)); /* Error Code for polling timeout */ 1869 } 1870 1871 /* Poll for field "dsc_state" = DSC_STATE_UC_TUNE [Return Val => Error_code (0 = Polling Pass)] */ 1872 err_code_t merlin16_INTERNAL_poll_dsc_state_equals_uc_tune(srds_access_t *sa__, uint32_t timeout_ms) { 1873 uint16_t loop; 1874 uint16_t dsc_state; 1875 /* poll 10 times to avoid longer delays later */ 1876 for (loop = 0; loop < 100; loop++) { 1877 ESTM(dsc_state = rd_dsc_state()); 1878 if (dsc_state == DSC_STATE_UC_TUNE) { 1879 return (ERR_CODE_NONE); 1880 } 1881 if(loop>10) { 1882 EFUN(USR_DELAY_US(10*timeout_ms)); 1883 } 1884 } 1885 ESTM_PRINTF(("DSC_STATE = %d\n", rd_dsc_state())); 1886 return (_error(ERR_CODE_POLLING_TIMEOUT)); /* Error Code for polling timeout */ 1887 } 1888 1889 /* Poll for field "st_afe_tx_fifo_resetb" = 1 [Return Val => Error_code (0 = Polling Pass)] */ 1890 err_code_t merlin16_INTERNAL_poll_st_afe_tx_fifo_resetb_equals_1(srds_access_t *sa__, uint32_t timeout_ms) { 1891 uint16_t loop; 1892 1893 for (loop = 0; loop <= 100; loop++) { 1894 uint8_t st_afe_tx_fifo_resetb; 1895 ESTM(st_afe_tx_fifo_resetb = rd_st_afe_tx_fifo_resetb()); 1896 if (st_afe_tx_fifo_resetb) { 1897 return (ERR_CODE_NONE); 1898 } 1899 EFUN(USR_DELAY_US(10*timeout_ms)); 1900 } 1901 return (_error(ERR_CODE_POLLING_TIMEOUT)); /* Error Code for polling timeout */ 1902 } 1903 1904 /* Poll for field "micro_ra_initdone" = 1 [Return Val => Error_code (0 = Polling Pass)] */ 1905 err_code_t merlin16_INTERNAL_poll_micro_ra_initdone(srds_access_t *sa__, uint32_t timeout_ms) { 1906 uint16_t loop; 1907 1908 uint8_t result; 1909 for (loop = 0; loop <= 100; loop++) { 1910 ESTM(result = rdc_micro_ra_initdone()); 1911 if (result) { 1912 return (ERR_CODE_NONE); 1913 } 1914 EFUN(USR_DELAY_US(10*timeout_ms)); 1915 } 1916 return (_error(ERR_CODE_POLLING_TIMEOUT)); /* Error Code for polling timeout */ 1917 } 1918 1919 #endif /* CUSTOM_REG_POLLING */ 1920 1921 1922 int merlin16_INTERNAL_get_endian_offset(uint8_t *addr) { 1923 const int endian_const = 1; 1924 return ((*(char*)&endian_const) == 0) ? 1925 ( 1926 (((USR_UINTPTR)(addr))%4 == 0) ? 3 : 1927 (((USR_UINTPTR)(addr))%4 == 1) ? 1 : 1928 (((USR_UINTPTR)(addr))%4 == 2) ? -1 : 1929 (((USR_UINTPTR)(addr))%4 == 3) ? -3 : 1930 0) 1931 : 0; 1932 } 1933 1934 err_code_t merlin16_INTERNAL_rdblk_callback(void *arg, uint8_t byte_count, uint16_t data) { 1935 merlin16_INTERNAL_rdblk_callback_arg_t * const cast_arg = (merlin16_INTERNAL_rdblk_callback_arg_t *)arg; 1936 int endian_offset = 0; 1937 ESTM(endian_offset = merlin16_INTERNAL_get_endian_offset(cast_arg->mem_ptr)); 1938 *(cast_arg->mem_ptr + endian_offset) = data & 0xFF; 1939 cast_arg->mem_ptr++; 1940 if (byte_count == 2) { 1941 ESTM(endian_offset = merlin16_INTERNAL_get_endian_offset(cast_arg->mem_ptr)); 1942 *(cast_arg->mem_ptr + endian_offset) = data >> 8; 1943 cast_arg->mem_ptr++; 1944 } 1945 return (ERR_CODE_NONE); 1946 } 1947 1948 err_code_t merlin16_INTERNAL_rdblk_uc_generic_ram(srds_access_t *sa__, 1949 uint32_t block_addr, 1950 uint16_t block_size, 1951 uint16_t start_offset, 1952 uint16_t cnt, 1953 void *arg, 1954 err_code_t (*callback)(void *, uint8_t, uint16_t)) { 1955 uint32_t read_val = 0; 1956 uint8_t defecit = 0; 1957 uint32_t addr = block_addr + start_offset; 1958 1959 if (cnt == 0) { 1960 return (ERR_CODE_NONE); 1961 } 1962 1963 /* Check for bad start offset and block size. */ 1964 if (start_offset >= block_size) { 1965 return (ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 1966 } 1967 1968 while (cnt > 0) { 1969 /* Determine how many bytes to read before wrapping back to start of block. */ 1970 uint16_t block_cnt = SRDS_MIN(cnt, block_addr + block_size - addr); 1971 cnt -= block_cnt; 1972 1973 /* Set up the word reads. */ 1974 EFUN(wrc_micro_autoinc_rdaddr_en(1)); 1975 EFUN(wrc_micro_ra_rddatasize(0x1)); /* Select 16bit read datasize */ 1976 EFUN(wrc_micro_ra_rdaddr_msw(addr >> 16)); /* Upper 16bits of RAM address to be read */ 1977 EFUN(wrc_micro_ra_rdaddr_lsw(addr & 0xFFFE)); /* Lower 16bits of RAM address to be read */ 1978 1979 /* Read the leading byte, if starting at an odd address. */ 1980 if ((addr & 1) == 1) { 1981 ESTM(read_val |= ((rdc_micro_ra_rddata_lsw() >> 8) << defecit)); 1982 if (defecit == 8) { 1983 EFUN(callback(arg, 2, (uint16_t)read_val)); 1984 read_val = 0; 1985 } 1986 /* We just read a byte. This toggles the defecit from 0 to 8 or from 8 to 0. */ 1987 defecit ^= 8; 1988 --block_cnt; 1989 } 1990 1991 /* Read the whole words, and call the callback with two bytes at a time. */ 1992 while (block_cnt >= 2) { 1993 ESTM(read_val |= (rdc_micro_ra_rddata_lsw() << defecit)); 1994 EFUN(callback(arg, 2, (uint16_t)read_val)); 1995 read_val >>= 16; 1996 /* We just read two bytes. This preserves whatever defecit (8 or 0) is there. */ 1997 block_cnt -= 2; 1998 } 1999 2000 /* Read the trailing byte, if leftover after reading whole words. */ 2001 if (block_cnt > 0) { 2002 ESTM(read_val |= ((rdc_micro_ra_rddata_lsw() & 0xFF) << defecit)); 2003 if (defecit == 8) { 2004 EFUN(callback(arg, 2, (uint16_t)read_val)); 2005 read_val = 0; 2006 } 2007 /* We just read a byte. This toggles the defecit from 0 to 8 or from 8 to 0. */ 2008 defecit ^= 8; 2009 } 2010 addr = block_addr; 2011 } 2012 2013 /* If a final byte is left behind, then call the callback with it. */ 2014 if (defecit > 0) { 2015 EFUN(callback(arg, 1, (uint16_t)read_val)); 2016 } 2017 2018 return(ERR_CODE_NONE); 2019 } 2020 err_code_t merlin16_INTERNAL_rdblk_uc_generic_ram_descending(srds_access_t *sa__, 2021 uint32_t block_addr, 2022 uint16_t block_size, 2023 uint16_t start_offset, 2024 uint16_t cnt, 2025 void *arg, 2026 err_code_t (*callback)(void *, uint8_t, uint16_t)) { 2027 uint32_t read_val = 0; 2028 uint8_t defecit = 0; 2029 uint32_t addr = block_addr + start_offset; 2030 uint16_t configured_addr_msw = (addr >> 16) + 1; 2031 2032 if (cnt == 0) { 2033 return (ERR_CODE_NONE); 2034 } 2035 2036 /* Check for bad start offset and block size. */ 2037 if (start_offset >= block_size) { 2038 return (ERR_CODE_BAD_PTR_OR_INVALID_INPUT); 2039 } 2040 2041 EFUN(wrc_micro_autoinc_rdaddr_en(0)); 2042 EFUN(wrc_micro_ra_rddatasize(0x1)); /* Select 16bit read datasize */ 2043 2044 while (cnt > 0) { 2045 /* Determine how many bytes to read before wrapping back to end of block. */ 2046 uint16_t block_cnt = SRDS_MIN(cnt, start_offset+1); 2047 cnt -= block_cnt; 2048 2049 while (block_cnt > 0) { 2050 const uint16_t addr_msw = addr >> 16; 2051 uint16_t read_val2; 2052 if (addr_msw != configured_addr_msw) { 2053 EFUN(wrc_micro_ra_rdaddr_msw(addr_msw)); /* Upper 16bits of RAM address to be read */ 2054 configured_addr_msw = addr_msw; 2055 } 2056 2057 EFUN(wrc_micro_ra_rdaddr_lsw(addr & 0xFFFE)); /* Lower 16bits of RAM address to be read */ 2058 ESTM(read_val2 = rdc_micro_ra_rddata_lsw()); 2059 2060 if (((addr & 1) == 1) && (block_cnt >= 2)) { 2061 /* Reading two bytes. Since we're reading in descending address order, they 2062 * will be reversed before they are sent out. */ 2063 read_val |= ((((read_val2 & 0xFF) << 8) | (read_val2 >> 8)) << defecit); 2064 EFUN(callback(arg, 2, (uint16_t)read_val)); 2065 read_val >>= 16; 2066 /* We just read two bytes. This preserves whatever defecit (8 or 0) is there. */ 2067 block_cnt -= 2; 2068 addr -= 2; 2069 } else { 2070 if ((addr & 1) == 1) { 2071 /* Reading upper byte of word. */ 2072 read_val |= ((read_val2 >> 8) << defecit); 2073 } else { 2074 /* Reading lower byte of word. */ 2075 read_val |= ((read_val2 & 0xFF) << defecit); 2076 } 2077 if (defecit == 8) { 2078 EFUN(callback(arg, 2, (uint16_t)read_val)); 2079 read_val = 0; 2080 } 2081 /* We just read a byte. This toggles the defecit from 0 to 8 or from 8 to 0. */ 2082 defecit ^= 8; 2083 --block_cnt; 2084 --addr; 2085 } 2086 } 2087 2088 addr = block_addr + block_size - 1; 2089 start_offset = block_size - 1; 2090 } 2091 2092 /* If a final byte is left behind, then call the callback with it. */ 2093 if (defecit > 0) { 2094 EFUN(callback(arg, 1, (uint16_t)read_val)); 2095 } 2096 2097 return(ERR_CODE_NONE); 2098 } 2099 2100 uint8_t merlin16_INTERNAL_grp_idx_from_lane(uint8_t lane) { 2101 return(0); 2102 } 2103